import { NextResponse } from "next/server";
import { createClient as createSupabaseClient } from "@supabase/supabase-js";
import { buildPublicUrl } from "@/lib/request-origin";
import { origemDaRequisicao, tentativaPermitida, esquecerTentativas } 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 password = "";
    let next = "";

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

    if (!slug || !identifier || !password) {
      if (!isJson) {
        return redirectSeeOther(
          buildLoginRedirect(request, slug || "catalogo", {
            mode: "login",
            error: "Informe loja, identificador e senha.",
          })
        );
      }
      return NextResponse.json(
        { error: "Informe loja, identificador e senha." },
        { 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: "login",
            error: "Configuração do Supabase ausente.",
          })
        );
      }
      return NextResponse.json({ error: "Configuração do Supabase ausente." }, { status: 500 });
    }

    /* Dez tentativas a cada quinze minutos por origem e loja: chute de senha
       nao passa daqui. Quem acerta zera a contagem. */
    const chaveDeTentativas = `portal-login:${origemDaRequisicao(request)}:${slug.toLowerCase()}`;
    if (!tentativaPermitida(chaveDeTentativas, 10, 15 * 60)) {
      const message = "Muitas tentativas. Aguarde alguns minutos e tente de novo.";
      if (!isJson) {
        return redirectSeeOther(buildLoginRedirect(request, slug, { mode: "login", error: message }));
      }
      return NextResponse.json({ error: message }, { status: 429 });
    }

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

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

    if (error || !data?.session_token) {
      const message =
        error?.code === "PGRST202"
          ? "Área do cliente ainda não configurada no banco. Execute o SQL de migration da área do cliente."
          : (error?.message || "Credenciais inválidas ou acesso não liberado.");
      if (!isJson) {
        return redirectSeeOther(
          buildLoginRedirect(request, slug, {
            mode: "login",
            error: message,
          })
        );
      }
      return NextResponse.json(
        { error: message },
        { status: 401 }
      );
    }

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

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

    response.cookies.set({
      name: "ks_client_portal",
      value: String(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 entrar na área do cliente.";
    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: "login",
          error: message,
        })
      );
    }
    return NextResponse.json(
      { error: message },
      { status: 500 }
    );
  }
}
