import { NextResponse, type NextRequest } from "next/server";
import { parceiraPeloHost } from "@/landing/parceiras";

function extractHostname(request: NextRequest) {
  const host = request.headers.get("host") || "";
  return host.split(":")[0]?.trim().toLowerCase() || "";
}

function readConfiguredPublicHost() {
  const raw = process.env.NEXT_PUBLIC_PUBLIC_CATALOG_BASE_URL || "";
  if (!raw) return "";
  try {
    return new URL(raw).hostname.toLowerCase();
  } catch {
    return raw.replace(/^https?:\/\//, "").split("/")[0]?.split(":")[0]?.toLowerCase() || "";
  }
}

function isSystemPath(pathname: string) {
  if (pathname.startsWith("/_next")) return true;
  if (pathname.startsWith("/api")) return true;
  if (pathname === "/lp" || pathname.startsWith("/lp/")) return true;
  if (pathname.startsWith("/images")) return true;
  if (pathname.startsWith("/assets")) return true;
  if (pathname === "/favicon.ico") return true;
  if (pathname === "/robots.txt") return true;
  if (pathname === "/sitemap.xml") return true;
  return /\.[a-z0-9]+$/i.test(pathname);
}

function isPrimaryCatalogHost(hostname: string) {
  const configured = readConfiguredPublicHost();
  const knownHosts = new Set([
    "localhost",
    "127.0.0.1",
    "ktalogu.com.br",
    "www.ktalogu.com.br",
    configured,
  ]);
  return knownHosts.has(hostname);
}

/*
  Dominio proprio -> slug, com memoria.

  Antes cada request de pagina, em qualquer host (inclusive ktalogu.com.br),
  ia ao banco perguntar o slug: 200 ms a mais em toda visita, 900 mil vezes.
  Agora os hosts do proprio Ktalogu nem perguntam, e o dominio de cliente e
  lembrado por alguns minutos por instancia. Falha de rede nao e lembrada:
  o proximo request pergunta de novo.
*/
const LEMBRANCA_MS = 5 * 60 * 1000;
const LEMBRANCA_VAZIA_MS = 60 * 1000;
const lembrados = new Map<string, { slug: string; ate: number }>();

async function slugDoDominio(hostname: string) {
  const agora = Date.now();
  const lembrado = lembrados.get(hostname);
  if (lembrado && lembrado.ate > agora) return lembrado.slug;
  const slug = await resolveSlugByDomain(hostname);
  if (slug === null) return lembrado?.slug || "";
  lembrados.set(hostname, { slug, ate: agora + (slug ? LEMBRANCA_MS : LEMBRANCA_VAZIA_MS) });
  return slug;
}

/* Devolve o slug, "" quando o dominio nao e de ninguem, e null quando a
   pergunta falhou (rede, tempo esgotado). */
async function resolveSlugByDomain(hostname: string): Promise<string | null> {
  const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
  const anonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
  if (!supabaseUrl || !anonKey) return "";
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), 1200);

  try {
    const response = await fetch(`${supabaseUrl}/rest/v1/rpc/get_public_profile_slug_by_domain`, {
      method: "POST",
      headers: {
        "content-type": "application/json",
        apikey: anonKey,
        authorization: `Bearer ${anonKey}`,
      },
      body: JSON.stringify({ p_domain: hostname }),
      cache: "no-store",
      signal: controller.signal,
    });

    if (!response.ok) return null;
    const data = (await response.json()) as string | null;
    return typeof data === "string" ? data.trim() : "";
  } catch {
    return null;
  } finally {
    clearTimeout(timeoutId);
  }
}

/**
 * Subdominio da vitrine de lojas (lojas.ktalogu.com.br).
 *
 * Precisa ser testado ANTES da busca de dominio -> slug: sem isso o host cairia
 * no lookup, nao acharia loja nenhuma e serviria a landing em vez da vitrine.
 */
function isStoreDirectoryHost(hostname: string) {
  return hostname === "lojas.ktalogu.com.br" || hostname === "lojas.localhost";
}

/**
 * O subdominio dos boletins.
 *
 * `info.ktalogu.com.br/frete-na-compra` e a mesma pagina que
 * `/boletim/frete-na-compra` neste app. Precisa ser testado ANTES da busca de
 * dominio -> slug pelo mesmo motivo do diretorio de lojas: sem isso o host
 * cairia no lookup, nao acharia loja nenhuma e serviria a landing.
 */
function isBulletinHost(hostname: string) {
  return hostname === "info.ktalogu.com.br" || hostname === "info.localhost";
}

/**
 * O subdominio do centro de aprendizado.
 *
 * `help.ktalogu.com.br/pdv/fechar-caixa` e a mesma pagina que
 * `/aprender/pdv/fechar-caixa` neste app. Mesma razao do diretorio de lojas e
 * do boletim para ser testado ANTES da busca de dominio -> slug: sem isso o
 * host cairia no lookup, nao acharia loja nenhuma e serviria a landing.
 */
function isHelpHost(hostname: string) {
  return hostname === "help.ktalogu.com.br" || hostname === "help.localhost";
}

/*
  O link curto da live, como no Meet: ktalogu.com.br/abc-defg-hij (ou no
  dominio da loja). O endereco continua curto na barra; por dentro a pagina e
  /<slug>/live/<sala>. Lembrado por alguns minutos por instancia.
*/
const CODIGO_DA_LIVE = /^\/([a-z]{3}-[a-z]{4}-[a-z]{3})\/?$/i;
const salasLembradas = new Map<string, { slug: string; sala: string; ate: number }>();

