"use client";

import { useEffect, useMemo, useState } from "react";
import { Building2, CheckCircle2, Loader2, Plus, Search, X } from "lucide-react";

import { pedirFiscal } from "@/components/fiscal/comum";
import { Aviso } from "@/components/ui/aviso";
import { CustomSelect } from "@/components/ui/custom-select";
import { problemaNaInscricaoEstadual } from "@/lib/fiscal/montar";
import { REGIMES, type Regime } from "@/lib/fiscal/regras";

import { BarraDeSalvar, Bloco, Campo, Escolha, mascaraCep, mascaraCnpj, mascaraTelefone, Recolhivel, soDigitos, TopoDoPasso } from "./campos";
import type { PropsDoPasso } from "./cliente";

type Formulario = {
  cnpj: string;
  razaoSocial: string;
  nomeFantasia: string;
  inscricaoEstadual: string;
  ieIsenta: boolean;
  inscricaoMunicipal: string;
  regime: Regime | "";
  regimeEspecial: string;
  regimeSimplesNfse: string;
  cnaes: Array<{ codigo: string; principal: boolean; descricao?: string }>;
  email: string;
  telefone: string;
  cep: string;
  logradouro: string;
  numero: string;
  complemento: string;
  bairro: string;
  cidade: string;
  uf: string;
  ibge: string;
};

const REGIMES_ESPECIAIS = [
  { value: "", label: "Não se aplica" },
  { value: "microenterpriseAndSmallBusiness", label: "Microempresa ou empresa de pequeno porte (ME/EPP)" },
  { value: "individualMicroenterprise", label: "Microempreendedor individual (MEI)" },
  { value: "municipalMicroenterprise", label: "Microempresa municipal" },
  { value: "estimate", label: "Estimativa" },
  { value: "societyOfProfessionals", label: "Sociedade de profissionais" },
  { value: "cooperative", label: "Cooperativa" },
  { value: "noSpecialRegime", label: "Nenhum regime especial" },
  { value: "others", label: "Outro" },
];

const REGIMES_SIMPLES_NFSE = [
  { value: "", label: "Não informar" },
  { value: "federalAndMunicipalBySimplesNacional", label: "Tudo pelo Simples, inclusive o ISS" },
  { value: "federalBySimplesAndIssqnByNfse", label: "Impostos federais pelo Simples e ISS pago à prefeitura" },
  { value: "federalAndMunicipalByNfse", label: "Tudo fora do Simples" },
];

const TEXTO_DO_REGIME: Record<Regime, string> = {
  simplesNacional: "Micro e pequena empresa que paga os impostos pelo Simples.",
  simplesNacionalMEI: "Microempreendedor individual.",
  simplesNacionalExcessoSublimite: "Está no Simples, mas passou do limite de faturamento do estado.",
  regimeNormal: "Empresa fora do Simples.",
};

function formularioInicial(props: PropsDoPasso): Formulario {
  const e = props.painel.emissor;
  const loja = props.painel.sugestaoDaLoja;
  if (e) {
    return {
      cnpj: mascaraCnpj(e.cnpj),
      razaoSocial: e.razaoSocial,
      nomeFantasia: e.nomeFantasia ?? "",
      inscricaoEstadual: e.inscricaoEstadual && e.inscricaoEstadual !== "ISENTO" ? e.inscricaoEstadual : "",
      ieIsenta: e.inscricaoEstadual === "ISENTO",
      inscricaoMunicipal: e.inscricaoMunicipal ?? "",
      regime: e.regime,
      regimeEspecial: e.regimeEspecial ?? "",
      regimeSimplesNfse: e.regimeSimplesNfse ?? "",
      cnaes: e.cnaes,
      email: e.email ?? "",
      telefone: mascaraTelefone(e.telefone ?? ""),
      cep: mascaraCep(e.endereco.cep ?? ""),
      logradouro: e.endereco.logradouro ?? "",
      numero: e.endereco.numero ?? "",
      complemento: e.endereco.complemento ?? "",
      bairro: e.endereco.bairro ?? "",
      cidade: e.endereco.cidade ?? "",
      uf: e.endereco.uf ?? "",
      ibge: e.endereco.ibge ?? "",
    };
  }
  return {
    cnpj: mascaraCnpj(loja.cnpj),
    razaoSocial: loja.razaoSocial,
    nomeFantasia: "",
    inscricaoEstadual: "",
    ieIsenta: false,
    inscricaoMunicipal: "",
    regime: "",
    regimeEspecial: "",
    regimeSimplesNfse: "",
    cnaes: [],
    email: loja.email,
    telefone: mascaraTelefone(loja.telefone),
    cep: mascaraCep(loja.endereco.cep),
    logradouro: loja.endereco.logradouro,
    numero: loja.endereco.numero,
    complemento: loja.endereco.complemento,
    bairro: loja.endereco.bairro,
    cidade: loja.endereco.cidade,
    uf: loja.endereco.uf,
    ibge: "",
  };
}

