/**
 * As tabelas de códigos fiscais que o sistema carrega consigo.
 *
 * Elas mudam uma ou duas vezes por ano e cabem no próprio sistema: busca
 * instantânea, funciona sem internet e ninguém precisa abrir o site da SEFAZ no
 * meio do cadastro. Onde a tabela oficial é grande demais para embarcar (CEST,
 * NCM), o campo continua aceitando o código digitado e a tela mostra o link
 * oficial — melhor isso do que uma lista pela metade fingindo ser completa.
 *
 * Cada lista traz os códigos usados por quem vende produto ou presta serviço no
 * balcão e na produção sob encomenda. Quem precisa de um código fora da lista
 * digita: o campo nunca trava no que está aqui.
 */

export type CodigoFiscal = { codigo: string; descricao: string; ajuda?: string };

export type TipoDeTabela = "cfop" | "cfopEntrada" | "cstIcms" | "csosn" | "cstIbsCbs" | "classificacaoIbsCbs" | "lc116";

/* ---------------- CFOP ---------------- */

/** Saídas: 5xxx dentro do estado, 6xxx para outro estado. O par anda junto. */
export const CFOP_DE_SAIDA: CodigoFiscal[] = [
  { codigo: "5101", descricao: "Venda de produção do estabelecimento", ajuda: "O que a empresa fabrica ou personaliza e vende pronto." },
  { codigo: "5102", descricao: "Venda de mercadoria adquirida de terceiros", ajuda: "Revenda: comprou pronto e vendeu sem transformar." },
  { codigo: "5103", descricao: "Venda de produção do estabelecimento, efetuada fora do estabelecimento" },
  { codigo: "5104", descricao: "Venda de mercadoria de terceiros, efetuada fora do estabelecimento" },
  { codigo: "5109", descricao: "Venda de produção do estabelecimento destinada à Zona Franca de Manaus ou Área de Livre Comércio" },
  { codigo: "5110", descricao: "Venda de mercadoria de terceiros destinada à Zona Franca de Manaus ou Área de Livre Comércio" },
  { codigo: "5116", descricao: "Venda de produção do estabelecimento originada de encomenda para entrega futura" },
  { codigo: "5117", descricao: "Venda de mercadoria de terceiros originada de encomenda para entrega futura" },
  { codigo: "5122", descricao: "Venda de produção remetida para industrialização por conta e ordem do adquirente" },
  { codigo: "5124", descricao: "Industrialização efetuada para outra empresa", ajuda: "Serviço de industrialização sobre material do cliente." },
  { codigo: "5151", descricao: "Transferência de produção do estabelecimento", ajuda: "Entre filiais da mesma empresa." },
  { codigo: "5152", descricao: "Transferência de mercadoria adquirida de terceiros" },
  { codigo: "5202", descricao: "Devolução de compra para comercialização", ajuda: "A empresa devolve ao fornecedor o que comprou." },
  { codigo: "5401", descricao: "Venda de produção do estabelecimento com substituição tributária (contribuinte substituto)" },
  { codigo: "5403", descricao: "Venda de mercadoria de terceiros com substituição tributária (contribuinte substituto)" },
  { codigo: "5405", descricao: "Venda de mercadoria com substituição tributária (contribuinte substituído)", ajuda: "O imposto já foi pago antes, pelo fornecedor." },
  { codigo: "5551", descricao: "Venda de bem do ativo imobilizado", ajuda: "Máquina ou equipamento usado da empresa." },
  { codigo: "5556", descricao: "Venda de material de uso ou consumo" },
  { codigo: "5901", descricao: "Remessa para industrialização por encomenda" },
  { codigo: "5902", descricao: "Retorno de mercadoria utilizada na industrialização por encomenda" },
  { codigo: "5903", descricao: "Retorno de mercadoria recebida para industrialização e não aplicada" },
  { codigo: "5904", descricao: "Remessa para venda fora do estabelecimento" },
  { codigo: "5905", descricao: "Remessa para depósito fechado ou armazém geral" },
  { codigo: "5906", descricao: "Retorno de mercadoria depositada em depósito fechado ou armazém geral" },
  { codigo: "5908", descricao: "Remessa de bem por conta de contrato de comodato" },
  { codigo: "5909", descricao: "Retorno de bem recebido por conta de contrato de comodato" },
  { codigo: "5910", descricao: "Remessa em bonificação, doação ou brinde", ajuda: "Saída sem cobrança, como brinde e amostra promocional." },
  { codigo: "5911", descricao: "Remessa de amostra grátis" },
  { codigo: "5912", descricao: "Remessa de mercadoria ou bem para demonstração" },
  { codigo: "5913", descricao: "Retorno de mercadoria ou bem recebido para demonstração" },
  { codigo: "5915", descricao: "Remessa de mercadoria ou bem para conserto ou reparo" },
  { codigo: "5916", descricao: "Retorno de mercadoria ou bem recebido para conserto ou reparo" },
  { codigo: "5917", descricao: "Remessa de mercadoria em consignação mercantil ou industrial" },
  { codigo: "5920", descricao: "Remessa de vasilhame ou sacaria" },
  { codigo: "5921", descricao: "Retorno de vasilhame ou sacaria" },
  { codigo: "5933", descricao: "Prestação de serviço tributado pelo ISSQN", ajuda: "Serviço que entra na nota de produto por exigência da operação." },
  { codigo: "5949", descricao: "Outra saída de mercadoria ou prestação de serviço não especificada", ajuda: "Último recurso: use um código específico quando existir." },
];

