"use client";

import { useCallback, useEffect, useMemo, useState, type ReactNode } from "react";
import { AlertTriangle, CheckCircle2, Loader2, MapPin, Package, ReceiptText, Settings2, Store, Wrench } from "lucide-react";

import { pedirFiscal } from "@/components/fiscal/comum";
import { Dica } from "@/components/fiscal/dica";
import { FormatoDoCodigo } from "@/components/fiscal/formato-do-codigo";
import { Aviso } from "@/components/ui/aviso";
import { CampoDecimal } from "@/components/ui/campo-decimal";
import { CustomSelect } from "@/components/ui/custom-select";
import { Switch } from "@/components/ui/switch";
import {
  exigenciasDaCidade,
  problemaNaIdentificacaoDoCsc,
  problemaNoCsc,
  type CidadeDaNfse,
  type ConfigNfce,
  type ConfigNfe,
  type ConfigNfse,
} from "@/lib/fiscal/emissor";
import {
  faltasDoServico,
  lerRegrasDeMercadoria,
  lerRegrasDeServico,
  MODELOS_DE_MERCADORIA,
  regimeUsaCsosn,
  SEM_REGRAS_DE_SERVICO,
  type Regime,
  type RegrasDeMercadoria,
  type RegrasDeServico,
} from "@/lib/fiscal/regras";

import { AjustesDoContador } from "./ajustes-do-contador";
import { BarraDeSalvar, Bloco, Campo, Escolha, Recolhivel, soDigitos, TopoDoPasso, type PerfilNaTela } from "./campos";
import type { PropsDoPasso } from "./cliente";
import { ProdutosSemNcm } from "./produtos-sem-ncm";

type ComoVende = "producao" | "revenda";
type TipoDeServico = "grafico" | "visual" | "outro";

const AVISO_DO_ESTADO: Record<string, string> = {
  PE: "Em Pernambuco, o credenciamento do cupom fiscal é pedido no e-Fisco, em Cadastros e Credenciamentos > Credenciamento de Emissor de DF-e: tipo 83 para teste e tipo 84 para uso real. Peça os dois — sai na hora.",
  SC: "Em Santa Catarina, o cupom fiscal exige cadastrar o sistema emissor na Secretaria da Fazenda antes do uso real.",
  PR: "No Paraná, o cupom fiscal exige a autorização de uso do sistema no portal da Receita estadual antes do uso real.",
  ES: "No Espírito Santo, o cupom fiscal exige o cadastro do sistema emissor na Secretaria da Fazenda antes do uso real.",
  PA: "No Pará, o cupom fiscal exige o cadastro do sistema emissor na Secretaria da Fazenda antes do uso real.",
  RS: "No Rio Grande do Sul, o cupom fiscal exige a maquininha de cartão integrada ao sistema, o que ainda não está disponível.",
};

const SERVICOS: Record<TipoDeServico, { titulo: string; texto: string; codigo: string | null; nome: string }> = {
  grafico: { titulo: "Serviço gráfico", texto: "Impressão personalizada feita sob encomenda.", codigo: "13.05", nome: "Serviço gráfico sob encomenda" },
  visual: { titulo: "Arte e comunicação visual", texto: "Criação de arte, design e comunicação visual.", codigo: "23.01", nome: "Criação de arte e comunicação visual" },
  outro: { titulo: "Outro serviço", texto: "Instalação, manutenção ou outro. O contador informa o código.", codigo: null, nome: "Outro serviço" },
};

function perfilPrincipal(perfis: PerfilNaTela[], tipo: "mercadoria" | "servico") {
  const doTipo = perfis.filter((p) => p.ativo && p.tipo === tipo);
  return doTipo.find((p) => p.padrao) ?? doTipo[0] ?? null;
}

/** Qual resposta gerou a tributação que está salva. Se ninguém reconhece, foi o contador que ajustou. */
function respostaDoPerfil(perfil: PerfilNaTela | null, regime: Regime): ComoVende | "ajustado" | null {
  if (!perfil) return null;
  const regras = lerRegrasDeMercadoria(perfil.regras);
  for (const modelo of MODELOS_DE_MERCADORIA.filter((m) => m.regimes.includes(regime))) {
    const r = modelo.regras;
    const igual =
      regras.cfopInterno === r.cfopInterno &&
      regras.cfopInterestadual === r.cfopInterestadual &&
      (regimeUsaCsosn(regime) ? regras.csosn === r.csosn : regras.cstIcms === r.cstIcms) &&
      regras.pisCst === r.pisCst &&
      regras.cofinsCst === r.cofinsCst;
    if (igual) return modelo.chave.startsWith("producao") ? "producao" : "revenda";
  }
  return "ajustado";
}

function tipoDoServico(codigo: string | null): TipoDeServico {
  if (codigo === "13.05") return "grafico";
  if (codigo === "23.01") return "visual";
  return "outro";
}

