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

export const authOptions: NextAuthOptions = {
  providers: [
    CredentialsProvider({
      name: 'Credentials',
      credentials: {
        email: { label: 'Email', type: 'email' },
        password: { label: 'Password', type: 'password' },
      },
      async authorize(credentials) {
        if (!credentials?.email || !credentials?.password) {
          throw new Error('Email and password required');
        }

        const user = await prisma.gfsUser.findUnique({
          where: { email: credentials.email.toLowerCase() },
          include: {
            roles: {
              include: {
                role: {
                  include: {
                    permissions: {
                      include: { permission: true },
                    },
                  },
                },
              },
            },
          },
        });

        if (!user) {
          throw new Error('Invalid email or password');
        }

        // Check if account is locked
        if (user.lockedUntil && user.lockedUntil > new Date()) {
          throw new Error('Account is locked. Try again later.');
        }

        // Check if account is active
        if (user.status !== 'active') {
          throw new Error('Account is not active');
        }

        // Verify password
        if (!user.passwordHash) {
          throw new Error('Password not set. Please contact admin.');
        }

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

        if (!isValid) {
          // Increment failed attempts
          const failedAttempts = user.failedAttempts + 1;
          const lockThreshold = 5;

          await prisma.gfsUser.update({
            where: { id: user.id },
            data: {
              failedAttempts,
              lockedUntil: failedAttempts >= lockThreshold 
                ? new Date(Date.now() + 30 * 60 * 1000) // Lock for 30 minutes
                : null,
            },
          });

          // Log security event
          await prisma.securityEvent.create({
            data: {
              type: 'failed_login',
              severity: failedAttempts >= lockThreshold ? 'high' : 'low',
              userId: user.id,
              description: `Failed login attempt (${failedAttempts})`,
              details: { email: credentials.email },
            },
          });

          throw new Error('Invalid email or password');
        }

        // Reset failed attempts and update last login
        await prisma.gfsUser.update({
          where: { id: user.id },
          data: {
            failedAttempts: 0,
            lockedUntil: null,
            lastLogin: new Date(),
          },
        });

        // Extract permissions from roles
        const permissions: string[] = [];
        const roleNames: string[] = [];

        user.roles.forEach((ur: any) => {
          roleNames.push(ur.role.name);
          ur.role.permissions.forEach((rp: any) => {
            const perm = `${rp.permission.resource}:${rp.permission.action}:${rp.permission.scope}`;
            if (!permissions.includes(perm)) {
              permissions.push(perm);
            }
          });
        });

        // Log successful login
        await prisma.auditLog.create({
          data: {
            userId: user.id,
            action: 'login',
            resource: 'session',
            details: { method: 'credentials' },
            success: true,
          },
        });

        return {
          id: user.id,
          email: user.email,
          name: user.name ?? undefined,
          avatar: user.avatar ?? undefined,
          department: user.department ?? undefined,
          title: user.title ?? undefined,
          roles: roleNames,
          permissions,
        };
      },
    }),
  ],
  session: {
    strategy: 'jwt',
    maxAge: 8 * 60 * 60, // 8 hours
  },
  pages: {
    signIn: '/login',
    error: '/login',
  },
  callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token.id = user.id;
        token.roles = user.roles;
        token.permissions = user.permissions;
        token.department = user.department;
        token.title = user.title;
        token.avatar = user.avatar;
      }
      return token;
    },
    async session({ session, token }) {
      if (session.user) {
        session.user.id = token.id as string;
        session.user.roles = token.roles as string[];
        session.user.permissions = token.permissions as string[];
        session.user.department = token.department as string | undefined;
        session.user.title = token.title as string | undefined;
        session.user.avatar = token.avatar as string | undefined;
      }
      return session;
    },
  },
};
