import type { NextApiRequest, NextApiResponse } from 'next'
import crypto from 'crypto'
import { findUserByEmail, getUserById } from './[...nextauth]'
import { AuthResponse, VerifyEmailInput, TokenPayload } from '@/lib/auth/types'
import { withRateLimit } from '@/lib/auth/withAuth'

// In-memory token store (will be replaced with database in Agent 2)
const emailVerificationTokens = new Map<string, TokenPayload>()

// Token expiry: 24 hours
const TOKEN_EXPIRY_MS = 24 * 60 * 60 * 1000

export function generateVerificationToken(userId: string, email: string): string {
  const token = crypto.randomBytes(32).toString('hex')
  const payload: TokenPayload = {
    userId,
    email,
    type: 'email_verification',
    expiresAt: Date.now() + TOKEN_EXPIRY_MS,
  }
  emailVerificationTokens.set(token, payload)
  return token
}

function verifyToken(token: string): TokenPayload | null {
  const payload = emailVerificationTokens.get(token)
  if (!payload) return null
  if (Date.now() > payload.expiresAt) {
    emailVerificationTokens.delete(token)
    return null
  }
  return payload
}

function invalidateToken(token: string): void {
  emailVerificationTokens.delete(token)
}

async function handler(
  req: NextApiRequest,
  res: NextApiResponse<AuthResponse>
) {
  // Handle GET request (verify token from email link)
  if (req.method === 'GET') {
    const { token } = req.query

    if (!token || typeof token !== 'string') {
      return res.status(400).json({
        success: false,
        message: 'Verification token is required',
        error: 'VALIDATION_ERROR',
      })
    }

    const payload = verifyToken(token)
    if (!payload) {
      return res.status(400).json({
        success: false,
        message: 'Invalid or expired verification token',
        error: 'INVALID_TOKEN',
      })
    }

    const user = getUserById(payload.userId)
    if (!user) {
      return res.status(400).json({
        success: false,
        message: 'User not found',
        error: 'USER_NOT_FOUND',
      })
    }

    // Mark email as verified
    user.emailVerified = new Date()

    // Invalidate the used token
    invalidateToken(token)

    console.log(`Email verified for user: ${user.email}`)

    // Redirect to success page or return success response
    if (req.headers.accept?.includes('text/html')) {
      res.redirect(302, '/auth/email-verified')
      return
    }

    return res.status(200).json({
      success: true,
      message: 'Email verified successfully',
    })
  }

  // Handle POST request (resend verification email)
  if (req.method === 'POST') {
    const { email } = req.body

    if (!email) {
      return res.status(400).json({
        success: false,
        message: 'Email is required',
        error: 'VALIDATION_ERROR',
      })
    }

    const user = findUserByEmail(email)
    if (!user) {
      // Return success to prevent email enumeration
      return res.status(200).json({
        success: true,
        message: 'If an account exists with this email, a verification link has been sent.',
      })
    }

    if (user.emailVerified) {
      return res.status(400).json({
        success: false,
        message: 'Email is already verified',
        error: 'ALREADY_VERIFIED',
      })
    }

    // Generate new verification token
    const verificationToken = generateVerificationToken(user.id, user.email)

    // Build verification URL
    const baseUrl = process.env.NEXTAUTH_URL || `http://${req.headers.host}`
    const verifyUrl = `${baseUrl}/api/auth/verify-email?token=${verificationToken}`

    // TODO: Send verification email (will be implemented with Agent 8 - Notifications)
    if (process.env.NODE_ENV === 'development') {
      console.log(`Email verification link for ${email}: ${verifyUrl}`)
    }

    return res.status(200).json({
      success: true,
      message: 'If an account exists with this email, a verification link has been sent.',
    })
  }

  return res.status(405).json({
    success: false,
    message: 'Method not allowed',
    error: 'Only GET and POST requests are accepted',
  })
}

// Apply rate limiting: 3 requests per minute per IP
export default withRateLimit(handler, {
  limit: 3,
  windowMs: 60000,
})
