import NextAuth from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import { prismaAuth } from '@/lib/db';
import bcrypt from 'bcryptjs';

export const { handlers, signIn, signOut, auth } = NextAuth({
  secret: process.env.NEXTAUTH_SECRET,
  trustHost: true, // Trust all hosts (for development/internal network)
  providers: [
    CredentialsProvider({
      name: 'Credentials',
      credentials: {
        email: { label: 'Email', type: 'email' },
        password: { label: 'Password', type: 'password' },
      },
      async authorize(credentials) {
        try {
          if (!credentials?.email || !credentials?.password) {
            console.log('[AUTH] Missing credentials');
            return null;
          }

          console.log('[AUTH] Attempting to find user:', credentials.email);
          const user = await prismaAuth.user.findUnique({
            where: { email: credentials.email as string },
            select: {
              id: true,
              email: true,
              name: true,
              passwordHash: true,
              isAdmin: true,
              hasWriteAccess: true,
              emailVerified: true,
              isActive: true,
            },
          });

          if (!user) {
            console.log('[AUTH] User not found:', credentials.email);
            return null;
          }

          console.log('[AUTH] User found, checking password...');
          const isPasswordValid = await bcrypt.compare(
            credentials.password as string,
            user.passwordHash
          );

          if (!isPasswordValid) {
            console.log('[AUTH] Invalid password for user:', credentials.email);
            return null;
          }

          // Check if email is verified
          if (!user.emailVerified) {
            console.log('[AUTH] Email not verified for user:', credentials.email);
            return null; // Return null to indicate failed login
          }

          // Check if user is active (treat null/undefined as true)
          if (user.isActive === false) {
            console.log('[AUTH] User is inactive:', credentials.email);
            return null; // Return null to indicate failed login
          }

          console.log('[AUTH] Login successful for:', credentials.email);

          return {
            id: user.id.toString(),
            email: user.email,
            name: user.name || undefined,
            isAdmin: user.isAdmin,
            hasWriteAccess: user.hasWriteAccess,
          };
        } catch (error: any) {
          console.error('[AUTH] Error during authorization:', error);
          return null;
        }
      },
    }),
  ],
  pages: {
    signIn: '/login',
    signOut: '/',
  },
  session: {
    strategy: 'jwt',
    maxAge: 24 * 60 * 60, // 24 hours in seconds
    updateAge: 1 * 60 * 60, // Refresh session every 1 hour (more frequent validation)
  },
  jwt: {
    maxAge: 24 * 60 * 60, // 24 hours in seconds
  },
  callbacks: {
    async jwt({ token, user, trigger }) {
      // Set expiration time when user first logs in
      if (user) {
        token.id = user.id;
        token.email = user.email;
        token.isAdmin = user.isAdmin;
        token.hasWriteAccess = user.hasWriteAccess;
        token.exp = Math.floor(Date.now() / 1000) + (24 * 60 * 60); // 24 hours from now
      }
      
      // Refresh user data from database on token refresh to get latest hasWriteAccess and isActive
      // This ensures permissions are up-to-date even if granted after login
      if (token.email && !user) {
        try {
          const dbUser = await prismaAuth.user.findUnique({
            where: { email: token.email as string },
            select: {
              id: true,
              email: true,
              isAdmin: true,
              hasWriteAccess: true,
              isActive: true,
            },
          });
          
          if (dbUser) {
            // Check if user is still active (treat null/undefined as true)
            if (dbUser.isActive === false) {
              // User was deactivated, invalidate token
              return null as any;
            }
            token.id = dbUser.id.toString();
            token.isAdmin = dbUser.isAdmin;
            token.hasWriteAccess = dbUser.hasWriteAccess;
          }
        } catch (error) {
          console.error('[AUTH] Error refreshing user data:', error);
          // Continue with existing token data if refresh fails
        }
      }
      
      return token;
    },
    async session({ session, token }) {
      // If token is null or expired, return null session to force logout
      if (!token || (token.exp && token.exp < Math.floor(Date.now() / 1000))) {
        return null as any;
      }
      
      if (session.user) {
        session.user.id = token.id as string;
        session.user.email = token.email as string;
        session.user.isAdmin = token.isAdmin as boolean;
        session.user.hasWriteAccess = token.hasWriteAccess as boolean;
      }
      return session;
    },
  },
});

export const { GET, POST } = handlers;

