import { NextResponse } from "next/server";
import { and, eq, isNull, sql } from "drizzle-orm";
import { db } from "@/db";
import { authUsers, userEmails, userPhones } from "@/db/schema";
import { createSession, currentUser, SESSION_COOKIE } from "@/lib/auth";
import { checkRateLimit, readJson } from "@/lib/api-security";
import { EmailVerificationError, normalizeEmail, upsertUserEmail, verifyEmailChallenge } from "@/lib/email-pin";
import { getVerifiedPhone } from "@/lib/sms-pin";

function sessionCookie(token: string) {
  return { httpOnly: true, sameSite: "lax" as const, secure: process.env.NODE_ENV === "production", maxAge: 30 * 24 * 60 * 60, path: "/" };
}

/**
 * Email-PIN verify (§10.2 «email link/PIN»): with a session it attaches the
 * address to a phone-backed cabinet; without a session it can only log into
 * an existing cabinet that already owns this verified address.
 */
export async function POST(request: Request) {
  try {
    checkRateLimit(request, "email-verify", 20, 10 * 60 * 1000);
    const body = await readJson<{ email?: unknown; code?: unknown }>(request, 4 * 1024);
    const current = await currentUser();
    const email = normalizeEmail(typeof body.email === "string" ? body.email : "", current ? "strip" : "reject");
    const code = typeof body.code === "string" ? body.code.replace(/\D/g, "") : "";
    if (!email || code.length < 4 || code.length > 10) return NextResponse.json({ error: "bad_request", message: "Проверьте адрес и код." }, { status: 400 });
    await verifyEmailChallenge({ email, pin: code });

    if (current) {
      if (!(await getVerifiedPhone(current.id))) return NextResponse.json({ error: "phone_required", message: "Сначала подтвердите номер телефона." }, { status: 403 });
      await upsertUserEmail(current.id, email);
      return NextResponse.json({ ok: true, attached: true }, { headers: { "Cache-Control": "no-store" } });
    }
    if (!db) return NextResponse.json({ error: "service_unavailable" }, { status: 503 });
    const [existing] = await db.select({ email: userEmails, user: authUsers }).from(userEmails).innerJoin(authUsers, eq(authUsers.id, userEmails.userId)).innerJoin(userPhones, and(eq(userPhones.userId, userEmails.userId), isNull(userPhones.archivedAt), sql`${userPhones.verifiedAt} IS NOT NULL`)).where(and(eq(userEmails.email, email), isNull(userEmails.archivedAt), sql`${userEmails.verifiedAt} IS NOT NULL`, eq(authUsers.state, "active"))).limit(1);
    if (!existing) throw new EmailVerificationError("Не удалось выполнить вход.");
    const userId = existing.user.id;
    const token = await createSession(userId);
    const response = NextResponse.json({ ok: true, login: true }, { headers: { "Cache-Control": "no-store" } });
    response.cookies.set(SESSION_COOKIE, token, sessionCookie(token));
    return response;
  } catch (error) {
    if (error instanceof EmailVerificationError) return NextResponse.json({ error: "verify_failed", message: error.message }, { status: 400 });
    return NextResponse.json({ error: "verify_failed", message: "Не удалось проверить код. Попробуйте позже." }, { status: 503 });
  }
}
