/**
 * As regras das ferramentas de nota fiscal que não falam com o banco: o que
 * fazer com cada pendência ou recusa, os grupos de situação, a conferência dos
 * números (NCM, CEST, inscrição estadual, CPF/CNPJ) e os textos de motivo.
 *
 * Fica separado para ser testado sem servidor (notas-fiscais.test.ts).
 */

export const GRUPOS_DE_SITUACAO: Record<string, string[]> = {
  autorizadas: ["autorizada", "contingencia"],
  andamento: ["preparando", "enviando", "processando", "cancelando"],
  problemas: ["rejeitada", "erro", "denegada"],
  canceladas: ["cancelada"],
  previas: ["rascunho"],
};

export const OPCOES_DE_GRUPO = ["todas", ...Object.keys(GRUPOS_DE_SITUACAO)] as const;

export const EM_ANDAMENTO = ["preparando", "enviando", "processando", "cancelando"];

/** O máximo que um comando espera pela resposta da SEFAZ ou da prefeitura antes de devolver. */
export const ESPERA_MAXIMA_S = 25;

export function segundosDeEspera(valor: unknown): number {
  const numero = Math.floor(Number(valor));
  if (!Number.isFinite(numero) || numero <= 0) return 0;
  return Math.min(ESPERA_MAXIMA_S, numero);
}

export type ComoResolver = {
  /* "assistente": dá para resolver por aqui, com a ferramenta indicada.
     "painel": só no painel da Ktalogu, no caminho indicado.
     "aguardar": não mexer; consultar de novo daqui a pouco.
     "suporte": falar com o suporte da Ktalogu. */
  quem: "assistente" | "painel" | "aguardar" | "suporte";
  ferramenta?: string;
  onde_no_painel?: string;
  orientacao: string;
};

const NO_PAINEL_CONFIGURACAO = "Notas fiscais › Configuração";

/**
 * O caminho do conserto, a partir de "onde" (da pendência do plano ou da
 * explicação de uma recusa). O código ajuda a separar os casos que o
 * assistente resolve sozinho dos que só o painel resolve.
 */
export function comoResolver(onde: string | null | undefined, codigo?: string | null): ComoResolver {
  const c = String(codigo ?? "");
  switch (onde) {
    case "cliente":
      return {
        quem: "assistente",
        ferramenta: "corrigir_dados_fiscais_do_cliente",
        orientacao:
          "Corrija o cadastro do cliente (CPF/CNPJ, inscrição estadual, se é contribuinte de ICMS, endereço completo com CEP). Pergunte à pessoa os dados que faltam; nunca invente.",
      };
    case "produto":
      return {
        quem: "assistente",
        ferramenta: "corrigir_ncm_dos_produtos",
        orientacao:
          "Informe o NCM (8 números) do produto — ou do item digitado no pedido — e, se houver, o CEST e a origem. Na dúvida sobre o NCM certo, a pessoa confirma com o contador; nunca chute.",
      };
    case "pedido":
      if (c.startsWith("avulsa.")) {
        return { quem: "assistente", ferramenta: "emitir_nota_avulsa", orientacao: "Ajuste os itens ou valores da nota e chame de novo." };
      }
      return {
        quem: "painel",
        onde_no_painel: "Pedidos",
        orientacao: "Ajuste o pedido no painel (itens, valores ou situação) e depois planeje a nota de novo.",
      };
    case "pagamento":
      return {
        quem: "painel",
        onde_no_painel: "Pedidos › Pagamentos",
        orientacao:
          "O cupom fiscal (NFC-e) sai só com o pedido pago. Registre o pagamento no painel, ou emita como NF-e (modelo_mercadoria nfe).",
      };
    case "perfil":
    case "tributacao":
    case "servico":
      return {
        quem: "assistente",
        ferramenta: "salvar_tributacao_fiscal",
        onde_no_painel: `${NO_PAINEL_CONFIGURACAO} › Notas e impostos › Ajustes do contador`,
        orientacao:
          "A tributação (CFOP, CSOSN/CST, PIS/COFINS, ISS) precisa de ajuste. Veja com listar_tributacoes_fiscais, proponha a correção e grave com salvar_tributacao_fiscal (com a licença da pessoa, de preferência conferido com o contador).",
      };
    case "empresa":
      if (c.startsWith("creditos.")) {
        return {
          quem: "painel",
          onde_no_painel: "Assinatura › Notas fiscais",
          orientacao: "Acabaram as notas do pacote do mês. A pessoa compra um pacote no painel.",
        };
      }
      return {
        quem: "assistente",
        ferramenta: "alterar_dados_fiscais_da_empresa",
        onde_no_painel: `${NO_PAINEL_CONFIGURACAO} › Sua empresa`,
        orientacao:
          "É um dado da própria empresa emissora (CNPJ, inscrição estadual ou municipal, regime, endereço). Confira com ver_configuracao_fiscal e corrija com alterar_dados_fiscais_da_empresa, com a licença da pessoa. Se for o CSC do cupom fiscal, só no painel (Notas e impostos › Cupom fiscal).",
      };
    case "certificado":
      return {
        quem: "painel",
        onde_no_painel: `${NO_PAINEL_CONFIGURACAO} › passo 2 Certificado digital`,
        orientacao: "O certificado digital da empresa precisa ser enviado ou renovado no painel.",
      };
    case "numeracao":
      return {
        quem: "assistente",
        ferramenta: "configurar_tipo_de_nota",
        onde_no_painel: `${NO_PAINEL_CONFIGURACAO} › Notas e impostos`,
        orientacao: "Confira a série e o próximo número com ver_configuracao_fiscal e ajuste com configurar_tipo_de_nota (só mude a numeração se a empresa já emitia em outro sistema).",
      };
    case "csc":
      return {
        quem: "painel",
        onde_no_painel: `${NO_PAINEL_CONFIGURACAO} › Notas e impostos › Cupom fiscal`,
        orientacao: "Confira o CSC do cupom fiscal (o código do QR Code fornecido pela Secretaria da Fazenda) no painel.",
      };
    case "aguardar":
      return {
        quem: "aguardar",
        ferramenta: "consultar_situacao_da_nota",
        orientacao: "Não reenvie: a nota ainda está sendo processada. Consulte a situação de novo daqui a alguns segundos.",
      };
    case "suporte":
      return { quem: "suporte", orientacao: "Oriente a pessoa a falar com o suporte da Ktalogu." };
    default:
      return {
        quem: "painel",
        onde_no_painel: "Notas fiscais",
        orientacao: "Leia a mensagem com a pessoa. Se for dado de cadastro (cliente ou produto), corrija e reenvie; se não, ela confere no painel ou fala com o suporte.",
      };
  }
}

