import NextAuth from "next-auth"
import Credentials from "next-auth/providers/credentials"
import { prisma } from "./prisma"
import bcrypt from "bcryptjs"
import { logger } from "./logger"

// Lazy check for NEXTAUTH_SECRET - only validate when actually needed
// This prevents build-time errors when the secret isn't available
function getNextAuthSecret(): string {
  const secret = process.env.NEXTAUTH_SECRET
  if (!secret) {
    // Always throw at runtime - this is a critical configuration error
    throw new Error("NEXTAUTH_SECRET is not set. Define it to enable authentication.")
  }
  return secret
}

// Determine if we should use secure cookies based on AUTH_URL/NEXTAUTH_URL
// Auth.js v5 derives this from the origin it detects, so we need to be explicit
const authUrl = process.env.AUTH_URL || process.env.NEXTAUTH_URL || "http://localhost:3000"
const isHttp = authUrl.startsWith("http://")

export const { handlers, auth, signIn, signOut } = NextAuth({
  // trustHost must be true for NextAuth v5 to work, even on localhost
  trustHost: true,
  debug: process.env.NODE_ENV !== "production",
  basePath: "/api/auth",
  providers: [
    Credentials({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" }
      },
      async authorize(credentials) {
        try {
          if (!credentials?.email || !credentials?.password) {
            return null
          }

          const email = credentials.email as string
          const password = credentials.password as string

          const user = await prisma.user.findUnique({
            where: { email }
          })

          if (!user || !user.passwordHash) {
            return null
          }

          const isValid = await bcrypt.compare(password, user.passwordHash)

          if (!isValid) {
            return null
          }

          return {
            id: user.id,
            email: user.email,
            name: user.name,
            role: user.role,
          }
        } catch (err) {
          logger.error("Auth authorize error", err instanceof Error ? err : new Error(String(err)))
          return null
        }
      }
    })
  ],
  callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token.id = user.id
        token.role = (user as { role: string }).role
        token.email = user.email
        token.name = user.name
        // DEBUG level: only logs in development or when LOG_LEVEL=DEBUG
        logger.debug("JWT callback: user added to token", { 
          userId: user.id, 
          email: user.email 
        })
      } else {
        // DEBUG level: token refresh (normal operation, only log in debug mode)
        logger.debug("JWT callback: token refresh", { 
          hasToken: !!token,
          tokenId: token?.id,
          tokenEmail: token?.email,
        })
      }
      return token
    },
    async session({ session, token }) {
      // Always ensure session.user exists when token exists
      if (token && (token.id || token.email)) {
        session.user = {
          ...session.user,
          id: token.id as string,
          email: (token.email as string) || session.user?.email || "",
          name: (token.name as string) || session.user?.name || "",
          role: token.role as string,
        }
        // DEBUG level: session creation is normal operation, only log in debug mode
        logger.debug("Session callback: session created", { 
          userId: token.id, 
          email: token.email,
          userRole: token.role,
        })
      } else {
        // WARN level: token missing/invalid is a warning condition
        logger.warn("Session callback: token missing or invalid", { 
          hasToken: !!token,
          hasSession: !!session,
          tokenId: token?.id,
          tokenEmail: token?.email
        })
        // Return session even if token is invalid - NextAuth will handle validation
      }
      // Explicitly return session to ensure it's returned
      return session
    }
  },
  pages: {
    signIn: "/login",
  },
  session: {
    strategy: "jwt",
    maxAge: 30 * 24 * 60 * 60, // 30 days
  },
  // Explicitly configure cookies for HTTP (localhost)
  // For HTTPS, let Auth.js defaults handle it (prefixes + Secure)
  cookies: isHttp
    ? {
        // localhost / pure HTTP: no prefixes, no Secure
        sessionToken: {
          name: "authjs.session-token",
          options: {
            httpOnly: true,
            sameSite: "lax",
            path: "/",
            secure: false,
          },
        },
        csrfToken: {
          name: "authjs.csrf-token",
          options: {
            httpOnly: true,
            sameSite: "lax",
            path: "/",
            secure: false,
          },
        },
        callbackUrl: {
          name: "authjs.callback-url",
          options: {
            httpOnly: true,
            sameSite: "lax",
            path: "/",
            secure: false,
          },
        },
      }
    : undefined, // Let Auth.js defaults handle HTTPS envs (prefixes + Secure)
  secret: getNextAuthSecret(),
})