/** Entradas: 1xxx dentro do estado, 2xxx de outro estado. */
export const CFOP_DE_ENTRADA: CodigoFiscal[] = [
  { codigo: "1101", descricao: "Compra para industrialização" },
  { codigo: "1102", descricao: "Compra para comercialização" },
  { codigo: "1201", descricao: "Devolução de venda de produção do estabelecimento", ajuda: "O cliente devolve o que a empresa fabricou." },
  { codigo: "1202", descricao: "Devolução de venda de mercadoria adquirida de terceiros", ajuda: "O cliente devolve o que a empresa revendeu." },
  { codigo: "1410", descricao: "Devolução de venda de produção com substituição tributária" },
  { codigo: "1411", descricao: "Devolução de venda de mercadoria de terceiros com substituição tributária" },
  { codigo: "1551", descricao: "Compra de bem para o ativo imobilizado" },
  { codigo: "1556", descricao: "Compra de material para uso ou consumo" },
  { codigo: "1902", descricao: "Retorno de mercadoria remetida para industrialização por encomenda" },
  { codigo: "1915", descricao: "Entrada de mercadoria ou bem recebido para conserto ou reparo" },
  { codigo: "1916", descricao: "Retorno de mercadoria ou bem remetido para conserto ou reparo" },
  { codigo: "1949", descricao: "Outra entrada de mercadoria ou prestação de serviço não especificada" },
];

/* ---------------- ICMS ---------------- */

/** Regime normal: como o ICMS incide no item. */
export const CST_ICMS: CodigoFiscal[] = [
  { codigo: "00", descricao: "Tributada integralmente", ajuda: "O caso comum de quem é do regime normal." },
  { codigo: "10", descricao: "Tributada e com cobrança do ICMS por substituição tributária" },
  { codigo: "20", descricao: "Com redução de base de cálculo" },
  { codigo: "30", descricao: "Isenta ou não tributada e com cobrança do ICMS por substituição tributária" },
  { codigo: "40", descricao: "Isenta" },
  { codigo: "41", descricao: "Não tributada" },
  { codigo: "50", descricao: "Suspensão" },
  { codigo: "51", descricao: "Diferimento" },
  { codigo: "60", descricao: "ICMS cobrado anteriormente por substituição tributária", ajuda: "O imposto já foi pago pelo fornecedor." },
  { codigo: "70", descricao: "Com redução de base de cálculo e cobrança do ICMS por substituição tributária" },
  { codigo: "90", descricao: "Outras" },
];

