import { createBrowserClient } from "@supabase/ssr";
import { navigatorLock, type SupabaseClient } from "@supabase/supabase-js";
import { fetchQueAvisaALoja } from "@/lib/gravacoes-da-vitrine";
import { travaQueNaoQuebra } from "@/lib/trava-do-login";

/* A trava do login que não derruba a consulta quando outra aba a rouba
   ("Lock broken by another request with the 'steal' option" virava "Pedido
   não encontrado" — lib/trava-do-login.ts). Só onde o navegador tem Web
   Locks; sem ela, o cliente segue com o que já usava. */
function travaDoLogin() {
  const temWebLocks = typeof globalThis.navigator !== "undefined" && Boolean(globalThis.navigator.locks);
  return temWebLocks ? { lock: travaQueNaoQuebra(navigatorLock) } : {};
}

/**
 * Recusa uma chave de servico onde deveria ir a publica.
 *
 * Tudo com prefixo NEXT_PUBLIC_ e embutido no JavaScript enviado ao
 * navegador. Se a chave de servico cair aqui, ela vai junto — e ela ignora
 * todo o RLS, ou seja, qualquer visitante ganha acesso total ao banco. Ja
 * aconteceu nos quatro apps de uma vez; parar de pe e melhor que vazar
 * calado.
 */
function exigirChavePublica(chave: string) {
  const partes = chave.split(".");
  if (partes.length !== 3) return chave; // sb_publishable_... nao e JWT
  try {
    const payload = JSON.parse(
      Buffer.from(partes[1], "base64").toString("utf8")
    ) as { role?: string };
    if (payload.role === "service_role") {
      throw new Error(
        "NEXT_PUBLIC_SUPABASE_ANON_KEY esta com a chave de servico. " +
          "Ela iria para o navegador e daria acesso total ao banco. " +
          "Use a anon key do painel do Supabase."
      );
    }
  } catch (erro) {
    if (erro instanceof Error && erro.message.includes("chave de servico")) throw erro;
    /* payload ilegivel nao e motivo para derrubar o app */
  }
  return chave;
}

let cachedClient: SupabaseClient | null = null;

export function getSupabaseClient(): SupabaseClient {
  if (cachedClient) return cachedClient;

  const url = process.env.NEXT_PUBLIC_SUPABASE_URL;
  const anon = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;

  if (!url || !anon) {
    throw new Error("Supabase env vars are missing.");
  }

  /* O `fetch` é o mesmo de sempre, com um aviso a mais: gravou em tabela que
     a loja virtual mostra, a loja esquece o retrato guardado na hora
     (lib/gravacoes-da-vitrine.ts). */
  cachedClient = createBrowserClient(url, exigirChavePublica(anon), {
    global: { fetch: fetchQueAvisaALoja },
    auth: travaDoLogin(),
  });
  return cachedClient;
}
