import { NextResponse } from "next/server";
import { createClient as createSupabaseClient } from "@supabase/supabase-js";
import { buildPublicUrl } from "@/lib/request-origin";
import { origemDaRequisicao, tentativaPermitida } from "@/lib/limite-de-tentativas";

function buildLoginRedirect(request: Request, slug: string, params: Record<string, string | null | undefined>) {
  const url = buildPublicUrl(request, `/${slug}/cliente/login`);
  Object.entries(params).forEach(([key, value]) => {
    if (value) url.searchParams.set(key, value);
  });
  return url;
}

function redirectSeeOther(url: URL) {
  return NextResponse.redirect(url, { status: 303 });
}

function sanitizeNextPath(slug: string, value: string | null | undefined) {
  const next = String(value || "").trim();
  if (!next) return null;
  if (!next.startsWith("/")) return null;
  if (next.startsWith("//")) return null;
  if (!next.startsWith(`/${slug}`)) return null;
  return next;
}

export async function POST(request: Request) {
  try {
    const contentType = request.headers.get("content-type") || "";
    const isJson = contentType.includes("application/json");
    let slug = "";
    let identifier = "";
    let document = "";
    let password = "";
    let name = "";
    let next = "";

    if (isJson) {
      const body = (await request.json()) as {
        slug?: string;
        identifier?: string;
        document?: string;
        password?: string;
        name?: string;
        next?: string;
      };
      slug = String(body?.slug || "").trim();
      identifier = String(body?.identifier || "").trim();
      document = String(body?.document || "").trim();
      password = String(body?.password || "");
      name = String(body?.name || "").trim();
      next = String(body?.next || "").trim();
    } else {
      const formData = await request.formData();
      slug = String(formData.get("slug") || "").trim();
      identifier = String(formData.get("identifier") || "").trim();
      document = String(formData.get("document") || "").trim();
      password = String(formData.get("password") || "");
      name = String(formData.get("name") || "").trim();
      next = String(formData.get("next") || "").trim();
    }

    if (!slug || !password || !name || (!identifier && !document)) {
      if (!isJson) {
        return redirectSeeOther(
          buildLoginRedirect(request, slug || "catalogo", {
            mode: "register",
            error: "Preencha loja, nome, CPF/CNPJ (ou contato) e senha.",
          })
        );
      }
      return NextResponse.json(
        { error: "Preencha loja, nome, CPF/CNPJ (ou contato) e senha." },
        { status: 400 }
      );
    }

    if (password.length < 8) {
      if (!isJson) {
        return redirectSeeOther(
          buildLoginRedirect(request, slug, {
            mode: "register",
            error: "A senha deve ter ao menos 8 caracteres.",
          })
        );
      }
      return NextResponse.json(
        { error: "A senha deve ter ao menos 8 caracteres." },
        { status: 400 }
      );
    }

    const url = process.env.NEXT_PUBLIC_SUPABASE_URL;
    const anon = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
    if (!url || !anon) {
      if (!isJson) {
        return redirectSeeOther(
          buildLoginRedirect(request, slug, {
            mode: "register",
            error: "Configuração do Supabase ausente.",
          })
        );
      }
      return NextResponse.json({ error: "Configuração do Supabase ausente." }, { status: 500 });
    }

    /* Cinco cadastros a cada quinze minutos por origem: ninguem precisa de mais. */
    if (!tentativaPermitida(`portal-cadastro:${origemDaRequisicao(request)}`, 5, 15 * 60)) {
      const message = "Muitos cadastros seguidos. Aguarde alguns minutos e tente de novo.";
      if (!isJson) {
        return redirectSeeOther(buildLoginRedirect(request, slug, { mode: "register", error: message }));
      }
      return NextResponse.json({ error: message }, { status: 429 });
    }

    const supabase = createSupabaseClient(url, anon);

    const registerResult = await supabase.rpc("client_portal_register", {
      p_slug: slug,
      p_identifier: identifier,
      p_document: document,
      p_password: password,
      p_name: name,
    });

    if (registerResult.error) {
      const message =
        registerResult.error.code === "PGRST202"
          ? "Área do cliente ainda não configurada no banco. Execute o SQL de migration da área do cliente."
          : registerResult.error.message || "Não foi possível liberar o acesso.";
      if (!isJson) {
        return redirectSeeOther(
          buildLoginRedirect(request, slug, {
            mode: "register",
            error: message,
          })
        );
      }
      return NextResponse.json({ error: message }, { status: 400 });
    }

    if (registerResult.data?.session_token) {
      const sanitizedNext = sanitizeNextPath(slug, next);
      const redirectUrl = buildPublicUrl(request, sanitizedNext || `/${slug}/cliente`);
      if (redirectUrl.pathname.startsWith(`/${slug}/cliente`)) {
        redirectUrl.searchParams.set("portal_token", String(registerResult.data.session_token));
      }

      const response = isJson
        ? NextResponse.json({
            ok: true,
            portal_status: registerResult.data.portal_status || "approved",
            client: registerResult.data.client || null,
            expires_at: registerResult.data.expires_at || null,
            redirect_url: redirectUrl.toString(),
          })
        : redirectSeeOther(redirectUrl);
      response.cookies.set({
        name: "ks_client_portal",
        value: String(registerResult.data.session_token),
        httpOnly: true,
        secure: process.env.NODE_ENV === "production",
        sameSite: "lax",
        path: "/",
        maxAge: 60 * 60 * 24 * 15,
      });
      return response;
    }

    const userAgent = request.headers.get("user-agent") || "";
    const forwardedFor = request.headers.get("x-forwarded-for") || "";
    const ip = forwardedFor.split(",")[0]?.trim() || "";

    const loginResult = await supabase.rpc("client_portal_login", {
      p_slug: slug,
      p_identifier: identifier,
      p_password: password,
      p_user_agent: userAgent,
      p_ip: ip,
    });

    if (loginResult.error || !loginResult.data?.session_token) {
      if (!isJson) {
        return redirectSeeOther(
          buildLoginRedirect(request, slug, {
            mode: "login",
            success: "Cadastro concluído com sucesso. Agora entre na aba Entrar.",
          })
        );
      }
      return NextResponse.json({
        ok: true,
        manual_login_required: true,
        message: "Cadastro concluído com sucesso. Agora entre na aba Entrar.",
      });
    }

    const sanitizedNext = sanitizeNextPath(slug, next);
    const redirectUrl = buildPublicUrl(request, sanitizedNext || `/${slug}/cliente`);
    if (redirectUrl.pathname.startsWith(`/${slug}/cliente`)) {
      redirectUrl.searchParams.set("portal_token", String(loginResult.data.session_token));
    }

    const response = isJson
      ? NextResponse.json({
          ok: true,
          client: loginResult.data.client || null,
          expires_at: loginResult.data.expires_at || null,
          redirect_url: redirectUrl.toString(),
        })
      : redirectSeeOther(redirectUrl);

    response.cookies.set({
      name: "ks_client_portal",
      value: String(loginResult.data.session_token),
      httpOnly: true,
      secure: process.env.NODE_ENV === "production",
      sameSite: "lax",
      path: "/",
      maxAge: 60 * 60 * 24 * 15,
    });

    return response;
  } catch (err) {
    const message =
      typeof err === "object" && err && "message" in err && typeof err.message === "string"
        ? err.message
        : "Não foi possível concluir o primeiro acesso.";
    const fallbackSlug = (() => {
      try {
        const url = new URL(request.url);
        return url.searchParams.get("slug") || "catalogo";
      } catch {
        return "catalogo";
      }
    })();
    if ((request.headers.get("content-type") || "").includes("application/json") === false) {
      return redirectSeeOther(
        buildLoginRedirect(request, fallbackSlug, {
          mode: "register",
          error: message,
        })
      );
    }
    return NextResponse.json(
      { error: message },
      { status: 500 }
    );
  }
}
