import { createError, readBody, setResponseStatus } from "h3"
import { createHash, timingSafeEqual } from "node:crypto"
import {
  getSessionPayload,
  setAuthSession
} from "~/server/utils/auth"
import { assertLoginRateLimit, clearFailedLoginAttempts, registerFailedLoginAttempt } from "~/server/utils/login-rate-limit"
import { hashPassword, verifyPassword } from "~/server/utils/password"
import { prisma } from "~/server/utils/prisma"

interface LoginBody {
  identifier?: string
  email?: string
  username?: string
  password?: string
}

const normalizeEmail = (value: string) => value.trim().toLowerCase()

const safeEqual = (left: string, right: string) => {
  const leftHash = createHash("sha256").update(left).digest()
  const rightHash = createHash("sha256").update(right).digest()
  return timingSafeEqual(leftHash, rightHash)
}

const tryLegacyAdminLogin = async (identifier: string, password: string) => {
  const legacyUsername = process.env.AUTH_USERNAME?.trim()
  const legacyPassword = process.env.AUTH_PASSWORD

  if (!legacyUsername || !legacyPassword) {
    return null
  }

  if (!safeEqual(identifier, legacyUsername) || !safeEqual(password, legacyPassword)) {
    return null
  }

  const legacyAdminEmail = normalizeEmail(process.env.AUTH_ADMIN_EMAIL?.trim() || `${legacyUsername}@local.vitrio`)
  let legacyPasswordHash: string | null = null

  try {
    legacyPasswordHash = hashPassword(password)
  } catch {
    legacyPasswordHash = null
  }

  return prisma.user.upsert({
    where: {
      email: legacyAdminEmail
    },
    update: {
      role: "ADMIN",
      ...(legacyPasswordHash ? { passwordHash: legacyPasswordHash } : {})
    },
    create: {
      email: legacyAdminEmail,
      name: "Administrador",
      role: "ADMIN",
      passwordHash: legacyPasswordHash,
      emailVerifiedAt: new Date()
    }
  })
}

export default defineEventHandler(async (event) => {
  if (event.method !== "POST") {
    setResponseStatus(event, 405)
    return {
      error: true,
      message: "Metodo no permitido"
    }
  }

  assertLoginRateLimit(event)

  const body = await readBody<LoginBody>(event)
  const identifier = body.identifier?.trim() || body.email?.trim() || body.username?.trim() || ""
  const password = body.password || ""

  if (!identifier || !password) {
    throw createError({
      statusCode: 400,
      statusMessage: "Debes completar correo/usuario y contrasena"
    })
  }

  const legacyUser = await tryLegacyAdminLogin(identifier, password)

  if (legacyUser) {
    await setAuthSession(event, legacyUser.id)
    clearFailedLoginAttempts(event)
    return await getSessionPayload(event)
  }

  let user = null

  if (identifier.includes("@")) {
    user = await prisma.user.findUnique({
      where: {
        email: normalizeEmail(identifier)
      }
    })
  }

  if (!user?.passwordHash || !verifyPassword(password, user.passwordHash)) {
    registerFailedLoginAttempt(event)

    throw createError({
      statusCode: 401,
      statusMessage: "Credenciales invalidas"
    })
  }

  await setAuthSession(event, user.id)
  clearFailedLoginAttempts(event)

  return await getSessionPayload(event)
})