type EmpresaDaReceita = {
  razaoSocial: string;
  nomeFantasia: string;
  email: string;
  telefone: string;
  simples: boolean | null;
  mei: boolean | null;
  inscricaoEstadual: string | null;
  cnaes: Array<{ codigo: string; descricao: string; principal: boolean }>;
  endereco: { cep: string; logradouro: string; numero: string; complemento: string; bairro: string; cidade: string; uf: string; ibge: string };
};

export function PassoEmpresa(props: PropsDoPasso) {
  const { painel, recarregar, irPara } = props;
  const inicial = useMemo(() => formularioInicial(props), [props]);
  const [form, setForm] = useState<Formulario>(inicial);
  const [buscandoCnpj, setBuscandoCnpj] = useState(false);
  const [achouNaReceita, setAchouNaReceita] = useState(false);
  const [regimeDaReceita, setRegimeDaReceita] = useState<Regime | null>(null);
  const [buscandoCep, setBuscandoCep] = useState(false);
  const [salvando, setSalvando] = useState(false);
  const [erro, setErro] = useState<string | null>(null);
  /* Buscar o CNPJ e salvar falham por motivos diferentes: o aviso diz qual dos dois foi. */
  const [erroNaBusca, setErroNaBusca] = useState(false);
  const [novoCnae, setNovoCnae] = useState("");
  const cadastrada = Boolean(painel.emissor?.cadastradoNaSpedy);
  const alterado = JSON.stringify(form) !== JSON.stringify(inicial);

  const mudar = (parcial: Partial<Formulario>) => {
    setErro(null);
    setForm((atual) => ({ ...atual, ...parcial }));
  };

  /* A cidade sem código oficial (cadastro antigo da loja) é resolvida sozinha. */
  useEffect(() => {
    if (form.ibge || !form.cidade || !form.uf) return;
    const relogio = setTimeout(async () => {
      try {
        const busca = new URLSearchParams({ cep: soDigitos(form.cep), cidade: form.cidade, uf: form.uf });
        const json = await pedirFiscal<{ cidade: { ibge: string } | null }>(`/api/fiscal/consultas/ibge?${busca.toString()}`);
        if (json.cidade?.ibge) setForm((atual) => (atual.ibge ? atual : { ...atual, ibge: json.cidade?.ibge ?? "" }));
      } catch {
        /* sem código: o salvamento avisa */
      }
    }, 500);
    return () => clearTimeout(relogio);
  }, [form.cidade, form.uf, form.cep, form.ibge]);

  const buscarCnpj = async () => {
    setBuscandoCnpj(true);
    setErro(null);
    setAchouNaReceita(false);
    try {
      const { empresa } = await pedirFiscal<{ empresa: EmpresaDaReceita }>(`/api/fiscal/consultas/cnpj?cnpj=${soDigitos(form.cnpj)}`);
      const regime: Regime | "" = empresa.mei ? "simplesNacionalMEI" : empresa.simples ? "simplesNacional" : empresa.simples === false ? "regimeNormal" : "";
      setRegimeDaReceita(regime || null);
      mudar({
        razaoSocial: empresa.razaoSocial || form.razaoSocial,
        nomeFantasia: empresa.nomeFantasia || form.nomeFantasia,
        email: form.email || empresa.email,
        telefone: form.telefone || mascaraTelefone(empresa.telefone),
        inscricaoEstadual: empresa.inscricaoEstadual || form.inscricaoEstadual,
        ieIsenta: empresa.inscricaoEstadual ? false : form.ieIsenta,
        regime: regime || form.regime,
        cnaes: empresa.cnaes.length ? empresa.cnaes : form.cnaes,
        cep: mascaraCep(empresa.endereco.cep),
        logradouro: empresa.endereco.logradouro,
        numero: empresa.endereco.numero,
        complemento: empresa.endereco.complemento,
        bairro: empresa.endereco.bairro,
        cidade: empresa.endereco.cidade,
        uf: empresa.endereco.uf,
        ibge: empresa.endereco.ibge,
      });
      setAchouNaReceita(true);
    } catch (e) {
      setErroNaBusca(true);
      setErro(e instanceof Error ? e.message : "Não encontramos o CNPJ.");
    } finally {
      setBuscandoCnpj(false);
    }
  };

  const buscarCep = async (cep: string) => {
    if (soDigitos(cep).length !== 8) return;
    setBuscandoCep(true);
    try {
      const resposta = await fetch(`https://viacep.com.br/ws/${soDigitos(cep)}/json/`);
      const dados = (await resposta.json().catch(() => null)) as Record<string, string> | null;
      if (dados && !dados.erro) {
        setForm((atual) => ({
          ...atual,
          logradouro: dados.logradouro || atual.logradouro,
          bairro: dados.bairro || atual.bairro,
          cidade: dados.localidade || atual.cidade,
          uf: (dados.uf || atual.uf).toUpperCase(),
          ibge: dados.ibge || atual.ibge,
        }));
      }
    } catch {
      /* o CEP é conferido de novo ao salvar */
    } finally {
      setBuscandoCep(false);
    }
  };

  const salvar = async () => {
    if (cadastrada && !alterado) {
      irPara("certificado");
      return;
    }
    setSalvando(true);
    setErro(null);
    try {
      await pedirFiscal("/api/fiscal/empresa", {
        method: "PUT",
        json: {
          cnpj: soDigitos(form.cnpj),
          razaoSocial: form.razaoSocial,
          nomeFantasia: form.nomeFantasia,
          inscricaoEstadual: form.ieIsenta ? "ISENTO" : form.inscricaoEstadual,
          inscricaoMunicipal: form.inscricaoMunicipal,
          regime: form.regime,
          regimeEspecial: form.regimeEspecial,
          regimeSimplesNfse: form.regimeSimplesNfse,
          cnaes: form.cnaes.map((c) => ({ codigo: c.codigo, principal: c.principal })),
          email: form.email,
          telefone: form.telefone,
          endereco: {
            cep: form.cep,
            logradouro: form.logradouro,
            numero: form.numero,
            complemento: form.complemento,
            bairro: form.bairro,
            cidade: form.cidade,
            uf: form.uf,
            ibge: form.ibge,
          },
        },
      });
      const atualizado = await recarregar();
      if (atualizado?.emissor?.cadastradoNaSpedy) irPara("certificado");
    } catch (e) {
      setErroNaBusca(false);
      setErro(e instanceof Error ? e.message : "Não foi possível salvar.");
    } finally {
      setSalvando(false);
    }
  };

  return (
    <div className="space-y-8">
      <TopoDoPasso
        Icone={Building2}
        titulo="Sua empresa"
        texto="Digite o CNPJ e clique em buscar: preenchemos o resto com o cadastro da Receita Federal. Confira e complete o que faltar."
      />

      {erro ? (
        <Aviso tom={erroNaBusca ? "neutro" : "ruim"} titulo={erroNaBusca ? "A busca do CNPJ não respondeu" : "Não deu para salvar"} aoFechar={() => setErro(null)}>
          {erro}
        </Aviso>
      ) : null}

      <Bloco titulo="Identificação">
        <div className="grid grid-cols-1 gap-5 lg:grid-cols-2 2xl:grid-cols-3">
          <Campo
            rotulo="CNPJ"
            ajuda="O número da empresa na Receita Federal. Ao buscar, o sistema traz razão social, endereço e atividades automaticamente."
            link="cnpj"
            dica={cadastrada ? "O CNPJ não muda depois do cadastro." : undefined}
          >
            <div className="flex gap-2">
              <input
                value={form.cnpj}
                onChange={(e) => {
                  setAchouNaReceita(false);
                  mudar({ cnpj: mascaraCnpj(e.target.value) });
                }}
                onKeyDown={(e) => {
                  if (e.key === "Enter" && soDigitos(form.cnpj).length === 14) void buscarCnpj();
                }}
                disabled={cadastrada}
                inputMode="numeric"
                placeholder="00.000.000/0000-00"
                className="ks-field tabular-nums"
              />
              <button
                type="button"
                onClick={() => void buscarCnpj()}
                disabled={soDigitos(form.cnpj).length !== 14 || buscandoCnpj}
                className="ks-button ks-button-primary shrink-0"
              >
                {buscandoCnpj ? <Loader2 size={16} className="animate-spin" /> : <Search size={16} />}
                Buscar
              </button>
            </div>
          </Campo>
          <Campo rotulo="Razão social" className="2xl:col-span-2">
            <input value={form.razaoSocial} onChange={(e) => mudar({ razaoSocial: e.target.value })} className="ks-field" />
          </Campo>
          <Campo rotulo="Nome fantasia" opcional>
            <input value={form.nomeFantasia} onChange={(e) => mudar({ nomeFantasia: e.target.value })} className="ks-field" />
          </Campo>
          <Campo
            rotulo="Inscrição estadual"
            erro={form.ieIsenta ? null : problemaNaInscricaoEstadual(form.inscricaoEstadual, form.uf)}
            dica="Precisa para nota de produto e cupom fiscal. Marque isenta só se a empresa emite apenas nota de serviço."
          >
            <div className="flex items-center gap-3">
              <input
                value={form.ieIsenta ? "ISENTO" : form.inscricaoEstadual}
                onChange={(e) => mudar({ inscricaoEstadual: soDigitos(e.target.value).slice(0, 14) })}
                disabled={form.ieIsenta}
                inputMode="numeric"
                className="ks-field tabular-nums"
              />
              <label className="flex shrink-0 cursor-pointer items-center gap-2 text-sm font-semibold text-[var(--ks-color-text-secondary)]">
                <input type="checkbox" checked={form.ieIsenta} onChange={(e) => mudar({ ieIsenta: e.target.checked })} className="h-4 w-4 accent-[var(--ks-color-primary)]" />
                Isenta
              </label>
            </div>
          </Campo>
          <Campo
            rotulo="Inscrição municipal"
            ajuda="O cadastro da empresa na prefeitura. Só a nota de serviço precisa dele; está no alvará ou no carnê do ISS."
            dica="Só precisa para nota de serviço."
          >
            <input value={form.inscricaoMunicipal} onChange={(e) => mudar({ inscricaoMunicipal: e.target.value.slice(0, 20) })} className="ks-field tabular-nums" />
          </Campo>
        </div>
        {achouNaReceita ? (
          <p className="flex items-center gap-2 text-sm font-semibold text-emerald-700">
            <CheckCircle2 size={16} /> Dados preenchidos com o cadastro da Receita Federal. Confira antes de salvar.
          </p>
        ) : null}
      </Bloco>

      <Bloco titulo="Regime tributário" texto="Define como os impostos saem na nota. Na dúvida, ele está no cartão CNPJ ou com o seu contador.">
        <Escolha
          colunas={4}
          valor={form.regime}
          aoMudar={(valor) => mudar({ regime: valor })}
          opcoes={REGIMES.map((r) => ({
            valor: r.valor,
            titulo: r.valor === "simplesNacionalExcessoSublimite" ? "Simples acima do limite" : r.rotulo,
            texto: TEXTO_DO_REGIME[r.valor],
            selo: regimeDaReceita === r.valor ? "Na Receita" : undefined,
          }))}
        />
      </Bloco>

      <Bloco titulo="Endereço" texto="O mesmo do cartão CNPJ.">
        <div className="grid grid-cols-1 gap-5 md:grid-cols-6 2xl:grid-cols-12">
          <Campo rotulo="CEP" className="md:col-span-2 2xl:col-span-2">
            <div className="relative">
              <input
                value={form.cep}
                onChange={(e) => {
                  const cep = mascaraCep(e.target.value);
                  mudar({ cep, ibge: soDigitos(cep) !== soDigitos(form.cep) ? "" : form.ibge });
                  if (soDigitos(cep).length === 8) void buscarCep(cep);
                }}
                inputMode="numeric"
                className="ks-field tabular-nums"
              />
              {buscandoCep ? <Loader2 size={15} className="absolute right-3 top-1/2 -translate-y-1/2 animate-spin text-[var(--ks-color-primary)]" /> : null}
            </div>
          </Campo>
          <Campo rotulo="Rua" className="md:col-span-4 2xl:col-span-5">
            <input value={form.logradouro} onChange={(e) => mudar({ logradouro: e.target.value })} className="ks-field" />
          </Campo>
          <Campo rotulo="Número" className="md:col-span-2 2xl:col-span-2">
            <input value={form.numero} onChange={(e) => mudar({ numero: e.target.value.slice(0, 10) })} className="ks-field" />
          </Campo>
          <Campo rotulo="Complemento" opcional className="md:col-span-4 2xl:col-span-3">
            <input value={form.complemento} onChange={(e) => mudar({ complemento: e.target.value })} className="ks-field" />
          </Campo>
          <Campo rotulo="Bairro" className="md:col-span-2 2xl:col-span-4">
            <input value={form.bairro} onChange={(e) => mudar({ bairro: e.target.value })} className="ks-field" />
          </Campo>
          <Campo rotulo="Cidade" className="md:col-span-3 2xl:col-span-6">
            <input value={form.cidade} onChange={(e) => mudar({ cidade: e.target.value, ibge: "" })} className="ks-field" />
          </Campo>
          <Campo rotulo="Estado" className="md:col-span-1 2xl:col-span-2">
            <input
              value={form.uf}
              onChange={(e) => mudar({ uf: e.target.value.replace(/[^a-zA-Z]/g, "").slice(0, 2).toUpperCase(), ibge: "" })}
              placeholder="UF"
              className="ks-field uppercase"
            />
          </Campo>
        </div>
      </Bloco>

      <Bloco titulo="Contato" texto="O e-mail recebe os avisos importantes sobre as notas, como certificado perto de vencer.">
        <div className="grid grid-cols-1 gap-5 lg:grid-cols-2 2xl:grid-cols-3">
          <Campo rotulo="E-mail">
            <input type="email" value={form.email} onChange={(e) => mudar({ email: e.target.value })} className="ks-field" />
          </Campo>
          <Campo rotulo="Telefone" opcional>
            <input value={form.telefone} onChange={(e) => mudar({ telefone: mascaraTelefone(e.target.value) })} inputMode="numeric" className="ks-field tabular-nums" />
          </Campo>
        </div>
      </Bloco>

      <Recolhivel titulo="Opções para nota de serviço (só se o contador pedir)">
        <div className="space-y-5 rounded-2xl bg-[var(--ks-color-bg-inset)] p-5">
          <div className="grid grid-cols-1 gap-5 lg:grid-cols-2">
            <Campo rotulo="Regime especial na prefeitura">
              <CustomSelect options={REGIMES_ESPECIAIS} value={form.regimeEspecial} onChange={(v) => mudar({ regimeEspecial: v })} />
            </Campo>
            <Campo rotulo="Como o ISS é pago">
              <CustomSelect options={REGIMES_SIMPLES_NFSE} value={form.regimeSimplesNfse} onChange={(v) => mudar({ regimeSimplesNfse: v })} />
            </Campo>
          </div>
          <Campo rotulo="Atividades da empresa (CNAE)" dica="Vêm da Receita ao buscar o CNPJ. Clique numa atividade para marcá-la como principal.">
            <div className="flex flex-wrap gap-2">
              {form.cnaes.map((cnae) => (
                <span
                  key={cnae.codigo}
                  title={cnae.descricao}
                  className={`inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-xs font-semibold ${
                    cnae.principal ? "bg-[var(--ks-color-primary)] text-white" : "bg-[var(--ks-color-bg-elevated)] text-[var(--ks-color-text-secondary)]"
                  }`}
                >
                  <button type="button" onClick={() => mudar({ cnaes: form.cnaes.map((c) => ({ ...c, principal: c.codigo === cnae.codigo })) })} className="ks-num">
                    {cnae.codigo.replace(/^(\d{4})(\d)(\d{2})$/, "$1-$2/$3")}
                  </button>
                  <button type="button" onClick={() => mudar({ cnaes: form.cnaes.filter((c) => c.codigo !== cnae.codigo) })} aria-label="Tirar atividade">
                    <X size={12} />
                  </button>
                </span>
              ))}
              <span className="inline-flex items-center gap-1 rounded-full bg-[var(--ks-color-bg-elevated)] pl-3 pr-1">
                <input
                  value={novoCnae}
                  onChange={(e) => setNovoCnae(soDigitos(e.target.value).slice(0, 7))}
                  placeholder="Código"
                  className="w-20 bg-transparent py-1.5 text-xs tabular-nums outline-none"
                />
                <button
                  type="button"
                  disabled={novoCnae.length !== 7}
                  onClick={() => {
                    if (!form.cnaes.some((c) => c.codigo === novoCnae)) {
                      mudar({ cnaes: [...form.cnaes, { codigo: novoCnae, principal: form.cnaes.length === 0 }] });
                    }
                    setNovoCnae("");
                  }}
                  className="rounded-full p-1 text-[var(--ks-color-primary)] disabled:opacity-30"
                  aria-label="Adicionar atividade"
                >
                  <Plus size={14} />
                </button>
              </span>
            </div>
          </Campo>
        </div>
      </Recolhivel>

      <BarraDeSalvar
        fixa={alterado || !cadastrada}
        rotulo={cadastrada && !alterado ? "Continuar" : "Salvar e continuar"}
        salvando={salvando}
        aoSalvar={() => void salvar()}
        mensagem={
          alterado ? (
            <span className="font-semibold text-[var(--ks-color-text-primary)]">Há alterações para salvar.</span>
          ) : cadastrada ? (
            <span className="flex items-center gap-2 font-semibold text-emerald-700">
              <CheckCircle2 size={16} /> Empresa salva.
            </span>
          ) : (
            "Confira os dados e salve para seguir para o certificado."
          )
        }
      />
    </div>
  );
}
