"use client";

import { useMemo, useState } from "react";
import { Gift, PauseCircle, PlayCircle, Search } from "lucide-react";

import type { PainelFiscal } from "@/lib/fiscal-owner";

import type { Avisar } from "./painel-client";
import {
  Barra,
  BOTAO_PRIMARIO,
  BOTAO_SECUNDARIO,
  CLASSE_DO_CAMPO,
  Campo,
  cnpjFormatado,
  inteiro,
  mesPorExtenso,
  Modal,
  pedir,
  plural,
  Recado,
  Selo,
  type Tom,
} from "./ui";

type Emissor = PainelFiscal["emissores"][number];
type Filtro = "todas" | "ativo" | "rascunho" | "suspenso";

const STATUS: Record<Emissor["status"], { rotulo: string; tom: Tom }> = {
  ativo: { rotulo: "Emitindo", tom: "verde" },
  rascunho: { rotulo: "Configurando", tom: "cinza" },
  suspenso: { rotulo: "Suspensa", tom: "vermelho" },
};

const MODELOS: Record<string, string> = { nfe: "NF-e", nfce: "NFC-e", nfse: "NFS-e" };

const REGIMES: Record<string, string> = {
  simplesNacional: "Simples Nacional",
  simplesNacionalExcessoSublimite: "Simples (excesso de sublimite)",
  simplesNacionalMEI: "MEI",
  regimeNormal: "Regime normal",
};

