"use client";

import { createContext, useContext, useMemo } from "react";
import { canCompanyRole, type CompanyPermission, type CompanyRole } from "./company-context";

/**
 * O que a pessoa logada pode fazer, disponível em qualquer tela.
 *
 * Antes, cada tela que quisesse esconder um botão repetia o mesmo trecho:
 * pegar o cliente do Supabase, buscar o usuário, buscar o contexto da empresa,
 * guardar num `useState`. São três idas ao servidor por tela, e o resultado é
 * que quase nenhuma tela fazia — das 54, seis. As outras mostravam tudo para
 * todo mundo e deixavam a API responder 403 depois do clique.
 *
 * O layout do painel já resolve esse contexto para montar o menu. Aqui ele é
 * apenas repassado, então perguntar "pode?" numa tela custa uma chamada de
 * função.
 *
 * Isto decide o que *aparece*. Quem protege o dado é o banco, com as políticas
 * que chamam `has_company_permission`. Esconder um botão é cortesia com quem
 * usa — não é a tranca.
 */

type ValorPermissoes = {
  papel: CompanyRole | null;
  ajustes: unknown;
  /* `false` enquanto a checagem não terminou ou não foi possível fazê-la. */
  resolvido: boolean;
};

const Contexto = createContext<ValorPermissoes>({
  papel: null,
  ajustes: undefined,
  resolvido: false,
});

export function ProvedorPermissoes({
  papel,
  ajustes,
  resolvido,
  children,
}: ValorPermissoes & { children: React.ReactNode }) {
  const valor = useMemo(
    () => ({ papel, ajustes, resolvido }),
    [papel, ajustes, resolvido]
  );
  return <Contexto.Provider value={valor}>{children}</Contexto.Provider>;
}

/**
 * `pode("orders.write")` — a pergunta que as telas fazem.
 *
 * Quando a checagem não pôde ser feita (rede caiu, sessão ainda resolvendo), a
 * resposta é `true`. É a mesma escolha de `decidirAcessoDaRota`, e pela mesma
 * razão: uma oscilação de rede não pode trancar quem tem acesso. O pior caso
 * aqui é um botão que aparece e devolve 403 ao ser clicado; o pior caso do
 * contrário é a pessoa achando que perdeu o acesso ao próprio trabalho.
 */
export function usePermissoes() {
  const { papel, ajustes, resolvido } = useContext(Contexto);

  return useMemo(() => {
    const pode = (permissao: CompanyPermission): boolean => {
      if (!resolvido || papel === null) return true;
      return canCompanyRole(papel, ajustes, permissao);
    };
    return { pode, papel, resolvido };
  }, [papel, ajustes, resolvido]);
}