/** Simples Nacional: o CSOSN faz o papel do CST. */
export const CSOSN: CodigoFiscal[] = [
  { codigo: "101", descricao: "Tributada pelo Simples Nacional com permissão de crédito", ajuda: "O cliente empresa aproveita crédito do que você pagou." },
  { codigo: "102", descricao: "Tributada pelo Simples Nacional sem permissão de crédito", ajuda: "O caso comum de quem é do Simples." },
  { codigo: "103", descricao: "Isenção do ICMS no Simples Nacional para faixa de receita bruta" },
  { codigo: "201", descricao: "Tributada com permissão de crédito e com cobrança do ICMS por substituição tributária" },
  { codigo: "202", descricao: "Tributada sem permissão de crédito e com cobrança do ICMS por substituição tributária" },
  { codigo: "203", descricao: "Isenção do ICMS para faixa de receita bruta e com cobrança por substituição tributária" },
  { codigo: "300", descricao: "Imune de ICMS", ajuda: "Produto que a Constituição deixa fora do imposto, como livro e jornal." },
  { codigo: "400", descricao: "Não tributada pelo Simples Nacional" },
  { codigo: "500", descricao: "ICMS cobrado anteriormente por substituição tributária ou por antecipação" },
  { codigo: "900", descricao: "Outros" },
];

/* ---------------- Reforma tributária (IBS/CBS) ---------------- */

/**
 * A tabela completa de CST e classificação do IBS/CBS é da SEFAZ e muda com a
 * transição. Aqui ficam os casos que cobrem a venda comum; o resto o contador
 * digita, com o link da tabela oficial ao lado do campo.
 */
export const CST_IBS_CBS: CodigoFiscal[] = [
  { codigo: "000", descricao: "Tributação integral", ajuda: "Venda comum de produto ou serviço. É o padrão do sistema." },
  { codigo: "200", descricao: "Alíquota reduzida" },
  { codigo: "400", descricao: "Isenção" },
  { codigo: "410", descricao: "Imunidade e não incidência" },
  { codigo: "510", descricao: "Diferimento" },
  { codigo: "550", descricao: "Suspensão" },
];

export const CLASSIFICACAO_IBS_CBS: CodigoFiscal[] = [
  { codigo: "000001", descricao: "Situações tributadas integralmente pelo IBS e pela CBS", ajuda: "Anda junto com o CST 000." },
];

/* ---------------- Serviços (LC 116) ---------------- */

/** Os itens da lista da Lei Complementar 116 mais usados por gráfica, comunicação visual e afins. */
export const SERVICOS_LC116: CodigoFiscal[] = [
  { codigo: "1.01", descricao: "Análise e desenvolvimento de sistemas" },
  { codigo: "1.02", descricao: "Programação" },
  { codigo: "1.05", descricao: "Licenciamento ou cessão de direito de uso de programas de computação" },
  { codigo: "1.07", descricao: "Suporte técnico em informática, inclusive instalação, configuração e manutenção" },
  { codigo: "7.02", descricao: "Execução de obras por administração, empreitada ou subempreitada" },
  { codigo: "7.10", descricao: "Limpeza, manutenção e conservação de imóveis" },
  { codigo: "10.09", descricao: "Representação de qualquer natureza, inclusive comercial" },
  { codigo: "12.13", descricao: "Produção de eventos, espetáculos e congêneres" },
  { codigo: "13.05", descricao: "Composição gráfica, inclusive confecção de impressos gráficos", ajuda: "O item da gráfica: impresso feito sob encomenda para uso do próprio cliente." },
  { codigo: "14.01", descricao: "Conserto, restauração e manutenção de máquinas, aparelhos e equipamentos" },
  { codigo: "14.05", descricao: "Beneficiamento, lavagem, pintura, acabamento e congêneres de objetos de terceiros", ajuda: "Trabalho feito sobre material que é do cliente." },
  { codigo: "14.13", descricao: "Carpintaria e serralheria" },
  { codigo: "17.01", descricao: "Assessoria ou consultoria de qualquer natureza" },
  { codigo: "17.06", descricao: "Propaganda e publicidade, inclusive criação e produção de material" },
  { codigo: "23.01", descricao: "Programação visual, comunicação visual e desenho industrial", ajuda: "Criação de arte, identidade visual e projeto." },
  { codigo: "24.01", descricao: "Chaveiros, confecção de carimbos, placas, sinalização visual, banners e adesivos", ajuda: "Comunicação visual aplicada: placa, banner, adesivo, fachada." },
  { codigo: "37.01", descricao: "Serviços de artistas, atletas, modelos e manequins" },
];