export default function AbaEmpresas({ painel, aoMudar, avisar }: { painel: PainelFiscal; aoMudar: () => Promise<void>; avisar: Avisar }) {
  const [busca, setBusca] = useState("");
  const [filtro, setFiltro] = useState<Filtro>("todas");
  const [cortesiaPara, setCortesiaPara] = useState<Emissor | null>(null);
  const [situacaoDe, setSituacaoDe] = useState<Emissor | null>(null);
  const [ocupado, setOcupado] = useState(false);

  const emissores = painel.emissores;
  const mes = mesPorExtenso(painel.competencia);

  const contagens = useMemo(
    () => ({
      todas: emissores.length,
      ativo: emissores.filter((e) => e.status === "ativo").length,
      rascunho: emissores.filter((e) => e.status === "rascunho").length,
      suspenso: emissores.filter((e) => e.status === "suspenso").length,
    }),
    [emissores]
  );

  const filtrados = useMemo(() => {
    const alvo = busca.trim().toLowerCase();
    const digitos = alvo.replace(/\D/g, "");
    return emissores.filter((e) => {
      if (filtro !== "todas" && e.status !== filtro) return false;
      if (!alvo) return true;
      const textoDaLinha = `${e.empresaNome} ${e.razaoSocial} ${e.nomeFantasia ?? ""} ${e.email ?? ""} ${e.cidade ?? ""}`.toLowerCase();
      return textoDaLinha.includes(alvo) || (digitos.length >= 3 && e.cnpj.includes(digitos));
    });
  }, [emissores, busca, filtro]);

  async function mudarSituacao() {
    if (!situacaoDe) return;
    const acao = situacaoDe.status === "suspenso" ? "reativar" : "suspender";
    setOcupado(true);
    try {
      const resposta = await pedir<{ status: Emissor["status"] }>("/api/fiscal/emissores", {
        method: "PUT",
        body: JSON.stringify({ id: situacaoDe.id, acao }),
      });
      await aoMudar();
      avisar(
        "ok",
        acao === "suspender"
          ? `Emissão de ${situacaoDe.empresaNome} suspensa.`
          : resposta.status === "ativo"
            ? `${situacaoDe.empresaNome} voltou a emitir.`
            : `${situacaoDe.empresaNome} foi reativada, mas ainda falta terminar a configuração para emitir.`
      );
      setSituacaoDe(null);
    } catch (falha) {
      avisar("erro", falha instanceof Error ? falha.message : "Não foi possível mudar a situação.");
    } finally {
      setOcupado(false);
    }
  }

  return (
    <div className="grid grid-cols-1 gap-4">
      <div className="flex flex-wrap items-end justify-between gap-3">
        <div>
          <h2 className="text-base font-semibold text-slate-900">Empresas emissoras</h2>
          <p className="mt-0.5 text-sm text-slate-500">
            {inteiro(painel.resumo.vagasUsadas)} de {inteiro(painel.regras.limite_emissores)} vagas usadas · uso de notas em {mes}
          </p>
        </div>
      </div>

      <div className="flex flex-col gap-3 sm:flex-row sm:items-center">
        <div className="flex flex-1 items-center gap-2 rounded-xl border border-slate-200 bg-white px-3 shadow-sm">
          <Search size={16} className="shrink-0 text-slate-400" />
          <input
            value={busca}
            onChange={(e) => setBusca(e.target.value)}
            placeholder="Buscar por empresa, razão social, CNPJ ou cidade"
            aria-label="Buscar empresa"
            className="h-11 min-w-0 flex-1 border-0 bg-transparent text-sm text-slate-900 outline-none placeholder:text-slate-400"
          />
        </div>
        <div className="flex max-w-full gap-1 overflow-x-auto rounded-xl border border-slate-200 bg-white p-1 shadow-sm">
          {(
            [
              ["todas", "Todas"],
              ["ativo", "Emitindo"],
              ["rascunho", "Configurando"],
              ["suspenso", "Suspensas"],
            ] as Array<[Filtro, string]>
          ).map(([chave, rotulo]) => (
            <button
              key={chave}
              type="button"
              onClick={() => setFiltro(chave)}
              aria-pressed={filtro === chave}
              className={`inline-flex h-9 shrink-0 items-center gap-1.5 rounded-lg px-3 text-sm font-medium transition ${
                filtro === chave ? "bg-slate-900 text-white" : "text-slate-600 hover:bg-slate-50"
              }`}
            >
              {rotulo}
              <span className={`text-[11px] tabular-nums ${filtro === chave ? "text-white/70" : "text-slate-400"}`}>{contagens[chave]}</span>
            </button>
          ))}
        </div>
      </div>

      {filtrados.length === 0 ? (
        <div className="rounded-2xl border border-dashed border-slate-300 bg-white px-6 py-12 text-center">
          <p className="text-sm font-medium text-slate-800">
            {emissores.length === 0 ? "Nenhuma empresa configurou a emissão neste ambiente ainda." : "Nada encontrado com esse filtro."}
          </p>
          <p className="mx-auto mt-1 max-w-md text-xs leading-5 text-slate-500">
            {emissores.length === 0
              ? "Elas aparecem aqui quando começam a configuração em Notas fiscais › Configuração, no sistema."
              : "Tente outro termo ou outro filtro."}
          </p>
        </div>
      ) : (
        <ul className="grid grid-cols-1 gap-3">
          {filtrados.map((e) => {
            const status = STATUS[e.status] ?? STATUS.rascunho;
            const certificado =
              e.certificadoDias === null
                ? null
                : e.certificadoDias < 0
                  ? { tom: "vermelho" as Tom, texto: "Certificado vencido" }
                  : e.certificadoDias <= 30
                    ? { tom: "ambar" as Tom, texto: `Certificado vence em ${plural(e.certificadoDias, "dia", "dias")}` }
                    : { tom: "cinza" as Tom, texto: `Certificado vence em ${plural(e.certificadoDias, "dia", "dias")}` };
            return (
              <li key={e.id} className="min-w-0 rounded-2xl border border-slate-200 bg-white p-4 shadow-sm sm:p-5">
                <div className="flex flex-wrap items-start justify-between gap-4">
                  <div className="min-w-0 flex-1 basis-[280px]">
                    <div className="flex flex-wrap items-center gap-2">
                      <span className="text-sm font-semibold text-slate-900">{e.empresaNome}</span>
                      <Selo tom={status.tom}>{status.rotulo}</Selo>
                      {!e.naSpedy ? <Selo tom="cinza" titulo="Ainda não ocupa vaga no plano">Fora da Spedy</Selo> : null}
                    </div>
                    <p className="mt-1 truncate text-xs text-slate-500">
                      {e.razaoSocial} · {cnpjFormatado(e.cnpj)}
                      {e.cidade ? ` · ${e.cidade}` : ""}
                    </p>
                    <div className="mt-2 flex flex-wrap items-center gap-1.5">
                      {e.modelos.length === 0 ? (
                        <span className="text-xs text-slate-400">Nenhum modelo ligado</span>
                      ) : (
                        e.modelos.map((m) => (
                          <Selo key={m.modelo} tom={m.producao ? "azul" : "cinza"} titulo={m.producao ? "Emitindo com valor fiscal" : "Em homologação (teste)"}>
                            {MODELOS[m.modelo]}
                            {m.producao ? "" : " · teste"}
                          </Selo>
                        ))
                      )}
                      <span className="text-[11px] text-slate-400">{REGIMES[e.regime] ?? e.regime}</span>
                    </div>
                  </div>

                  <div className="w-full min-w-[200px] sm:w-56">
                    <div className="flex items-baseline justify-between gap-2 text-xs">
                      <span className="text-slate-500">Notas do mês</span>
                      <span className="tabular-nums text-slate-700">
                        <strong className="text-slate-900">{inteiro(e.usadas)}</strong> de {inteiro(e.entradas)}
                      </span>
                    </div>
                    <div className="mt-1.5">
                      <Barra valor={e.usadas + e.reservadas} maximo={e.entradas} />
                    </div>
                    <p className="mt-1.5 text-[11px] leading-4 text-slate-500">
                      {e.entradas === 0 ? "Sem pacote neste mês: não emite." : `${plural(Math.max(0, e.disponiveis), "disponível", "disponíveis")}`}
                      {e.reservadas > 0 ? ` · ${plural(e.reservadas, "em envio", "em envio")}` : ""}
                      {e.notasEmTeste > 0 ? ` · ${plural(e.notasEmTeste, "de teste", "de teste")}` : ""}
                    </p>
                  </div>
                </div>

                <div className="mt-3 flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t border-slate-100 pt-3">
                  <div className="flex min-w-0 flex-1 basis-[240px] flex-wrap items-center gap-2">
                    {certificado ? <Selo tom={certificado.tom}>{certificado.texto}</Selo> : null}
                    {e.ultimoErro ? (
                      <p className="min-w-0 flex-1 truncate text-xs text-rose-700" title={e.ultimoErro}>
                        Último erro na Spedy: {e.ultimoErro}
                      </p>
                    ) : null}
                    {!certificado && !e.ultimoErro ? <span className="text-xs text-slate-400">Sem certificado enviado</span> : null}
                  </div>
                  <div className="flex flex-wrap justify-end gap-2">
                    <button type="button" onClick={() => setCortesiaPara(e)} className={BOTAO_SECUNDARIO}>
                      <Gift size={15} />
                      Dar ou tirar notas
                    </button>
                    <button
                      type="button"
                      onClick={() => setSituacaoDe(e)}
                      className={
                        e.status === "suspenso"
                          ? "inline-flex h-10 items-center justify-center gap-2 rounded-xl border border-emerald-200 bg-white px-4 text-sm font-medium text-emerald-700 transition hover:bg-emerald-50"
                          : "inline-flex h-10 items-center justify-center gap-2 rounded-xl border border-rose-200 bg-white px-4 text-sm font-medium text-rose-600 transition hover:bg-rose-50"
                      }
                    >
                      {e.status === "suspenso" ? <PlayCircle size={15} /> : <PauseCircle size={15} />}
                      {e.status === "suspenso" ? "Reativar" : "Suspender"}
                    </button>
                  </div>
                </div>
              </li>
            );
          })}
        </ul>
      )}

      {cortesiaPara ? (
        <Cortesia
          emissor={cortesiaPara}
          ambiente={painel.ambiente}
          mes={mes}
          aoFechar={() => setCortesiaPara(null)}
          aoConcluir={async (texto) => {
            await aoMudar();
            avisar("ok", texto);
            setCortesiaPara(null);
          }}
        />
      ) : null}

      <Modal
        aberto={Boolean(situacaoDe)}
        aoFechar={() => (ocupado ? undefined : setSituacaoDe(null))}
        titulo={situacaoDe?.status === "suspenso" ? `Reativar ${situacaoDe?.empresaNome}?` : `Suspender ${situacaoDe?.empresaNome ?? ""}?`}
        descricao={
          situacaoDe?.status === "suspenso"
            ? "A empresa volta a emitir assim que a configuração dela estiver completa. Se faltar algo, ela vê o que falta na tela de configuração."
            : "Nenhuma nota nova sai desta empresa até você reativar, nem as automáticas do PDV e da loja. Notas já autorizadas continuam valendo e podem ser consultadas."
        }
        rodape={
          <>
            <button type="button" onClick={() => setSituacaoDe(null)} disabled={ocupado} className={BOTAO_SECUNDARIO}>
              Voltar
            </button>
            <button
              type="button"
              onClick={() => void mudarSituacao()}
              disabled={ocupado}
              className={
                situacaoDe?.status === "suspenso"
                  ? "inline-flex h-10 items-center justify-center rounded-xl bg-emerald-600 px-4 text-sm font-semibold text-white transition hover:bg-emerald-500 disabled:opacity-50"
                  : "inline-flex h-10 items-center justify-center rounded-xl bg-rose-600 px-4 text-sm font-semibold text-white transition hover:bg-rose-500 disabled:opacity-50"
              }
            >
              {ocupado ? "Salvando…" : situacaoDe?.status === "suspenso" ? "Reativar" : "Suspender emissão"}
            </button>
          </>
        }
      />
    </div>
  );
}

