"use client";

import { useEffect, useMemo, useState } from "react";

import { lerDefinicoes } from "@/lib/campos-proprios-do-banco";
import type { DefinicaoDeCampo, EntidadeDoCampo } from "@/lib/campos-proprios";
import { getSupabaseClient } from "@/lib/supabase";

/*
  As definições dos campos próprios de uma entidade, para os formulários.
  Ficam lembradas por um minuto: abrir e fechar o cadastro de cliente várias
  vezes não vira uma ida ao banco cada. A tela de ajustes chama
  `esquecerCamposProprios()` depois de salvar.
*/

const VALE_POR_MS = 60_000;
const lembradas = new Map<EntidadeDoCampo, { ate: number; definicoes: DefinicaoDeCampo[] }>();
const emCurso = new Map<EntidadeDoCampo, Promise<DefinicaoDeCampo[]>>();

export function esquecerCamposProprios() {
  lembradas.clear();
}

export function carregarCamposProprios(entidade: EntidadeDoCampo): Promise<DefinicaoDeCampo[]> {
  const lembrada = lembradas.get(entidade);
  if (lembrada && lembrada.ate > Date.now()) return Promise.resolve(lembrada.definicoes);
  const andando = emCurso.get(entidade);
  if (andando) return andando;
  const promessa = lerDefinicoes(getSupabaseClient(), entidade)
    .then(({ definicoes, erro }) => {
      if (!erro) lembradas.set(entidade, { ate: Date.now() + VALE_POR_MS, definicoes });
      return definicoes;
    })
    .catch(() => [] as DefinicaoDeCampo[])
    .finally(() => emCurso.delete(entidade));
  emCurso.set(entidade, promessa);
  return promessa;
}

/**
 * `definicoes`: todas (ativas e desativadas), na ordem da tela. Os
 * formulários mostram as ativas; a leitura mostra também as desativadas que
 * ainda têm valor gravado.
 */
export function useCamposProprios(entidade: EntidadeDoCampo, ligado = true) {
  const [definicoes, setDefinicoes] = useState<DefinicaoDeCampo[]>(() => lembradas.get(entidade)?.definicoes ?? []);
  const [carregado, setCarregado] = useState(() => Boolean(lembradas.get(entidade)));

  useEffect(() => {
    if (!ligado) return;
    let vivo = true;
    void carregarCamposProprios(entidade).then((lista) => {
      if (!vivo) return;
      setDefinicoes(lista);
      setCarregado(true);
    });
    return () => {
      vivo = false;
    };
  }, [entidade, ligado]);

  const ativas = useMemo(() => definicoes.filter((def) => def.ativo), [definicoes]);
  return { definicoes, ativas, carregado };
}