/* ---------------- Onde achar o que não está aqui ---------------- */

export const LINKS_OFICIAIS = {
  ncm: { titulo: "Tabela de NCM (Receita Federal)", url: "https://portalunico.siscomex.gov.br/classif/#/sumario" },
  cest: { titulo: "Tabela de CEST (Convênio ICMS 142/2018)", url: "https://www.confaz.fazenda.gov.br/legislacao/convenios/2018/CV142_18" },
  cfop: { titulo: "Tabela de CFOP (Ajuste SINIEF)", url: "https://www.confaz.fazenda.gov.br/legislacao/ajustes/sinief" },
  cst: { titulo: "Códigos de situação tributária (Portal da NF-e)", url: "https://www.nfe.fazenda.gov.br/portal/principal.aspx" },
  ibsCbs: { titulo: "Tabela de CST e cClassTrib do IBS/CBS (SVRS)", url: "https://dfe-portal.svrs.rs.gov.br/DFE/TabelaClassificacaoTributaria" },
  lc116: { titulo: "Lista de serviços da Lei Complementar 116", url: "https://www.planalto.gov.br/ccivil_03/leis/lcp/lcp116.htm" },
  inscricaoEstadual: { titulo: "Consulta de inscrição estadual (SINTEGRA)", url: "http://www.sintegra.gov.br/" },
  csc: { titulo: "Onde gerar o CSC do cupom fiscal", url: "https://www.nfe.fazenda.gov.br/portal/listaConteudo.aspx?tipoConteudo=SFhnpU7Wgfk=" },
  cnpj: { titulo: "Cartão CNPJ (Receita Federal)", url: "https://solucoes.receita.fazenda.gov.br/servicos/cnpjreva/cnpjreva_solicitacao.asp" },
  certificado: { titulo: "O que é o certificado digital A1", url: "https://www.gov.br/governodigital/pt-br/identidade/certificado-digital" },
  simples: { titulo: "Consulta de optantes do Simples Nacional", url: "https://consopt.www8.receita.fazenda.gov.br/consultaoptantes" },
} as const;

export type ChaveDeLinkOficial = keyof typeof LINKS_OFICIAIS;

/* ---------------- Estados ---------------- */

export const UFS = [
  "AC", "AL", "AM", "AP", "BA", "CE", "DF", "ES", "GO", "MA", "MG", "MS", "MT", "PA", "PB",
  "PE", "PI", "PR", "RJ", "RN", "RO", "RR", "RS", "SC", "SE", "SP", "TO",
];

export const NOME_DO_ESTADO: Record<string, string> = {
  AC: "Acre", AL: "Alagoas", AM: "Amazonas", AP: "Amapá", BA: "Bahia", CE: "Ceará", DF: "Distrito Federal",
  ES: "Espírito Santo", GO: "Goiás", MA: "Maranhão", MG: "Minas Gerais", MS: "Mato Grosso do Sul",
  MT: "Mato Grosso", PA: "Pará", PB: "Paraíba", PE: "Pernambuco", PI: "Piauí", PR: "Paraná",
  RJ: "Rio de Janeiro", RN: "Rio Grande do Norte", RO: "Rondônia", RR: "Roraima", RS: "Rio Grande do Sul",
  SC: "Santa Catarina", SE: "Sergipe", SP: "São Paulo", TO: "Tocantins",
};

const SUL_E_SUDESTE_SEM_ES = ["SP", "RJ", "MG", "PR", "SC", "RS"];