/**
 * Pendência de NCM aponta o produto do catálogo (alvoId) ou, quando o item foi
 * digitado no pedido sem produto, o próprio item (o id vem no código).
 */
export function alvoDaPendencia(codigo: string, alvoId: string | null | undefined): { produto_id?: string; item_do_pedido_id?: string } {
  const [tipo, id] = String(codigo).split(":");
  if (!tipo.startsWith("produto.")) return {};
  if (alvoId) return { produto_id: alvoId };
  return id ? { item_do_pedido_id: id } : {};
}

export const soDigitos = (valor: unknown) => String(valor ?? "").replace(/\D/g, "");

/** NCM: 8 números. Devolve só os dígitos, "" para apagar, ou null se estiver errado. */
export function ncmLido(valor: unknown): string | null {
  const digitos = soDigitos(valor);
  if (!digitos) return "";
  return digitos.length === 8 ? digitos : null;
}

export function cestLido(valor: unknown): string | null {
  const digitos = soDigitos(valor);
  if (!digitos) return "";
  return digitos.length === 7 ? digitos : null;
}

export function ncmFormatado(ncm: string | null | undefined) {
  const d = soDigitos(ncm);
  return d.length === 8 ? `${d.slice(0, 4)}.${d.slice(4, 6)}.${d.slice(6)}` : d || null;
}

/** A origem da mercadoria na tabela oficial (0 a 8). */
export const ORIGENS: Record<number, string> = {
  0: "Nacional",
  1: "Estrangeira, importação direta",
  2: "Estrangeira, comprada no mercado interno",
  3: "Nacional com mais de 40% de conteúdo importado",
  4: "Nacional, produzida conforme processos básicos",
  5: "Nacional com até 40% de conteúdo importado",
  6: "Estrangeira, importação direta, sem similar nacional",
  7: "Estrangeira, comprada no mercado interno, sem similar nacional",
  8: "Nacional com mais de 70% de conteúdo importado",
};

/** Inscrição estadual como o cadastro grava: "ISENTO" ou só os números. */
export function inscricaoLida(valor: unknown): string {
  const texto = String(valor ?? "").trim();
  if (!texto) return "";
  if (texto.toUpperCase() === "ISENTO") return "ISENTO";
  return soDigitos(texto);
}

export function documentoFormatado(digitos: string) {
  if (digitos.length === 11) return digitos.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, "$1.$2.$3-$4");
  if (digitos.length === 14) return digitos.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, "$1.$2.$3/$4-$5");
  return digitos;
}

export function cepFormatado(valor: unknown) {
  const d = soDigitos(valor);
  return d.length === 8 ? `${d.slice(0, 5)}-${d.slice(5)}` : null;
}

/** Motivo de cancelamento e texto da carta de correção: espaços colapsados e limites da lei. */
export function textoComLimites(valor: unknown, minimo: number, maximo: number): { ok: true; texto: string } | { ok: false; erro: string } {
  const texto = String(valor ?? "").replace(/\s+/g, " ").trim();
  if (texto.length < minimo) return { ok: false, erro: `precisa ter pelo menos ${minimo} letras (tem ${texto.length})` };
  if (texto.length > maximo) return { ok: false, erro: `pode ter até ${maximo} letras (tem ${texto.length})` };
  return { ok: true, texto };
}

/** Mensagem que vai à pessoa: o nome do fornecedor do serviço de notas não aparece. */
export function semFornecedor(mensagem: string) {
  return mensagem.replace(/\bda spedy\b/gi, "do serviço de notas").replace(/\bna spedy\b/gi, "no serviço de notas").replace(/\bspedy\b/gi, "serviço de notas");
}

export const NOME_DO_MODELO: Record<string, string> = {
  nfe: "NF-e (nota de produto)",
  nfce: "NFC-e (cupom fiscal)",
  nfse: "NFS-e (nota de serviço)",
};

export const PRESENCAS: Record<string, string> = {
  presencial: "presence",
  internet: "internet",
  telefone: "telephone",
  entrega_em_domicilio: "delivery",
  outros: "othersNonPresenceOperation",
};
