/*
  A trava do login do Supabase que não quebra a tela.

  Antes de cada consulta, o cliente do Supabase no navegador pega uma trava
  (Web Locks) para ler ou renovar o login. Se a trava fica presa mais de 5 s
  (aba em segundo plano que o Chrome deixa lenta, várias abas do painel,
  internet ruim), a operação seguinte a ROUBA ({ steal: true }). Quem estava
  com ela recebe "Lock broken by another request with the 'steal' option" e a
  consulta inteira falha: o assinante via "Pedido não encontrado" e o
  orçamento não salvava (21/10/2026, agenciamk5).

  Pela especificação, quem teve a trava roubada continua rodando até o fim;
  só deixa de ter a exclusividade. Então, em vez de falhar, esperamos o que
  ele já estava fazendo terminar e devolvemos esse resultado — nada roda duas
  vezes (renovar o login duas vezes gastaria o refresh token).

  Este arquivo é igual nos dois apps (admin e public).
*/

type Trava = <R>(nome: string, espera: number, fazer: () => Promise<R>) => Promise<R>;

/** O erro que a Web Locks devolve a quem teve a trava roubada. */
export function foiRoubada(erro: unknown): boolean {
  const e = erro as { name?: string; message?: string } | null;
  return Boolean(e && e.name === "AbortError" && /steal/i.test(String(e.message || "")));
}

/** Envolve a trava original: roubada no meio do caminho, devolve o resultado mesmo assim. */
export function travaQueNaoQuebra(original: Trava): Trava {
  return async <R,>(nome: string, espera: number, fazer: () => Promise<R>): Promise<R> => {
    let emAndamento: Promise<R> | null = null;
    try {
      return await original(nome, espera, () => {
        emAndamento = fazer();
        return emAndamento;
      });
    } catch (erro) {
      if (emAndamento && foiRoubada(erro)) return await emAndamento;
      throw erro;
    }
  };
}