export function PassoNotas({ painel, recarregar, irPara, abrir }: PropsDoPasso) {
  const emissor = painel.emissor;
  const regime: Regime = emissor?.regime ?? "simplesNacional";
  const normal = !regimeUsaCsosn(regime);

  const [nfe, setNfe] = useState<ConfigNfe>(() => emissor?.nfe ?? { ativo: false, ambiente: "homologacao", serie: "1", danfe: "default" });
  const [nfce, setNfce] = useState<ConfigNfce>(
    () => emissor?.nfce ?? { ativo: false, ambiente: "homologacao", serie: "1", tokenIdHomologacao: null, tokenIdProducao: null, contingenciaOffline: false }
  );
  const [nfse, setNfse] = useState<Omit<ConfigNfse, "cidade">>(() => ({
    ativo: emissor?.nfse.ativo ?? false,
    ambiente: emissor?.nfse.ambiente ?? "simulacao",
    serie: emissor?.nfse.serie ?? null,
    forma: emissor?.nfse.forma ?? "normal",
    usuario: emissor?.nfse.usuario ?? null,
    enviarInscricaoMunicipal: emissor?.nfse.enviarInscricaoMunicipal ?? "automatic",
  }));
  const [segredos, setSegredos] = useState({ cscHomologacao: "", cscProducao: "", nfseSenha: "", nfseNumeroAutenticacao: "" });
  const [numeracao, setNumeracao] = useState({ nfe: "", nfce: "", nfse: "", nfseLote: "" });

  /* Produtos: uma pergunta monta a tributação no padrão do regime. */
  const perfilDeProduto = perfilPrincipal(painel.perfis, "mercadoria");
  const respostaSalva = respostaDoPerfil(perfilDeProduto, regime);
  const regrasSalvas = useMemo(() => (perfilDeProduto ? lerRegrasDeMercadoria(perfilDeProduto.regras) : null), [perfilDeProduto]);
  const [comoVende, setComoVende] = useState<ComoVende | null>(respostaSalva === "producao" || respostaSalva === "revenda" ? respostaSalva : null);
  const [aliquotas, setAliquotas] = useState({
    icms: regrasSalvas?.aliquotaIcms ?? null,
    pis: regrasSalvas?.pisAliquota ?? null,
    cofins: regrasSalvas?.cofinsAliquota ?? null,
  });

  /* Serviços. */
  const perfilDeServico = perfilPrincipal(painel.perfis, "servico");
  const [servico, setServico] = useState<RegrasDeServico>(() => (perfilDeServico ? lerRegrasDeServico(perfilDeServico.regras) : { ...SEM_REGRAS_DE_SERVICO, codigoLc116: "13.05" }));
  const [tipoServico, setTipoServico] = useState<TipoDeServico>(() => tipoDoServico(perfilDeServico ? lerRegrasDeServico(perfilDeServico.regras).codigoLc116 : "13.05"));

  const [cidade, setCidade] = useState<CidadeDaNfse | null>(emissor?.nfse.cidade ?? null);
  const [consultandoCidade, setConsultandoCidade] = useState(false);
  const [cidadeNaoAtendida, setCidadeNaoAtendida] = useState(false);

  const [salvando, setSalvando] = useState(false);
  const [erro, setErro] = useState<ReactNode | null>(null);
  const [janela, setJanela] = useState<null | "produtos" | "ajustes-mercadoria" | "ajustes-servico">(() => {
    if (abrir === "produtos") return "produtos";
    if (abrir?.startsWith("ajustes")) {
      const perfilId = abrir.split(":")[1];
      return painel.perfis.find((p) => p.id === perfilId)?.tipo === "servico" ? "ajustes-servico" : "ajustes-mercadoria";
    }
    return null;
  });
  const perfilDoEndereco = abrir?.startsWith("ajustes:") ? abrir.split(":")[1] : null;

  /* A barra de salvar só gruda no pé da tela quando há o que salvar. */
  const retrato = JSON.stringify({ nfe, nfce, nfse, segredos, numeracao, comoVende, aliquotas, servico, tipoServico });
  const [retratoInicial] = useState(retrato);
  const alterado = retrato !== retratoInicial;

  const uf = emissor?.endereco.uf ?? "";
  const ibge = emissor?.endereco.ibge ?? "";
  const exige = exigenciasDaCidade(cidade?.opcoes ?? null);
  const produtoLigado = nfe.ativo || nfce.ativo;

  const consultarCidade = useCallback(async () => {
    if (!ibge) return;
    setConsultandoCidade(true);
    setCidadeNaoAtendida(false);
    try {
      const json = await pedirFiscal<{ cidade: CidadeDaNfse | null }>(`/api/fiscal/cidade?ibge=${ibge}`);
      setCidade(json.cidade);
      setCidadeNaoAtendida(!json.cidade);
      if (json.cidade && !emissor?.nfse.cidade) {
        setNfse((atual) => ({ ...atual, forma: json.cidade?.opcoes?.useNationalLayout ? "annfs" : "normal" }));
      }
    } catch {
      setCidadeNaoAtendida(false);
    } finally {
      setConsultandoCidade(false);
    }
  }, [ibge, emissor?.nfse.cidade]);

  useEffect(() => {
    if (!nfse.ativo || cidade || cidadeNaoAtendida) return;
    const relogio = setTimeout(() => void consultarCidade(), 0);
    return () => clearTimeout(relogio);
  }, [nfse.ativo, cidade, cidadeNaoAtendida, consultarCidade]);

  if (!emissor?.cadastradoNaSpedy) {
    return (
      <div className="space-y-8">
        <TopoDoPasso Icone={ReceiptText} titulo="Notas e impostos" texto="Escolha as notas que a empresa emite e responda algumas perguntas." />
        <Aviso
          tom="neutro"
          titulo="Primeiro, salve os dados da empresa"
          acao={
            <button type="button" onClick={() => irPara("empresa")} className="ks-button ks-button-primary ks-button-sm">
              Ir para Sua empresa
            </button>
          }
        >
          As notas ficam ligadas ao CNPJ salvo no passo 1.
        </Aviso>
      </div>
    );
  }

  const opcoesDaCidade = cidade?.opcoes ?? null;
  const pedeUsuario = opcoesDaCidade?.authentication === "userName";
  const pedeSenha = opcoesDaCidade?.authentication === "userName" || opcoesDaCidade?.authentication === "token";
  const faltaInscricaoEstadual = produtoLigado && !soDigitos(emissor.inscricaoEstadual);
  const faltaInscricaoMunicipal = nfse.ativo && !emissor.inscricaoMunicipal;

  const mudarServico = (parcial: Partial<RegrasDeServico>) => {
    setErro(null);
    setServico((atual) => ({ ...atual, ...parcial }));
  };

  const regrasDoProduto = (): RegrasDeMercadoria | null => {
    if (!comoVende) return null;
    const modelo = MODELOS_DE_MERCADORIA.find((m) => m.regimes.includes(regime) && m.chave.startsWith(comoVende));
    if (!modelo) return null;
    return {
      ...modelo.regras,
      origem: regrasSalvas?.origem ?? modelo.regras.origem,
      informacoesAdicionais: regrasSalvas && respostaSalva !== "ajustado" ? regrasSalvas.informacoesAdicionais ?? modelo.regras.informacoesAdicionais : modelo.regras.informacoesAdicionais,
      ...(normal ? { aliquotaIcms: aliquotas.icms, pisAliquota: aliquotas.pis, cofinsAliquota: aliquotas.cofins } : {}),
    };
  };

  const salvar = async () => {
    setErro(null);

    if (!nfe.ativo && !nfce.ativo && !nfse.ativo) {
      setErro("Ligue pelo menos um tipo de nota.");
      return;
    }
    if (faltaInscricaoEstadual || faltaInscricaoMunicipal) {
      setErro(
        <>
          Falta {faltaInscricaoEstadual ? "a inscrição estadual" : "a inscrição municipal"} da empresa.{" "}
          <button type="button" onClick={() => irPara("empresa")} className="font-bold underline underline-offset-2">
            Preencher em Sua empresa
          </button>
        </>
      );
      return;
    }
    if (produtoLigado && !comoVende && respostaSalva !== "ajustado") {
      setErro("Responda como você vende os seus produtos.");
      return;
    }
    if (produtoLigado && normal && comoVende && !(Number(aliquotas.icms) > 0 && Number(aliquotas.pis) > 0 && Number(aliquotas.cofins) > 0)) {
      setErro("Informe as alíquotas de ICMS, PIS e COFINS. O seu contador sabe quais são.");
      return;
    }
    if (nfce.ativo) {
      const temCscDeTeste = Boolean(segredos.cscHomologacao || emissor.nfce.cscHomologacaoGuardado);
      if (!nfce.tokenIdHomologacao || !temCscDeTeste) {
        setErro("Para o cupom fiscal, preencha a identificação e o código CSC de teste.");
        return;
      }
      const problemaDoCupom =
        problemaNaIdentificacaoDoCsc(nfce.tokenIdHomologacao, "identificação do CSC de teste") ??
        problemaNoCsc(segredos.cscHomologacao, "CSC de teste") ??
        (!segredos.cscHomologacao ? emissor.nfce.problemaNoCscHomologacao : null) ??
        problemaNaIdentificacaoDoCsc(nfce.tokenIdProducao, "identificação do CSC de uso real") ??
        problemaNoCsc(segredos.cscProducao, "CSC de uso real");
      if (problemaDoCupom) {
        setErro(problemaDoCupom);
        return;
      }
    }
    if (nfse.ativo) {
      if (cidadeNaoAtendida) {
        setErro("A nota de serviço da sua cidade ainda não pode ser emitida pelo Ktalogu. Desligue a nota de serviço por enquanto.");
        return;
      }
      const faltas = faltasDoServico(servico, exige);
      if (faltas.length) {
        setErro(`Para a nota de serviço, falta: ${faltas.join(", ")}.`);
        return;
      }
      if (pedeUsuario && !nfse.usuario) {
        setErro("A prefeitura pede o usuário de acesso ao sistema de notas dela.");
        return;
      }
      if (pedeSenha && !segredos.nfseSenha && !emissor.nfse.senhaGuardada) {
        setErro(opcoesDaCidade?.authentication === "token" ? "A prefeitura pede o código de acesso (token)." : "A prefeitura pede a senha de acesso ao sistema de notas dela.");
        return;
      }
    }

    setSalvando(true);
    try {
      /* 1. Tributação dos produtos, a partir da resposta (o ajuste do contador fica se ninguém mudou a resposta). */
      if (produtoLigado && comoVende) {
        const regras = regrasDoProduto();
        const mudouResposta = respostaSalva !== comoVende;
        const mudouAliquota =
          normal &&
          (regrasSalvas?.aliquotaIcms !== aliquotas.icms || regrasSalvas?.pisAliquota !== aliquotas.pis || regrasSalvas?.cofinsAliquota !== aliquotas.cofins);
        if (regras && (!perfilDeProduto || mudouResposta || mudouAliquota)) {
          const modelo = MODELOS_DE_MERCADORIA.find((m) => m.regimes.includes(regime) && m.chave.startsWith(comoVende));
          await pedirFiscal(perfilDeProduto ? `/api/fiscal/perfis/${perfilDeProduto.id}` : "/api/fiscal/perfis", {
            method: perfilDeProduto ? "PUT" : "POST",
            json: { nome: modelo?.nome ?? "Venda de produtos", tipo: "mercadoria", padrao: true, regras },
          });
        }
      }

      /* 2. Tributação dos serviços. */
      if (nfse.ativo) {
        await pedirFiscal(perfilDeServico ? `/api/fiscal/perfis/${perfilDeServico.id}` : "/api/fiscal/perfis", {
          method: perfilDeServico ? "PUT" : "POST",
          json: { nome: perfilDeServico?.nome ?? SERVICOS[tipoServico].nome, tipo: "servico", padrao: true, regras: servico },
        });
      }

      /* 3. As notas ligadas e os códigos de cada uma. */
      await pedirFiscal("/api/fiscal/modelos", {
        method: "PUT",
        json: {
          nfe,
          nfce,
          nfse,
          segredos,
          numeracao: {
            nfe: Number(numeracao.nfe) || null,
            nfce: Number(numeracao.nfce) || null,
            nfse: Number(numeracao.nfse) || null,
            nfseLote: Number(numeracao.nfseLote) || null,
          },
        },
      });
      setSegredos({ cscHomologacao: "", cscProducao: "", nfseSenha: "", nfseNumeroAutenticacao: "" });
      setNumeracao({ nfe: "", nfce: "", nfse: "", nfseLote: "" });
      await recarregar();
      irPara("testar");
    } catch (e) {
      setErro(e instanceof Error ? e.message : "Não foi possível salvar.");
      await recarregar();
    } finally {
      setSalvando(false);
    }
  };

  return (
    <div className="space-y-8">
      <TopoDoPasso
        Icone={ReceiptText}
        titulo="Notas e impostos"
        texto="Ligue as notas que a empresa emite e responda as perguntas de cada uma. Tudo começa em modo de teste, sem valor fiscal."
      />

      <Bloco titulo="Quais notas você vai emitir?">
        <div className="grid grid-cols-1 gap-4 md:grid-cols-3">
          <CartaoDoModelo
            Icone={Package}
            titulo="Nota de produto"
            sigla="NF-e"
            texto="Para pedidos, entregas, vendas para empresas e a loja virtual."
            ligado={nfe.ativo}
            aoMudar={(ativo) => setNfe({ ...nfe, ativo })}
          />
          <CartaoDoModelo
            Icone={Store}
            titulo="Cupom fiscal"
            sigla="NFC-e"
            texto="Para vendas rápidas no balcão, pelo PDV."
            ligado={nfce.ativo}
            aoMudar={(ativo) => setNfce({ ...nfce, ativo })}
          />
          <CartaoDoModelo
            Icone={Wrench}
            titulo="Nota de serviço"
            sigla="NFS-e"
            texto="Para serviços como criação de arte e instalação."
            ligado={nfse.ativo}
            aoMudar={(ativo) => {
              setCidadeNaoAtendida(false);
              setNfse({ ...nfse, ativo });
            }}
          />
        </div>
        {faltaInscricaoEstadual || faltaInscricaoMunicipal ? (
          <Aviso
            tom="atencao"
            titulo={faltaInscricaoEstadual ? "Falta a inscrição estadual" : "Falta a inscrição municipal"}
            acao={
              <button type="button" onClick={() => irPara("empresa")} className="ks-button ks-button-primary ks-button-sm">
                Preencher
              </button>
            }
          >
            {faltaInscricaoEstadual
              ? "A nota de produto e o cupom fiscal precisam do número da inscrição estadual. Empresa isenta emite só nota de serviço."
              : "A nota de serviço precisa da inscrição municipal da empresa."}
          </Aviso>
        ) : null}
      </Bloco>

      {produtoLigado ? (
        <Bloco
          titulo="Seus produtos"
          texto="Vale para a nota de produto e para o cupom fiscal."
          acao={
            <button type="button" onClick={() => setJanela("ajustes-mercadoria")} className="ks-button ks-button-soft ks-button-sm">
              <Settings2 size={15} />
              Ajustes do contador
            </button>
          }
        >
          <div className="space-y-3">
            <p className="text-[15px] font-semibold text-[var(--ks-color-text-primary)]">Como você vende os seus produtos?</p>
            <Escolha
              valor={comoVende}
              aoMudar={(valor) => {
                setErro(null);
                setComoVende(valor);
              }}
              opcoes={[
                { valor: "producao", titulo: "Fabrico ou personalizo", texto: "Produzo aqui: impressos, brindes personalizados, placas, adesivos sob medida." },
                { valor: "revenda", titulo: "Compro pronto e revendo", texto: "Mercadoria comprada de fornecedor e vendida sem mudar nada." },
              ]}
            />
            <p className="text-xs leading-5 text-[var(--ks-color-text-muted)]">
              {respostaSalva === "ajustado" && !comoVende
                ? "Os impostos dos produtos foram ajustados pelo contador e continuam como estão. Escolher uma opção acima troca pelo padrão."
                : "Se vende dos dois jeitos, escolha o mais comum: dá para trocar em cada produto. Os impostos seguem o padrão do seu regime; confira a nota de teste com o contador."}
            </p>
          </div>

          {normal ? (
            <div className="grid grid-cols-1 gap-5 md:grid-cols-3">
              <Campo
                rotulo="Alíquota de ICMS (%)"
                ajuda="O imposto estadual sobre a venda. Cada estado tem a sua; o contador informa a que vale para os seus produtos."
                dica="A do seu estado."
              >
                <CampoDecimal valor={aliquotas.icms} aoMudar={(n) => setAliquotas({ ...aliquotas, icms: Number.isFinite(n) && n > 0 ? n : null })} casas={4} zeroVazio className="ks-field" />
              </Campo>
              <Campo rotulo="Alíquota de PIS (%)" dica="Ex.: 0,65 no Lucro Presumido.">
                <CampoDecimal valor={aliquotas.pis} aoMudar={(n) => setAliquotas({ ...aliquotas, pis: Number.isFinite(n) && n > 0 ? n : null })} casas={4} zeroVazio className="ks-field" />
              </Campo>
              <Campo rotulo="Alíquota de COFINS (%)" dica="Ex.: 3 no Lucro Presumido.">
                <CampoDecimal valor={aliquotas.cofins} aoMudar={(n) => setAliquotas({ ...aliquotas, cofins: Number.isFinite(n) && n > 0 ? n : null })} casas={4} zeroVazio className="ks-field" />
              </Campo>
            </div>
          ) : null}

          {painel.produtosSemNcm > 0 ? (
            <div className="flex flex-col gap-4 rounded-2xl bg-[var(--ks-color-bg-inset)] p-5 sm:flex-row sm:items-center">
              <span className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-gradient-to-br from-rose-500 to-red-600 text-white">
                <AlertTriangle size={22} />
              </span>
              <div className="min-w-0 flex-1">
                <p className="text-[15px] font-extrabold text-[var(--ks-color-text-primary)]">
                  {painel.produtosSemNcm} {painel.produtosSemNcm === 1 ? "produto sem código fiscal" : "produtos sem código fiscal"}
                </p>
                <p className="text-sm text-[var(--ks-color-text-muted)]">
                  Todo produto que sai em nota precisa do código fiscal (NCM). Dá para completar agora ou depois; a nota de um produto sem código não sai.
                </p>
              </div>
              <button type="button" onClick={() => setJanela("produtos")} className="ks-button ks-button-primary shrink-0">
                Completar agora
              </button>
            </div>
          ) : (
            <p className="flex items-center gap-2 text-sm font-semibold text-emerald-700">
              <CheckCircle2 size={16} /> Todos os produtos têm código fiscal.{" "}
              <button type="button" onClick={() => setJanela("produtos")} className="font-semibold text-[var(--ks-color-primary)] underline-offset-2 hover:underline">
                Ver produtos
              </button>
            </p>
          )}

          {nfe.ativo ? (
            <Recolhivel titulo="Mais opções da nota de produto">
              <div className="grid grid-cols-1 gap-5 rounded-2xl bg-[var(--ks-color-bg-inset)] p-5 md:grid-cols-3">
                <Campo
                  rotulo="Série"
                  ajuda="Separa as sequências de numeração da empresa. Quem emite de um lugar só usa 1 e nunca mais mexe."
                  dica="Quase sempre 1."
                >
                  <input value={nfe.serie} onChange={(e) => setNfe({ ...nfe, serie: soDigitos(e.target.value).slice(0, 3) })} inputMode="numeric" className="ks-field tabular-nums" />
                </Campo>
                <Campo
                  rotulo="Próximo número"
                  opcional
                  ajuda="A numeração não pode repetir nem voltar atrás: se a empresa já emitia em outro sistema, continue de onde ela parou."
                  dica="Só se a empresa já emitia nota de produto em outro sistema nesta série."
                >
                  <input value={numeracao.nfe} onChange={(e) => setNumeracao({ ...numeracao, nfe: soDigitos(e.target.value).slice(0, 9) })} inputMode="numeric" className="ks-field tabular-nums" />
                </Campo>
                <Campo rotulo="Impressão da nota">
                  <CustomSelect
                    options={[
                      { value: "default", label: "Completa (folha A4)" },
                      { value: "simplified", label: "Simplificada" },
                    ]}
                    value={nfe.danfe}
                    onChange={(v) => setNfe({ ...nfe, danfe: v === "simplified" ? "simplified" : "default" })}
                  />
                </Campo>
              </div>
            </Recolhivel>
          ) : null}
        </Bloco>
      ) : null}

      {nfce.ativo ? (
        <Bloco
          titulo="Cupom fiscal"
          texto="Para o cupom fiscal, a Secretaria da Fazenda do seu estado pede duas coisas: credenciar a empresa para emitir esse tipo de nota (é um pedido à parte do da nota de produto) e gerar o código de segurança (CSC). Cada uma vem em dois — um para teste e outro para uso real —, e o seu contador consegue tudo no site dela."
        >
          {AVISO_DO_ESTADO[uf] ? <Aviso tom="atencao">{AVISO_DO_ESTADO[uf]}</Aviso> : null}
          <div className="grid grid-cols-1 gap-5 md:grid-cols-2 2xl:grid-cols-4">
            <Campo
              rotulo="Identificação do CSC de teste"
              ajuda="O número que a Secretaria da Fazenda dá junto com o código: costuma ser 1 ou 000001. Aparece na mesma tela do CSC."
              link="csc"
              dica="Um número curto, como 000001."
            >
              <input
                value={nfce.tokenIdHomologacao ?? ""}
                onChange={(e) => setNfce({ ...nfce, tokenIdHomologacao: soDigitos(e.target.value).slice(0, 6) || null })}
                inputMode="numeric"
                className="ks-field tabular-nums"
              />
            </Campo>
            <Campo
              rotulo="CSC de teste"
              erro={!segredos.cscHomologacao ? emissor.nfce.problemaNoCscHomologacao : null}
              dica={
                segredos.cscHomologacao
                  ? `${segredos.cscHomologacao.length} ${segredos.cscHomologacao.length === 1 ? "caractere" : "caracteres"} (o certo é de 16 a 36).`
                  : emissor.nfce.cscHomologacaoGuardado
                    ? "Já guardado. Digite só para trocar."
                    : "De 16 a 36 caracteres, copiado inteiro do site da Secretaria da Fazenda (com os traços, se houver)."
              }
            >
              <input
                value={segredos.cscHomologacao}
                onChange={(e) => setSegredos({ ...segredos, cscHomologacao: e.target.value.replace(/\s+/g, "") })}
                placeholder={emissor.nfce.cscHomologacaoGuardado ? "••••••••" : ""}
                autoComplete="off"
                className="ks-field"
              />
            </Campo>
            <Campo rotulo="Identificação do CSC de uso real" opcional>
              <input
                value={nfce.tokenIdProducao ?? ""}
                onChange={(e) => setNfce({ ...nfce, tokenIdProducao: soDigitos(e.target.value).slice(0, 6) || null })}
                inputMode="numeric"
                className="ks-field tabular-nums"
              />
            </Campo>
            <Campo
              rotulo="CSC de uso real"
              opcional
              erro={!segredos.cscProducao ? emissor.nfce.problemaNoCscProducao : null}
              dica={
                segredos.cscProducao
                  ? `${segredos.cscProducao.length} ${segredos.cscProducao.length === 1 ? "caractere" : "caracteres"} (o certo é de 16 a 36).`
                  : emissor.nfce.cscProducaoGuardado
                    ? "Já guardado. Digite só para trocar."
                    : "Pode preencher depois do teste."
              }
            >
              <input
                value={segredos.cscProducao}
                onChange={(e) => setSegredos({ ...segredos, cscProducao: e.target.value.replace(/\s+/g, "") })}
                placeholder={emissor.nfce.cscProducaoGuardado ? "••••••••" : ""}
                autoComplete="off"
                className="ks-field"
              />
            </Campo>
          </div>
          <Recolhivel titulo="Mais opções do cupom fiscal">
            <div className="space-y-5 rounded-2xl bg-[var(--ks-color-bg-inset)] p-5">
              <div className="grid grid-cols-1 gap-5 md:grid-cols-3">
                <Campo
                  rotulo="Série"
                  ajuda="Separa as sequências de numeração da empresa. Quem emite de um lugar só usa 1 e nunca mais mexe."
                  dica="Quase sempre 1."
                >
                  <input value={nfce.serie} onChange={(e) => setNfce({ ...nfce, serie: soDigitos(e.target.value).slice(0, 3) })} inputMode="numeric" className="ks-field tabular-nums" />
                </Campo>
                <Campo rotulo="Próximo número" opcional dica="Só se a empresa já emitia cupom fiscal em outro sistema nesta série.">
                  <input value={numeracao.nfce} onChange={(e) => setNumeracao({ ...numeracao, nfce: soDigitos(e.target.value).slice(0, 9) })} inputMode="numeric" className="ks-field tabular-nums" />
                </Campo>
              </div>
              <label className="flex items-center justify-between gap-4">
                <span>
                  <span className="flex items-baseline text-sm font-semibold text-[var(--ks-color-text-primary)]">
                    Emitir mesmo com a Secretaria da Fazenda fora do ar
                    <Dica titulo="Contingência offline">
                      Quando o sistema do estado cai, o balcão não pode parar de vender. Com isto ligado o cupom sai na hora, imprime com
                      um aviso de contingência e é confirmado sozinho quando a Secretaria volta. É a mesma regra que o supermercado usa.
                    </Dica>
                  </span>
                  <span className="block text-xs text-[var(--ks-color-text-muted)]">O cupom sai assim mesmo e é confirmado quando o sistema do estado voltar.</span>
                </span>
                <Switch checked={nfce.contingenciaOffline} onCheckedChange={(v) => setNfce({ ...nfce, contingenciaOffline: v })} />
              </label>
            </div>
          </Recolhivel>
        </Bloco>
      ) : null}

      {nfse.ativo ? (
        <Bloco
          titulo="Seus serviços"
          texto="A nota de serviço vai para a prefeitura da sua cidade."
          acao={
            <button type="button" onClick={() => setJanela("ajustes-servico")} className="ks-button ks-button-soft ks-button-sm">
              <Settings2 size={15} />
              Ajustes do contador
            </button>
          }
        >
          <div className="flex items-center gap-3 rounded-2xl bg-[var(--ks-color-bg-inset)] px-5 py-4">
            {consultandoCidade ? (
              <>
                <Loader2 size={18} className="animate-spin text-[var(--ks-color-primary)]" />
                <p className="text-sm text-[var(--ks-color-text-muted)]">Conferindo a prefeitura da sua cidade…</p>
              </>
            ) : cidadeNaoAtendida ? (
              <>
                <AlertTriangle size={18} className="shrink-0 text-rose-600" />
                <p className="text-sm text-[var(--ks-color-text-primary)]">
                  A nota de serviço de <strong>{emissor.endereco.cidade}/{uf}</strong> ainda não pode ser emitida pelo Ktalogu. Desligue a nota de serviço por enquanto e continue emitindo pelo site da prefeitura.
                </p>
              </>
            ) : cidade ? (
              <>
                <MapPin size={18} className="shrink-0 text-emerald-600" />
                <p className="text-sm text-[var(--ks-color-text-primary)]">
                  A prefeitura de <strong>{cidade.nome}/{cidade.uf}</strong> está pronta para receber as suas notas de serviço.
                </p>
              </>
            ) : (
              <>
                <MapPin size={18} className="shrink-0 text-[var(--ks-color-text-soft)]" />
                <p className="text-sm text-[var(--ks-color-text-muted)]">Salve o endereço da empresa para conferirmos a prefeitura.</p>
              </>
            )}
          </div>

          <div className="space-y-3">
            <p className="text-[15px] font-semibold text-[var(--ks-color-text-primary)]">Que serviço você presta?</p>
            <Escolha
              colunas={3}
              valor={tipoServico}
              aoMudar={(tipo) => {
                setTipoServico(tipo);
                mudarServico({ codigoLc116: SERVICOS[tipo].codigo ?? (tipoServico === "outro" ? servico.codigoLc116 : null) });
              }}
              opcoes={(Object.keys(SERVICOS) as TipoDeServico[]).map((tipo) => ({ valor: tipo, titulo: SERVICOS[tipo].titulo, texto: SERVICOS[tipo].texto }))}
            />
          </div>

          <div className="grid grid-cols-1 gap-5 md:grid-cols-2 2xl:grid-cols-4">
            {tipoServico === "outro" ? (
              <Campo
                rotulo="Código do serviço"
                ajuda="O item da lista nacional de serviços (Lei Complementar 116) que descreve o que a empresa faz."
                link="lc116"
                dica="Da lista nacional de serviços. Ex.: 7.02 para instalação."
              >
                <input value={servico.codigoLc116 ?? ""} onChange={(e) => mudarServico({ codigoLc116: e.target.value.replace(/[^\d.]/g, "").slice(0, 6) || null })} className="ks-field tabular-nums" />
              </Campo>
            ) : null}
            <Campo rotulo="Alíquota do ISS (%)" dica="No Simples, a da sua faixa. Na dúvida, pergunte ao contador.">
              <CampoDecimal valor={servico.aliquotaIss} aoMudar={(n) => mudarServico({ aliquotaIss: Number.isFinite(n) && n > 0 ? n : null })} casas={4} zeroVazio className="ks-field" />
            </Campo>
            {exige.codigoMunicipal ? (
              <Campo rotulo="Código do serviço na prefeitura" dica="A sua prefeitura exige. Está no cadastro da empresa nela.">
                <input value={servico.codigoMunicipal ?? ""} onChange={(e) => mudarServico({ codigoMunicipal: e.target.value.trim().slice(0, 20) || null })} className="ks-field tabular-nums" />
              </Campo>
            ) : exige.codigoMunicipalOpcional ? (
              <Campo
                rotulo="Código do serviço na prefeitura"
                opcional
                dica="Só algumas prefeituras têm. Se na nota que você já emitiu o código municipal aparece como um traço, deixe vazio."
              >
                <input value={servico.codigoMunicipal ?? ""} onChange={(e) => mudarServico({ codigoMunicipal: e.target.value.trim().slice(0, 20) || null })} className="ks-field tabular-nums" />
              </Campo>
            ) : null}
            {exige.cnae ? (
              <Campo rotulo="Atividade da empresa" dica="A sua prefeitura exige.">
                <CustomSelect
                  options={[{ value: "", label: "Escolha" }, ...emissor.cnaes.map((c) => ({ value: c.codigo, label: `${c.codigo}${c.principal ? " (principal)" : ""}` }))]}
                  value={servico.cnae ?? ""}
                  onChange={(v) => mudarServico({ cnae: v || null })}
                />
              </Campo>
            ) : null}
            {exige.codigoMunicipal ? (
              <div className="col-span-full -mt-2">
                <FormatoDoCodigo
                  ibge={cidade?.codigo}
                  cidade={cidade?.nome}
                  codigo={servico.codigoMunicipal}
                  cnae={servico.cnae}
                  cnaes={emissor.cnaes.map((c) => c.codigo)}
                  aoEscolherCnae={exige.cnae ? (cnae) => mudarServico({ cnae }) : undefined}
                />
              </div>
            ) : null}
            {exige.nbs ? (
              <Campo
                rotulo="Classificação do serviço (NBS)"
                dica={opcoesDaCidade?.useNationalLayout ? "Vai em toda nota de serviço. Está no campo Código da NBS de uma nota que você já emitiu." : "A sua prefeitura exige."}
              >
                <input
                  value={servico.nbs ?? ""}
                  onChange={(e) => mudarServico({ nbs: e.target.value.trim().slice(0, 12) || null })}
                  placeholder={opcoesDaCidade?.useNationalLayout ? "1.2101.21.00" : undefined}
                  className="ks-field tabular-nums"
                />
              </Campo>
            ) : null}
            {exige.codigoTributacaoNacional ? (
              <Campo rotulo="Código de tributação nacional" dica="A sua prefeitura exige.">
                <input value={servico.codigoTributacaoNacional ?? ""} onChange={(e) => mudarServico({ codigoTributacaoNacional: e.target.value.trim().slice(0, 12) || null })} className="ks-field tabular-nums" />
              </Campo>
            ) : null}
            {exige.anexoSimples ? (
              <Campo rotulo="Anexo do Simples Nacional" dica="A sua prefeitura exige.">
                <CustomSelect
                  options={[{ value: "", label: "Escolha" }, ...["I", "II", "III", "IV", "V"].map((a) => ({ value: a, label: `Anexo ${a}` }))]}
                  value={servico.anexoSimples ?? ""}
                  onChange={(v) => mudarServico({ anexoSimples: (v || null) as RegrasDeServico["anexoSimples"] })}
                />
              </Campo>
            ) : null}
            {pedeUsuario ? (
              <Campo rotulo="Usuário da prefeitura" dica="O login do sistema de notas da prefeitura.">
                <input value={nfse.usuario ?? ""} onChange={(e) => setNfse({ ...nfse, usuario: e.target.value.trim() || null })} autoComplete="off" className="ks-field" />
              </Campo>
            ) : null}
            {pedeSenha ? (
              <Campo
                rotulo={opcoesDaCidade?.authentication === "token" ? "Código de acesso da prefeitura" : "Senha da prefeitura"}
                dica={emissor.nfse.senhaGuardada ? "Já guardada. Digite só para trocar." : "A mesma do sistema de notas da prefeitura."}
              >
                <input
                  type="password"
                  value={segredos.nfseSenha}
                  onChange={(e) => setSegredos({ ...segredos, nfseSenha: e.target.value })}
                  placeholder={emissor.nfse.senhaGuardada ? "••••••••" : ""}
                  autoComplete="new-password"
                  className="ks-field"
                />
              </Campo>
            ) : null}
          </div>

          <div className="space-y-3">
            <p className="text-[15px] font-semibold text-[var(--ks-color-text-primary)]">Quem paga o ISS?</p>
            <Escolha
              colunas={3}
              valor={servico.issRetido}
              aoMudar={(issRetido) => mudarServico({ issRetido })}
              opcoes={[
                { valor: "nunca", titulo: "A minha empresa", texto: "O caso mais comum." },
                { valor: "cliente_pj", titulo: "O cliente, quando é empresa", texto: "Clientes com CNPJ descontam o ISS." },
                { valor: "sempre", titulo: "Sempre o cliente", texto: "Todo cliente desconta o ISS." },
              ]}
            />
          </div>

          <Recolhivel titulo="Mais opções da nota de serviço">
            <div className="space-y-5 rounded-2xl bg-[var(--ks-color-bg-inset)] p-5">
              {cidade ? (
                <Campo rotulo="Onde a nota é emitida">
                  <Escolha
                    valor={nfse.forma === "annfs" ? "annfs" : "normal"}
                    aoMudar={(forma) => setNfse({ ...nfse, forma })}
                    opcoes={[
                      { valor: "normal", titulo: "Sistema da prefeitura", texto: "O caminho de sempre da cidade." },
                      { valor: "annfs", titulo: "Emissor nacional", texto: "Para cidades que passaram a usar o padrão nacional." },
                    ]}
                  />
                </Campo>
              ) : null}
              <div className="grid grid-cols-1 gap-5 md:grid-cols-2 2xl:grid-cols-4">
                {opcoesDaCidade?.series ? (
                  <Campo rotulo="Série" opcional dica={opcoesDaCidade?.useNationalLayout || nfse.forma === "annfs" ? "Vazio vale 1. Não use a série das notas emitidas no portal do governo." : undefined}>
                    <input value={nfse.serie ?? ""} onChange={(e) => setNfse({ ...nfse, serie: e.target.value.trim().slice(0, 5) || null })} className="ks-field" />
                  </Campo>
                ) : null}
                <Campo rotulo="Próximo número" opcional dica="Só se já emitia nota de serviço em outro sistema.">
                  <input value={numeracao.nfse} onChange={(e) => setNumeracao({ ...numeracao, nfse: soDigitos(e.target.value).slice(0, 9) })} inputMode="numeric" className="ks-field tabular-nums" />
                </Campo>
                <Campo rotulo="Próximo lote" opcional>
                  <input value={numeracao.nfseLote} onChange={(e) => setNumeracao({ ...numeracao, nfseLote: soDigitos(e.target.value).slice(0, 9) })} inputMode="numeric" className="ks-field tabular-nums" />
                </Campo>
                <Campo rotulo="Número de autenticação" opcional dica={emissor.nfse.numeroAutenticacaoGuardado ? "Já guardado." : "Só algumas prefeituras pedem."}>
                  <input value={segredos.nfseNumeroAutenticacao} onChange={(e) => setSegredos({ ...segredos, nfseNumeroAutenticacao: e.target.value.trim() })} autoComplete="off" className="ks-field" />
                </Campo>
                <Campo
                  rotulo="Inscrição municipal na nota"
                  ajuda="Algumas prefeituras exigem a inscrição municipal da empresa em toda nota de serviço; outras recusam a nota que vem com ela."
                  dica="Mude só se a prefeitura recusar a nota por causa da inscrição municipal."
                >
                  <CustomSelect
                    options={[
                      { value: "automatic", label: "Decidir sozinho" },
                      { value: "yes", label: "Sempre enviar" },
                      { value: "no", label: "Nunca enviar" },
                    ]}
                    value={nfse.enviarInscricaoMunicipal}
                    onChange={(v) => setNfse({ ...nfse, enviarInscricaoMunicipal: v as typeof nfse.enviarInscricaoMunicipal })}
                  />
                </Campo>
              </div>
            </div>
          </Recolhivel>
        </Bloco>
      ) : null}

      {erro ? (
        <Aviso tom="ruim" titulo="Falta pouco" aoFechar={() => setErro(null)}>
          {erro}
        </Aviso>
      ) : null}

      <BarraDeSalvar
        rotulo="Salvar e continuar"
        fixa={alterado}
        salvando={salvando}
        aoSalvar={() => void salvar()}
        mensagem={
          nfe.ativo || nfce.ativo || nfse.ativo
            ? `Ligadas: ${[nfe.ativo ? "nota de produto" : null, nfce.ativo ? "cupom fiscal" : null, nfse.ativo ? "nota de serviço" : null].filter(Boolean).join(", ")}.`
            : "Ligue pelo menos um tipo de nota."
        }
      />

      {janela === "produtos" ? <ProdutosSemNcm painel={painel} aoFechar={() => setJanela(null)} aoSalvar={recarregar} /> : null}
      {janela === "ajustes-mercadoria" || janela === "ajustes-servico" ? (
        <AjustesDoContador
          tipo={janela === "ajustes-servico" ? "servico" : "mercadoria"}
          painel={painel}
          perfilInicial={perfilDoEndereco}
          aoFechar={() => setJanela(null)}
          aoSalvar={recarregar}
        />
      ) : null}
    </div>
  );
}

