import { Metadata } from "next"
import { hash } from "bcryptjs"
import { createId } from "@paralleldrive/cuid2"
import { eq } from "drizzle-orm"

import type { ActionState } from "@/shared/types/action-state"
import { RegisterForm } from "@/modules/auth/components/register-form"

export const metadata: Metadata = {
  title: "Register - Next_Edu",
  description: "Create an account",
}

const ADULT_AGE = 18

const normalizeBcryptHash = (value: string) => {
  if (value.startsWith("$2")) return value
  if (value.startsWith("$")) return `$2b${value}`
  return `$2b$${value}`
}

function calcAge(birth: string): number | null {
  if (!birth) return null
  const birthDate = new Date(birth)
  if (Number.isNaN(birthDate.getTime())) return null
  const now = new Date()
  let age = now.getFullYear() - birthDate.getFullYear()
  const monthDiff = now.getMonth() - birthDate.getMonth()
  if (monthDiff < 0 || (monthDiff === 0 && now.getDate() < birthDate.getDate())) {
    age -= 1
  }
  return age >= 0 ? age : null
}

export default function RegisterPage() {
  async function registerAction(formData: FormData): Promise<ActionState> {
    "use server"

    const databaseUrl = process.env.DATABASE_URL
    if (!databaseUrl) return { success: false, message: "DATABASE_URL 未配置" }

    try {
      const [{ db }, { roles, users, usersToRoles }] = await Promise.all([
        import("@/shared/db"),
        import("@/shared/db/schema"),
      ])

      const name = String(formData.get("name") ?? "").trim()
      const email = String(formData.get("email") ?? "").trim().toLowerCase()
      const password = String(formData.get("password") ?? "")
      const birthDateRaw = String(formData.get("birthDate") ?? "").trim()
      const guardianName = String(formData.get("guardianName") ?? "").trim()
      const guardianPhone = String(formData.get("guardianPhone") ?? "").trim()
      const guardianRelation = String(formData.get("guardianRelation") ?? "").trim()

      if (!email) return { success: false, message: "请输入邮箱" }
      if (!password) return { success: false, message: "请输入密码" }
      if (password.length < 6) return { success: false, message: "密码至少 6 位" }

      const age = calcAge(birthDateRaw)
      const isMinor = age !== null && age < ADULT_AGE
      if (isMinor) {
        if (!guardianName) return { success: false, message: "未成年人须填写监护人姓名" }
        if (!guardianPhone) return { success: false, message: "未成年人须填写监护人电话" }
        if (!guardianRelation) return { success: false, message: "未成年人须选择监护人关系" }
      }

      const existing = await db.query.users.findFirst({
        where: eq(users.email, email),
        columns: { id: true },
      })
      if (existing) return { success: false, message: "该邮箱已注册" }

      const hashedPassword = normalizeBcryptHash(await hash(password, 10))
      const userId = createId()
      await db.insert(users).values({
        id: userId,
        name: name.length ? name : null,
        email,
        password: hashedPassword,
        birthDate: birthDateRaw ? new Date(birthDateRaw) : null,
        age: age ?? null,
        guardianName: guardianName || null,
        guardianPhone: guardianPhone || null,
        guardianRelation: guardianRelation || null,
        consentAcceptedAt: new Date(),
      })
      const roleRow = await db.query.roles.findFirst({
        where: eq(roles.name, "student"),
        columns: { id: true },
      })
      if (!roleRow) {
        await db.insert(roles).values({ name: "student" })
      }
      const resolvedRole = roleRow
        ?? (await db.query.roles.findFirst({ where: eq(roles.name, "student"), columns: { id: true } }))
      if (resolvedRole?.id) {
        await db.insert(usersToRoles).values({ userId, roleId: resolvedRole.id })
      }

      return { success: true, message: "账户创建成功" }
    } catch (error) {
      const isProd = process.env.NODE_ENV === "production"

      const anyErr = error as unknown as {
        code?: string
        message?: string
        sqlMessage?: string
        cause?: unknown
      }

      const cause1 = anyErr?.cause as
        | { code?: string; message?: string; sqlMessage?: string; cause?: unknown }
        | undefined
      const cause2 = (cause1?.cause ?? undefined) as
        | { code?: string; message?: string; sqlMessage?: string }
        | undefined

      const code = String(cause2?.code ?? cause1?.code ?? anyErr?.code ?? "").trim()
      const msg = String(
        cause2?.sqlMessage ??
          cause1?.sqlMessage ??
          anyErr?.sqlMessage ??
          cause2?.message ??
          cause1?.message ??
          anyErr?.message ??
          ""
      ).trim()
      const msgLower = msg.toLowerCase()

      if (
        code === "ER_DUP_ENTRY" ||
        msgLower.includes("duplicate") ||
        msgLower.includes("unique")
      ) {
        return { success: false, message: "该邮箱已注册" }
      }

      if (
        code === "ER_NO_SUCH_TABLE" ||
        msgLower.includes("doesn't exist") ||
        msgLower.includes("unknown column")
      ) {
        return {
          success: false,
          message: "数据库未初始化或未迁移，请先运行 npm run db:migrate",
        }
      }

      if (code === "ER_ACCESS_DENIED_ERROR") {
        return { success: false, message: "数据库账号/权限错误，请检查 DATABASE_URL" }
      }

      if (code === "ECONNREFUSED" || code === "ENOTFOUND") {
        return { success: false, message: "数据库连接失败，请检查 DATABASE_URL 与网络" }
      }

      if (!isProd && msg) {
        return { success: false, message: `创建账户失败：${msg}` }
      }

      return { success: false, message: "创建账户失败，请稍后重试" }
    }
  }

  return <RegisterForm registerAction={registerAction} />
}