function Cortesia({
  emissor,
  ambiente,
  mes,
  aoFechar,
  aoConcluir,
}: {
  emissor: Emissor;
  ambiente: PainelFiscal["ambiente"];
  mes: string;
  aoFechar: () => void;
  aoConcluir: (texto: string) => Promise<void>;
}) {
  const [sentido, setSentido] = useState<"dar" | "tirar">("dar");
  const [quantidade, setQuantidade] = useState("");
  const [motivo, setMotivo] = useState("");
  const [enviando, setEnviando] = useState(false);
  const [erro, setErro] = useState<string | null>(null);

  const n = Number(quantidade);
  const disponiveis = Math.max(0, emissor.disponiveis);
  const valido = Number.isInteger(n) && n > 0 && motivo.trim().length >= 3 && (sentido === "dar" || n <= disponiveis);

  async function enviar() {
    if (!Number.isInteger(n) || n <= 0) return setErro("Informe quantas notas.");
    if (sentido === "tirar" && n > disponiveis) {
      return setErro(disponiveis > 0 ? `Dá para tirar no máximo ${plural(disponiveis, "nota", "notas")}.` : "Esta empresa não tem notas disponíveis para tirar.");
    }
    if (motivo.trim().length < 3) return setErro("Escreva o motivo: ele aparece no extrato da empresa.");
    setEnviando(true);
    setErro(null);
    try {
      await pedir("/api/fiscal/cortesia", {
        method: "POST",
        body: JSON.stringify({ empresaId: emissor.empresaId, ambiente, quantidade: sentido === "dar" ? n : -n, descricao: motivo.trim() }),
      });
      await aoConcluir(
        sentido === "dar"
          ? `${plural(n, "nota liberada", "notas liberadas")} para ${emissor.empresaNome}.`
          : `${plural(n, "nota retirada", "notas retiradas")} de ${emissor.empresaNome}.`
      );
    } catch (falha) {
      setErro(falha instanceof Error ? falha.message : "Não foi possível concluir.");
      setEnviando(false);
    }
  }

  return (
    <Modal
      aberto
      aoFechar={() => (enviando ? undefined : aoFechar())}
      titulo={`Notas para ${emissor.empresaNome}`}
      descricao={`Valem só em ${mes}, como os pacotes. Hoje: ${plural(disponiveis, "nota disponível", "notas disponíveis")}.`}
      rodape={
        <>
          <button type="button" onClick={aoFechar} disabled={enviando} className={BOTAO_SECUNDARIO}>
            Cancelar
          </button>
          <button type="button" onClick={() => void enviar()} disabled={enviando || !valido} className={BOTAO_PRIMARIO}>
            {enviando
              ? "Salvando…"
              : Number.isInteger(n) && n > 0
                ? `${sentido === "dar" ? "Dar" : "Tirar"} ${plural(n, "nota", "notas")}`
                : sentido === "dar"
                  ? "Dar notas"
                  : "Tirar notas"}
          </button>
        </>
      }
    >
      <form
        className="grid gap-4"
        onSubmit={(evento) => {
          evento.preventDefault();
          void enviar();
        }}
      >
        <div className="inline-flex w-full rounded-xl border border-slate-200 bg-slate-50 p-1" role="radiogroup" aria-label="Dar ou tirar">
          {(
            [
              ["dar", "Dar notas de cortesia"],
              ["tirar", "Tirar notas"],
            ] as const
          ).map(([chave, rotulo]) => (
            <button
              key={chave}
              type="button"
              role="radio"
              aria-checked={sentido === chave}
              onClick={() => {
                setSentido(chave);
                setErro(null);
              }}
              className={`h-9 flex-1 rounded-lg text-sm font-medium transition ${
                sentido === chave ? "bg-white text-slate-900 shadow-sm ring-1 ring-slate-200" : "text-slate-500 hover:text-slate-800"
              }`}
            >
              {rotulo}
            </button>
          ))}
        </div>

        <Campo rotulo="Quantas notas" ajuda={sentido === "tirar" ? `No máximo ${plural(disponiveis, "nota", "notas")}.` : undefined}>
          {(id) => (
            <input
              id={id}
              value={quantidade}
              onChange={(evento) => setQuantidade(evento.target.value.replace(/\D/g, "").slice(0, 5))}
              inputMode="numeric"
              placeholder="10"
              className={`${CLASSE_DO_CAMPO} max-w-[160px] tabular-nums`}
              autoFocus
            />
          )}
        </Campo>
        <Campo rotulo="Motivo" ajuda="Aparece no extrato de notas da empresa.">
          {(id) => (
            <input
              id={id}
              value={motivo}
              onChange={(evento) => setMotivo(evento.target.value.slice(0, 140))}
              placeholder={sentido === "dar" ? "Ex.: Cortesia de boas-vindas" : "Ex.: Ajuste de pacote liberado por engano"}
              className={CLASSE_DO_CAMPO}
            />
          )}
        </Campo>
        {erro ? <Recado tom="erro">{erro}</Recado> : null}
        <button type="submit" hidden aria-hidden tabIndex={-1} />
      </form>
    </Modal>
  );
}
