/**
 * POST /api/admin/auth/login — foundation-auth-rbac (Task 13).
 *
 * Verifies the admin password (PBKDF2). Branches on TOTP enrollment:
 *   - totp_secret NULL -> { requires_totp_setup: true, setup_token }
 *   - else             -> { requires_totp: true, temp_admin_token }
 * Both tokens are short-lived signed JWTs scoped by `purpose`. Admin sessions
 * carry no tid and no tenant permissions. Public route; Origin checked inline.
 */
import { Hono } from 'hono'
import { signSignedToken, verifyPassword } from '@zync/auth'
import { createDb, findAdminByEmail } from '@zync/db/queries'
import type { AppEnv } from '../../../types'
import { adminLoginSchema } from '../../../schemas/admin-auth'
import { isLockedOut, recordFailure, clearFailures } from '../../../lib/login-throttle'

import { getAdminOrigins } from '../../../lib/origins'
import { withDoHash } from '../../../lib/password-hash-do'

const SETUP_TOKEN_TTL = 60 * 15 // 15 min to complete enrollment
const TEMP_TOKEN_TTL = 60 * 10 // 10 min to complete TOTP step

export const adminLoginRoute = new Hono<AppEnv>()

adminLoginRoute.post('/login', async (c) => {
  const origin = c.req.header('Origin')
  const allowedOrigins = getAdminOrigins({
    environment: (c.env as { ENVIRONMENT?: string }).ENVIRONMENT,
  })
  if (!origin || !allowedOrigins.has(origin)) {
    return c.json({ error: 'Forbidden: invalid Origin' }, 403)
  }

  const ip = c.req.header('CF-Connecting-IP') ?? 'unknown'
  const rl = await (async () => { try { const _r = await c.env.RATE_LIMITER_AUTH?.limit({ key: `admin_login:${ip}` }); return _r ?? { success: true }; } catch { return { success: true }; } })()
  if (!rl.success) return c.json({ error: 'Too many requests' }, 429)

  const parsed = adminLoginSchema.safeParse(await c.req.json())
  if (!parsed.success) return c.json({ error: 'Invalid request' }, 400)
  const { email, password } = parsed.data

  if (await isLockedOut(c.env, `admin:${email}`)) {
    return c.json({ error: 'Account temporarily locked' }, 429)
  }

  const db = createDb(c.env)
  const admin = await findAdminByEmail(db, email)
  if (!admin || !(await verifyPassword(password, admin.passwordHash, withDoHash(c.env)))) {
    await recordFailure(c.env, `admin:${email}`)
    return c.json({ error: 'Invalid email or password' }, 401)
  }
  await clearFailures(c.env, `admin:${email}`)

  if (!admin.totpSecret) {
    const setupToken = await signSignedToken(
      { sub: admin.id, purpose: 'admin_totp_setup' },
      c.env.JWT_SECRET,
      SETUP_TOKEN_TTL,
    )
    return c.json({ requires_totp_setup: true, setup_token: setupToken }, 200)
  }

  const tempToken = await signSignedToken(
    { sub: admin.id, purpose: 'admin_totp_verify' },
    c.env.JWT_SECRET,
    TEMP_TOKEN_TTL,
  )
  return c.json({ requires_totp: true, temp_admin_token: tempToken }, 200)
})
