import { NextAuthOptions } from 'next-auth'
import CredentialsProvider from 'next-auth/providers/credentials'
import bcrypt from 'bcryptjs'
import { prisma } from './prisma'

const loginAttempts = new Map<string, { count: number; lockedUntil?: number }>()
const MAX_LOGIN_ATTEMPTS = 5
const LOCK_DURATION = 30 * 60 * 1000

function checkAccountLock(email: string): string | null {
  const entry = loginAttempts.get(email)
  if (!entry) return null
  if (entry.lockedUntil && Date.now() < entry.lockedUntil) {
    const mins = Math.ceil((entry.lockedUntil - Date.now()) / 60000)
    return `Account locked. Try again in ${mins} minutes.`
  }
  if (entry.lockedUntil && Date.now() >= entry.lockedUntil) {
    loginAttempts.delete(email)
  }
  return null
}

function recordFailedLogin(email: string) {
  const entry = loginAttempts.get(email) || { count: 0 }
  entry.count++
  if (entry.count >= MAX_LOGIN_ATTEMPTS) {
    entry.lockedUntil = Date.now() + LOCK_DURATION
  }
  loginAttempts.set(email, entry)
}

function clearLoginAttempts(email: string) {
  loginAttempts.delete(email)
}

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 are required')
        }

        const email = credentials.email.toLowerCase().trim()

        const lockMessage = checkAccountLock(email)
        if (lockMessage) throw new Error(lockMessage)

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

        if (!user || !user.isActive) {
          await bcrypt.hash(credentials.password, 12)
          recordFailedLogin(email)
          throw new Error('Invalid credentials')
        }

        const isPasswordValid = await bcrypt.compare(credentials.password, user.passwordHash)
        if (!isPasswordValid) {
          recordFailedLogin(email)
          throw new Error('Invalid credentials')
        }

        clearLoginAttempts(email)

        await prisma.user.update({
          where: { id: user.id },
          data: { lastLoginAt: new Date() },
        })

        return {
          id: user.id,
          email: user.email,
          name: user.name,
          role: user.role,
        }
      },
    }),
  ],
  callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token['uid'] = user.id
        token['urole'] = (user as any).role
      }
      return token
    },
    async session({ session, token }) {
      if (session.user) {
        const u = session.user as any
        u.id = token['uid']
        u.role = token['urole']
      }
      return session
    },
  },
  pages: {
    signIn: '/dmcify/login',
  },
  session: {
    strategy: 'jwt',
    maxAge: 8 * 60 * 60,
  },
  secret: process.env.NEXTAUTH_SECRET,
}
