/* Só servidor: usa a chave de serviço. Nunca importar de componente cliente. */
import { createAdminClient } from "@/lib/supabase-admin";
import type { LojaDaGalera, Totais } from "./tipos";

/*
  A Galera da Ktalogu, buscada no servidor — um lugar só para o HTML da página
  (page.tsx) e para o ciclo ao vivo (/api/lojas/ao-vivo e /api/lojas/totais).

  Por que existe (23/10/2026): a lista chegava VAZIA. A função antiga levava
  12,5 s e o papel anônimo corta em 3 s; o código lia `data` sem olhar
  `error`, então a falha virava "0 lojas". As funções novas
  (lojas_da_galera / placar_da_galera, migration 220) respondem em ~0,4 s e só
  a chave de serviço chama; aqui ficam a memória de 15 s (cem pessoas na
  página = uma consulta), uma segunda tentativa e o último valor bom. Falhou
  de vez, quem chama recebe null — nunca uma lista vazia inventada.

  Os critérios de cada número estão na migration 220 e em CRITERIOS_DA_GALERA
  (tipos.ts), que a página mostra para quem quiser saber como contamos.
*/

const LEMBRA_POR_MS = 15000;

const BASE_URL = String(process.env.NEXT_PUBLIC_PUBLIC_CATALOG_BASE_URL || "https://ktalogu.com.br").replace(/\/$/, "");

export type Galera = { lojas: LojaDaGalera[]; totais: Totais };

type Memoria = { bom: Galera | null; em: number; emVoo: Promise<Galera> | null };

declare global {
  var __galeraDaKtalogu: Memoria | undefined;
}

const memoria = () => (globalThis.__galeraDaKtalogu ??= { bom: null, em: 0, emVoo: null });

type LinhaDaLoja = Record<string, unknown>;

const numero = (valor: unknown) => Number(valor) || 0;
const textoOuNulo = (valor: unknown) => (typeof valor === "string" && valor.trim() ? valor.trim() : null);

function lojaDaLinha(linha: LinhaDaLoja, indice: number): LojaDaGalera {
  const slug = String(linha.slug);
  return {
    posicao: indice + 1,
    slug,
    nome: textoOuNulo(linha.nome) || "Loja",
    cidade: textoOuNulo(linha.cidade),
    uf: textoOuNulo(linha.uf),
    logo: textoOuNulo(linha.logo),
    cor: textoOuNulo(linha.cor) || "#4425A7",
    slogan: textoOuNulo(linha.slogan),
    produtos: numero(linha.produtos),
    visitantes30d: numero(linha.visitantes_30d),
    visitantes7d: numero(linha.visitantes_7d),
    visitantesTotal: numero(linha.visitantes_total),
    interesse30d: numero(linha.interesse_30d),
    pedidos30d: numero(linha.pedidos_30d),
    score: numero(linha.score),
    url: `${BASE_URL}/${slug}`,
  };
}

async function consultar(): Promise<Galera> {
  const admin = createAdminClient();
  const [ranking, placar] = await Promise.all([admin.rpc("lojas_da_galera"), admin.rpc("placar_da_galera")]);
  if (ranking.error) throw ranking.error;
  if (placar.error) throw placar.error;
  const linhas = Array.isArray(ranking.data) ? (ranking.data as LinhaDaLoja[]) : [];
  const total = Array.isArray(placar.data) ? (placar.data[0] as LinhaDaLoja | undefined) : undefined;
  if (!total) throw new Error("O placar da galera veio vazio.");
  return {
    lojas: linhas.filter((l) => textoOuNulo(l.slug)).map(lojaDaLinha),
    totais: {
      lojas: numero(total.lojas),
      produtos: numero(total.produtos),
      visitas: numero(total.visitas),
      estados: numero(total.estados),
      negociado: numero(total.negociado),
      negociado30d: numero(total.negociado_30d),
    },
  };
}

async function comSegundaTentativa(): Promise<Galera> {
  try {
    return await consultar();
  } catch {
    await new Promise((r) => setTimeout(r, 400));
    return consultar();
  }
}

/** A galera de agora; sem resposta do banco, a última boa; nunca tendo tido uma, null. */
export async function galeraDoServidor(): Promise<Galera | null> {
  const m = memoria();
  if (m.bom && Date.now() - m.em < LEMBRA_POR_MS) return m.bom;
  /* Dez visitantes no mesmo instante fazem uma consulta só. */
  m.emVoo ??= comSegundaTentativa().finally(() => {
    m.emVoo = null;
  });
  try {
    const dados = await m.emVoo;
    m.bom = dados;
    m.em = Date.now();
    return dados;
  } catch (erro) {
    console.error("[galera] sem resposta do banco:", erro instanceof Error ? erro.message : erro);
    return m.bom;
  }
}
