import "server-only"

import { eq } from "drizzle-orm"

import { db } from "@/shared/db"
import { users } from "@/shared/db/schema"
import {
  getBackupCodesHashed,
  getTotpSecret,
  getTwoFactorEnabled,
  setBackupCodesHashed,
} from "@/modules/settings/data-access-two-factor"
import {
  consumeBackupCode,
  verifyBackupCode,
  verifyTotpCode,
} from "@/modules/settings/lib/totp"

/**
 * Auth 模块 2FA 服务（P0-2 解耦修复）
 *
 * 此服务将登录流程中需要的 2FA 校验逻辑从 `modules/settings/actions-security`
 * 抽取到 `modules/auth/services`，使 `auth.ts` 不再直接依赖 settings 模块的
 * Server Actions，符合三层架构与跨模块通过 data-access 通信的规则。
 *
 * 依赖关系：
 * - auth.ts → modules/auth/services/two-factor-service（同模块）
 * - two-factor-service → modules/settings/data-access-two-factor（跨模块 data-access，允许）
 * - two-factor-service → modules/settings/lib/totp（跨模块工具库，允许）
 */

export interface TwoFactorLoginResult {
  /** 用户是否启用了 2FA */
  required: boolean
  /** 提供的 token 是否有效（未启用时视为有效） */
  valid: boolean
}

export interface TwoFactorPreflightResult {
  /** 是否需要 2FA（用户不存在时返回 false 以防邮箱枚举） */
  required: boolean
}

/**
 * 登录时校验 2FA：检查用户是否启用 2FA，并校验提供的一次性码或备份码。
 *
 * 返回值：
 * - `{ required: true }`  — 用户启用了 2FA 但未提供 token，登录流程应要求输入
 * - `{ required: false, valid: true }`  — 未启用 2FA，或已提供有效 token
 * - `{ required: false, valid: false }`  — 启用了 2FA 且提供的 token 无效
 *
 * 此函数不使用 requirePermission（登录时还未建立会话），
 * 由 `auth.ts` 的 authorize 回调直接调用。
 */
export async function verifyTwoFactorForLogin(params: {
  userId: string
  token?: string
}): Promise<TwoFactorLoginResult> {
  const { userId, token } = params

  const enabled = await getTwoFactorEnabled(userId)
  if (!enabled) {
    return { required: false, valid: true }
  }

  if (!token) {
    return { required: true, valid: false }
  }

  const secret = await getTotpSecret(userId)
  const backupHashed = await getBackupCodesHashed(userId)

  // 先尝试 TOTP
  if (secret && verifyTotpCode(token, secret)) {
    return { required: true, valid: true }
  }

  // 再尝试备份码
  if (backupHashed) {
    const idx = await verifyBackupCode(token, backupHashed)
    if (idx >= 0) {
      const nextHashed = await consumeBackupCode(backupHashed, idx)
      await setBackupCodesHashed(userId, nextHashed)
      return { required: true, valid: true }
    }
  }

  return { required: true, valid: false }
}

/**
 * 预检：根据邮箱查询用户是否启用了 2FA。
 *
 * 登录表单在首次提交前可调用此函数，若返回 `required=true` 则先展示
 * 2FA 验证码输入框。
 *
 * 为防止邮箱枚举攻击，无论用户是否存在都返回 `required=false`
 * （不存在则视为未启用）。
 */
export async function preflightTwoFactorByEmail(
  email: string
): Promise<TwoFactorPreflightResult> {
  try {
    const normalized = email.trim().toLowerCase()
    if (!normalized) return { required: false }

    const [user] = await db
      .select({ id: users.id })
      .from(users)
      .where(eq(users.email, normalized))
      .limit(1)

    if (!user) return { required: false }

    const enabled = await getTwoFactorEnabled(user.id)
    return { required: enabled }
  } catch {
    return { required: false }
  }
}