/**
 * A alíquota do ICMS entre estados não é escolha de ninguém: é resolução do
 * Senado. 4% para mercadoria importada (Resolução 13/2012); 7% quando sai do
 * Sul/Sudeste (menos o ES) para o Norte, Nordeste, Centro-Oeste ou ES; 12% no
 * restante (Resolução 22/1989).
 */
export function aliquotaEntreEstados(ufOrigem: string, ufDestino: string, origemDaMercadoria: number | null | undefined) {
  const importada = [1, 2, 3, 8].includes(Number(origemDaMercadoria));
  if (importada) return 4;
  const origem = String(ufOrigem ?? "").toUpperCase();
  const destino = String(ufDestino ?? "").toUpperCase();
  if (SUL_E_SUDESTE_SEM_ES.includes(origem) && !SUL_E_SUDESTE_SEM_ES.includes(destino)) return 7;
  return 12;
}

/* ---------------- Busca ---------------- */

const TABELAS: Record<TipoDeTabela, CodigoFiscal[]> = {
  cfop: CFOP_DE_SAIDA,
  cfopEntrada: CFOP_DE_ENTRADA,
  cstIcms: CST_ICMS,
  csosn: CSOSN,
  cstIbsCbs: CST_IBS_CBS,
  classificacaoIbsCbs: CLASSIFICACAO_IBS_CBS,
  lc116: SERVICOS_LC116,
};

const semAcento = (texto: string) =>
  texto
    .normalize("NFD")
    .replace(/[̀-ͯ]/g, "")
    .toLowerCase();

/**
 * Busca por código ou por palavra da descrição. Digitar "5102" acha pelo
 * número; digitar "revenda" acha pelo que a pessoa quer dizer.
 */
export function procurarCodigo(tipo: TipoDeTabela, termo: string, limite = 12): CodigoFiscal[] {
  const lista = TABELAS[tipo] ?? [];
  const busca = semAcento(String(termo ?? "").trim());
  if (!busca) return lista.slice(0, limite);
  const palavras = busca.split(/\s+/).filter(Boolean);
  const pontuar = (item: CodigoFiscal) => {
    const alvo = semAcento(`${item.codigo} ${item.descricao} ${item.ajuda ?? ""}`);
    if (item.codigo.startsWith(busca)) return 100;
    if (!palavras.every((palavra) => alvo.includes(palavra))) return 0;
    return semAcento(item.descricao).startsWith(palavras[0]) ? 50 : 10;
  };
  return lista
    .map((item) => ({ item, ponto: pontuar(item) }))
    .filter((linha) => linha.ponto > 0)
    .sort((a, b) => b.ponto - a.ponto || a.item.codigo.localeCompare(b.item.codigo))
    .slice(0, limite)
    .map((linha) => linha.item);
}

/** A descrição de um código já escolhido, para a tela mostrar ao lado do campo. */
export function descricaoDoCodigo(tipo: TipoDeTabela, codigo: string | number | null | undefined): string | null {
  const alvo = String(codigo ?? "").trim();
  if (!alvo) return null;
  const lista = TABELAS[tipo] ?? [];
  const achado =
    lista.find((item) => item.codigo === alvo) ??
    lista.find((item) => item.codigo === alvo.padStart(item.codigo.length, "0")) ??
    lista.find((item) => Number(item.codigo) === Number(alvo) && Number.isFinite(Number(alvo)));
  return achado?.descricao ?? null;
}

/** O par do CFOP de saída: mesmo código, outro dígito inicial (5 → 6). */
export function cfopParaForaDoEstado(cfop: number | string | null | undefined): number | null {
  const digitos = String(cfop ?? "").replace(/\D/g, "");
  if (digitos.length !== 4 || digitos[0] !== "5") return null;
  return Number(`6${digitos.slice(1)}`);
}

/** O CEST só é pedido quando o produto tem substituição tributária. */
export function pedeCest(regras: { cstIcms?: number | null; csosn?: number | null }) {
  const comSt = [10, 30, 60, 70];
  const csosnComSt = [201, 202, 203, 500];
  return comSt.includes(Number(regras.cstIcms)) || csosnComSt.includes(Number(regras.csosn));
}