function CartaoDoModelo({
  Icone,
  titulo,
  sigla,
  texto,
  ligado,
  aoMudar,
}: {
  Icone: typeof Package;
  titulo: string;
  sigla: string;
  texto: string;
  ligado: boolean;
  aoMudar: (ligado: boolean) => void;
}) {
  return (
    <div
      role="button"
      tabIndex={0}
      onClick={() => aoMudar(!ligado)}
      onKeyDown={(e) => {
        if (e.key === "Enter" || e.key === " ") {
          e.preventDefault();
          aoMudar(!ligado);
        }
      }}
      className={`flex cursor-pointer flex-col gap-4 rounded-3xl p-5 text-left outline-none transition focus-visible:ring-2 focus-visible:ring-[var(--ks-color-primary)] ${
        ligado
          ? "bg-gradient-to-br from-violet-500 to-purple-600 text-white shadow-[0_16px_36px_rgba(124,58,237,0.32)]"
          : "bg-[var(--ks-color-bg-inset)] text-[var(--ks-color-text-primary)] hover:bg-[var(--ks-color-bg-hover)]"
      }`}
    >
      <span className="flex items-center justify-between gap-3">
        <span className={`flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl ${ligado ? "bg-white/20" : "bg-[var(--ks-color-bg-elevated)] text-[var(--ks-color-primary)] shadow-sm"}`}>
          <Icone size={22} />
        </span>
        <span onClick={(e) => e.stopPropagation()}>
          <Switch checked={ligado} onCheckedChange={aoMudar} className={ligado ? "bg-white/30" : undefined} />
        </span>
      </span>
      <span className="min-w-0">
        <span className="flex flex-wrap items-baseline gap-x-2">
          <span className="text-base font-extrabold">{titulo}</span>
          <span className={`text-xs font-semibold ${ligado ? "text-white/70" : "text-[var(--ks-color-text-soft)]"}`}>{sigla}</span>
        </span>
        <span className={`mt-1 block text-[13px] leading-5 ${ligado ? "text-white/85" : "text-[var(--ks-color-text-muted)]"}`}>{texto}</span>
      </span>
    </div>
  );
}