async function salaDoCodigo(codigo: string): Promise<{ slug: string; sala: string } | null> {
  const chave = codigo.toLowerCase();
  const agora = Date.now();
  const lembrada = salasLembradas.get(chave);
  if (lembrada && lembrada.ate > agora) return lembrada.slug ? lembrada : null;
  const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
  const anonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
  if (!supabaseUrl || !anonKey) return null;
  try {
    const response = await fetch(`${supabaseUrl}/rest/v1/rpc/live_sala_pelo_codigo`, {
      method: "POST",
      headers: { "content-type": "application/json", apikey: anonKey, authorization: `Bearer ${anonKey}` },
      body: JSON.stringify({ p_codigo: chave }),
      cache: "no-store",
      signal: AbortSignal.timeout(2500),
    });
    if (!response.ok) return null;
    const linhas = (await response.json()) as Array<{ slug: string | null; sala_id: string }> | null;
    const linha = Array.isArray(linhas) ? linhas[0] : null;
    const achada = linha?.slug ? { slug: linha.slug, sala: linha.sala_id } : null;
    salasLembradas.set(chave, { slug: achada?.slug ?? "", sala: achada?.sala ?? "", ate: agora + (achada ? 5 * 60 * 1000 : 30 * 1000) });
    if (salasLembradas.size > 2000) salasLembradas.delete(salasLembradas.keys().next().value as string);
    return achada;
  } catch {
    return null;
  }
}

/* Reescreve o link curto para a pagina da sala; null quando o codigo nao e de ninguem (ou e de outra loja). */
async function reescreverLinkDaLive(request: NextRequest, slugDoHost: string | null): Promise<NextResponse | null> {
  const achado = CODIGO_DA_LIVE.exec(request.nextUrl.pathname);
  if (!achado) return null;
  const sala = await salaDoCodigo(achado[1]);
  if (!sala) return null;
  if (slugDoHost !== null && sala.slug !== slugDoHost) return null;
  const url = request.nextUrl.clone();
  url.pathname = `/${sala.slug}/live/${sala.sala}`;
  return NextResponse.rewrite(url);
}

export async function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;
  if (isSystemPath(pathname)) return NextResponse.next();

  const hostname = extractHostname(request);
  if (!hostname) return NextResponse.next();

  if (isBulletinHost(hostname)) {
    /* A raiz do subdominio nao tem indice: manda para o site. O resto do
       caminho e o endereco do boletim. */
    const url = request.nextUrl.clone();
    if (pathname === "/") {
      url.hostname = "ktalogu.com.br";
      url.pathname = "/";
      return NextResponse.redirect(url);
    }
    if (pathname.startsWith("/boletim")) return NextResponse.next();
    url.pathname = `/boletim${pathname}`;
    return NextResponse.rewrite(url);
  }

  if (isHelpHost(hostname)) {
    /* A raiz do subdominio E o centro de aprendizado, e nao um redirecionamento:
       diferente do boletim, aqui existe uma capa de verdade para mostrar. */
    const url = request.nextUrl.clone();
    if (pathname === "/") {
      url.pathname = "/aprender";
      return NextResponse.rewrite(url);
    }
    if (pathname.startsWith("/aprender") || pathname.startsWith("/api/help")) return NextResponse.next();
    url.pathname = `/aprender${pathname}`;
    return NextResponse.rewrite(url);
  }

  /* As paginas das parceiras (papo.ktalogu.com.br): a raiz e a landing com os
     links dela. Antes da busca de dominio -> slug pelo mesmo motivo do
     diretorio de lojas. Qualquer outro caminho volta para o site. */
  const parceira = parceiraPeloHost(hostname);
  if (parceira) {
    const url = request.nextUrl.clone();
    if (pathname === "/") {
      url.pathname = `/parceira/${parceira.slug}`;
      return NextResponse.rewrite(url);
    }
    url.hostname = "ktalogu.com.br";
    url.port = "";
    return NextResponse.redirect(url);
  }

  if (isStoreDirectoryHost(hostname)) {
    /* A raiz do subdominio serve /lojas; o resto segue direto, para /lojas
       continuar acessivel tambem por ktalogu.com.br/lojas. */
    if (pathname === "/" ) {
      const url = request.nextUrl.clone();
      url.pathname = "/lojas";
      return NextResponse.rewrite(url);
    }
    return NextResponse.next();
  }
  /* Os hosts do proprio Ktalogu (e o local) nao tem dominio para resolver. */
  if (isPrimaryCatalogHost(hostname)) return (await reescreverLinkDaLive(request, null)) ?? NextResponse.next();

  const slug = await slugDoDominio(hostname);
  if (!slug) return NextResponse.next();

  const daLive = await reescreverLinkDaLive(request, slug);
  if (daLive) return daLive;

  if (pathname === `/${slug}` || pathname.startsWith(`/${slug}/`)) {
    return NextResponse.next();
  }

  const nextUrl = request.nextUrl.clone();
  nextUrl.pathname = pathname === "/" ? `/${slug}` : `/${slug}${pathname}`;
  return NextResponse.rewrite(nextUrl);
}

export const config = {
  matcher: ["/:path*"],
};
