import { NextResponse } from "next/server";

import { origemDoPedido } from "@/lib/digitais/servidor/acessos";
import {
  DURACAO_DA_SESSAO_S,
  TENTATIVAS_POR_CODIGO,
  clienteDosMembros,
  criarSessaoDoPortal,
  emailValido,
  resumoDoCodigo,
  resumosIguais,
} from "@/lib/digitais/servidor/membros";
import { COOKIE_DA_SESSAO } from "@/lib/loja/visao.server";
import { createAdminClient } from "@/lib/supabase-admin";

/*
 * Confere o código da área de membros e abre a sessão do portal do cliente.
 * O código vale uma vez; cinco erros e ele cai (é preciso pedir outro).
 */

const INVALIDO = "Código errado ou vencido. Confira o e-mail ou peça outro código.";

export async function POST(request: Request) {
  const semCache = { headers: { "cache-control": "no-store" } };
  try {
    const corpo = (await request.json().catch(() => null)) as { slug?: unknown; email?: unknown; codigo?: unknown } | null;
    const slug = typeof corpo?.slug === "string" ? corpo.slug.trim().toLowerCase().slice(0, 120) : "";
    const email = typeof corpo?.email === "string" ? corpo.email.trim().toLowerCase().slice(0, 254) : "";
    const codigo = typeof corpo?.codigo === "string" ? corpo.codigo.replace(/\D/g, "") : "";
    if (!slug || !emailValido(email) || codigo.length !== 6) return NextResponse.json({ error: INVALIDO }, { status: 400, ...semCache });

    const admin = createAdminClient();
    const { data: perfil } = await admin.from("profiles").select("id").eq("slug", slug).maybeSingle();
    const lojaId = String((perfil as { id?: string } | null)?.id || "");
    if (!lojaId) return NextResponse.json({ error: "Loja não encontrada." }, { status: 404, ...semCache });

    const cliente = await clienteDosMembros(admin, lojaId, email);
    if (!cliente) return NextResponse.json({ error: INVALIDO }, { status: 401, ...semCache });

    const { data: registros } = await admin
      .from("client_portal_codes")
      .select("id,codigo_hash,tentativas,expira_em")
      .eq("store_id", lojaId)
      .eq("client_id", cliente.id)
      .eq("tipo", "entrar")
      .is("usado_em", null)
      .gt("expira_em", new Date().toISOString())
      .order("criado_em", { ascending: false })
      .limit(1);
    const registro = ((registros ?? []) as Array<{ id: string; codigo_hash: string; tentativas: number }>)[0];
    if (!registro) return NextResponse.json({ error: INVALIDO }, { status: 401, ...semCache });

    if (!resumosIguais(registro.codigo_hash, resumoDoCodigo(cliente.id, codigo))) {
      const tentativas = (Number(registro.tentativas) || 0) + 1;
      await admin
        .from("client_portal_codes")
        .update({ tentativas, ...(tentativas >= TENTATIVAS_POR_CODIGO ? { usado_em: new Date().toISOString() } : {}) })
        .eq("id", registro.id);
      return NextResponse.json(
        { error: tentativas >= TENTATIVAS_POR_CODIGO ? "Muitas tentativas. Peça um novo código." : INVALIDO },
        { status: 401, ...semCache }
      );
    }

    /* Queima o código ANTES de abrir a sessão: dois envios juntos não entram duas vezes. */
    const { data: queimado } = await admin
      .from("client_portal_codes")
      .update({ usado_em: new Date().toISOString() })
      .eq("id", registro.id)
      .is("usado_em", null)
      .select("id")
      .maybeSingle();
    if (!queimado) return NextResponse.json({ error: INVALIDO }, { status: 401, ...semCache });

    const origem = origemDoPedido(request);
    const sessao = await criarSessaoDoPortal(admin, { lojaId, clienteId: cliente.id, ip: origem.ip, navegador: origem.navegador });
    const resposta = NextResponse.json({ ok: true }, semCache);
    resposta.cookies.set({
      name: COOKIE_DA_SESSAO,
      value: sessao.token,
      httpOnly: true,
      secure: process.env.NODE_ENV === "production",
      sameSite: "lax",
      path: "/",
      maxAge: DURACAO_DA_SESSAO_S,
    });
    return resposta;
  } catch (erro) {
    console.error("[digitais] membros/entrar", erro);
    return NextResponse.json({ error: "Não foi possível entrar agora. Tente de novo." }, { status: 500, ...semCache });
  }
}
