"use client";

import { useState } from "react";
import { PackagePlus, Pencil, Sparkles, Trash2 } from "lucide-react";

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

import type { Avisar } from "./painel-client";
import {
  BOTAO_PRIMARIO,
  BOTAO_SECUNDARIO,
  CLASSE_DO_CAMPO,
  Campo,
  decimalDoCampo,
  decimalParaCampo,
  Interruptor,
  Modal,
  moeda,
  pedir,
  plural,
  Recado,
  Selo,
} from "./ui";

type Rascunho = {
  id: string | null;
  nome: string;
  descricao: string;
  quantidade: string;
  preco: string;
  ordem: string;
  ativo: boolean;
  destaque: boolean;
};

const VAZIO: Rascunho = { id: null, nome: "", descricao: "", quantidade: "", preco: "", ordem: "0", ativo: true, destaque: false };

function paraRascunho(pacote: PacoteFiscal): Rascunho {
  return {
    id: pacote.id,
    nome: pacote.nome,
    descricao: pacote.descricao ?? "",
    quantidade: String(pacote.quantidade),
    preco: decimalParaCampo(pacote.preco),
    ordem: String(pacote.ordem ?? 0),
    ativo: pacote.ativo,
    destaque: pacote.destaque,
  };
}

function corpoDoPacote(pacote: PacoteFiscal | Rascunho) {
  return {
    nome: pacote.nome,
    descricao: pacote.descricao,
    quantidade: Number(pacote.quantidade),
    preco: typeof pacote.preco === "number" ? pacote.preco : decimalDoCampo(pacote.preco),
    ordem: Number(pacote.ordem) || 0,
    ativo: pacote.ativo,
    destaque: pacote.destaque,
  };
}

export default function AbaPacotes({ painel, aoMudar, avisar }: { painel: PainelFiscal; aoMudar: () => Promise<void>; avisar: Avisar }) {
  const { regras } = painel;
  const [rascunho, setRascunho] = useState<Rascunho | null>(null);
  const [salvando, setSalvando] = useState(false);
  const [erroDoForm, setErroDoForm] = useState<string | null>(null);
  const [excluindo, setExcluindo] = useState<PacoteFiscal | null>(null);
  const [ocupado, setOcupado] = useState<string>("");

  /* O custo de uma nota para a Ktalogu: dentro do plano (se todas forem usadas) e no excedente. */
  const custoNoPlano = regras.plano_spedy_notas > 0 ? regras.plano_spedy_valor / regras.plano_spedy_notas : 0;
  const custoExcedente = regras.plano_spedy_nota_excedente;
  const pacotes = painel.pacotes;
  const aVenda = pacotes.filter((p) => p.ativo).length;

  function abrir(pacote: PacoteFiscal | null) {
    setErroDoForm(null);
    setRascunho(pacote ? paraRascunho(pacote) : { ...VAZIO, ordem: String(pacotes.length) });
  }

  async function salvar() {
    if (!rascunho) return;
    const corpo = corpoDoPacote(rascunho);
    if (rascunho.nome.trim().length < 2) return setErroDoForm("Dê um nome ao pacote.");
    if (!Number.isInteger(corpo.quantidade) || corpo.quantidade < 1) return setErroDoForm("Informe quantas notas o pacote libera no mês.");
    if (!Number.isFinite(corpo.preco) || corpo.preco < 1) return setErroDoForm("O preço precisa ser de pelo menos R$ 1,00.");
    setSalvando(true);
    setErroDoForm(null);
    try {
      if (rascunho.id) {
        await pedir(`/api/fiscal/pacotes?id=${rascunho.id}`, { method: "PUT", body: JSON.stringify(corpo) });
      } else {
        await pedir(`/api/fiscal/pacotes`, { method: "POST", body: JSON.stringify(corpo) });
      }
      await aoMudar();
      avisar("ok", rascunho.id ? "Pacote atualizado." : "Pacote criado.");
      setRascunho(null);
    } catch (falha) {
      setErroDoForm(falha instanceof Error ? falha.message : "Não foi possível salvar o pacote.");
    } finally {
      setSalvando(false);
    }
  }

  async function alternarVenda(pacote: PacoteFiscal) {
    setOcupado(pacote.id);
    try {
      await pedir(`/api/fiscal/pacotes?id=${pacote.id}`, {
        method: "PUT",
        body: JSON.stringify(corpoDoPacote({ ...pacote, ativo: !pacote.ativo })),
      });
      await aoMudar();
      avisar("ok", pacote.ativo ? `"${pacote.nome}" saiu da venda.` : `"${pacote.nome}" está à venda.`);
    } catch (falha) {
      avisar("erro", falha instanceof Error ? falha.message : "Não foi possível mudar o pacote.");
    } finally {
      setOcupado("");
    }
  }

  async function excluir() {
    if (!excluindo) return;
    setOcupado(excluindo.id);
    try {
      await pedir(`/api/fiscal/pacotes?id=${excluindo.id}`, { method: "DELETE" });
      await aoMudar();
      avisar("ok", "Pacote excluído.");
      setExcluindo(null);
    } catch (falha) {
      avisar("erro", falha instanceof Error ? falha.message : "Não foi possível excluir o pacote.");
    } finally {
      setOcupado("");
    }
  }

  const previa = rascunho ? corpoDoPacote(rascunho) : null;
  const previaValida = previa && Number.isInteger(previa.quantidade) && previa.quantidade > 0 && Number.isFinite(previa.preco) && previa.preco > 0;
  const porNotaDaPrevia = previaValida ? previa.preco / previa.quantidade : 0;

  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">Pacotes à venda</h2>
          <p className="mt-0.5 max-w-2xl text-sm text-slate-500">
            As empresas compram na tela de Assinatura, pelo seu Mercado Pago. Cada pacote libera notas só para o mês da compra: o que sobrar
            não acumula.
          </p>
        </div>
        <button type="button" onClick={() => abrir(null)} className={BOTAO_PRIMARIO}>
          <PackagePlus size={16} />
          Novo pacote
        </button>
      </div>

      <div className="rounded-2xl border border-slate-200 bg-white px-5 py-4 text-sm leading-6 text-slate-600 shadow-sm">
        Cada nota custa para você <strong className="text-slate-900">{moeda(custoNoPlano, 3)}</strong> dentro do plano (se as{" "}
        {plural(regras.plano_spedy_notas, "nota", "notas")} forem usadas) e <strong className="text-slate-900">{moeda(custoExcedente, 3)}</strong>{" "}
        no excedente. A margem de cada pacote abaixo usa o excedente, que é o pior caso.
        {!regras.vendas_abertas ? (
          <span className="mt-2 block font-medium text-amber-800">A venda de pacotes está pausada nas Regras: ninguém consegue comprar agora.</span>
        ) : null}
      </div>

      {pacotes.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">Nenhum pacote cadastrado.</p>
          <p className="mx-auto mt-1 max-w-md text-xs leading-5 text-slate-500">
            Sem pacote à venda as empresas não conseguem comprar notas, e sem notas no mês não emitem. Crie pelo menos um.
          </p>
          <button type="button" onClick={() => abrir(null)} className={`${BOTAO_PRIMARIO} mt-5`}>
            <PackagePlus size={16} />
            Criar o primeiro pacote
          </button>
        </div>
      ) : (
        <div className="overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-sm">
          <div className="hidden grid-cols-[minmax(0,1fr)_90px_110px_110px_130px_150px] gap-4 border-b border-slate-100 bg-slate-50/70 px-5 py-2.5 text-[11px] font-semibold uppercase tracking-wider text-slate-500 lg:grid">
            <span>Pacote</span>
            <span className="text-right">Notas</span>
            <span className="text-right">Preço</span>
            <span className="text-right">Por nota</span>
            <span className="text-right">Margem por nota</span>
            <span className="text-right">À venda</span>
          </div>
          <ul className="divide-y divide-slate-100">
            {pacotes.map((pacote) => {
              const porNota = pacote.preco / pacote.quantidade;
              const margem = porNota - custoExcedente;
              return (
                <li
                  key={pacote.id}
                  className="grid gap-3 px-5 py-4 lg:grid-cols-[minmax(0,1fr)_90px_110px_110px_130px_150px] lg:items-center lg:gap-4"
                >
                  <div className="min-w-0">
                    <div className="flex flex-wrap items-center gap-2">
                      <span className="text-sm font-semibold text-slate-900">{pacote.nome}</span>
                      {pacote.destaque ? (
                        <Selo tom="violeta">
                          <Sparkles size={11} />
                          Mais escolhido
                        </Selo>
                      ) : null}
                      {!pacote.ativo ? <Selo tom="cinza">Fora da venda</Selo> : null}
                    </div>
                    {pacote.descricao ? <p className="mt-0.5 line-clamp-2 text-xs text-slate-500">{pacote.descricao}</p> : null}
                  </div>
                  <div className="flex flex-wrap gap-x-5 gap-y-1 text-sm lg:contents">
                    <span className="tabular-nums text-slate-700 lg:text-right">
                      <span className="text-slate-400 lg:hidden">Notas: </span>
                      {pacote.quantidade.toLocaleString("pt-BR")}
                    </span>
                    <span className="font-medium tabular-nums text-slate-900 lg:text-right">{moeda(pacote.preco)}</span>
                    <span className="tabular-nums text-slate-600 lg:text-right">
                      {moeda(porNota, 3)}
                      <span className="text-slate-400 lg:hidden"> por nota</span>
                    </span>
                    <span className={`font-medium tabular-nums lg:text-right ${margem >= 0 ? "text-emerald-700" : "text-rose-700"}`}>
                      {margem >= 0 ? "+" : ""}
                      {moeda(margem, 3)}
                      <span className="font-normal text-slate-400 lg:hidden"> de margem</span>
                    </span>
                  </div>
                  <div className="flex items-center justify-between gap-2 lg:justify-end">
                    <Interruptor
                      ligado={pacote.ativo}
                      rotulo={pacote.ativo ? `Tirar ${pacote.nome} da venda` : `Pôr ${pacote.nome} à venda`}
                      desabilitado={ocupado === pacote.id}
                      aoMudar={() => void alternarVenda(pacote)}
                    />
                    <div className="flex items-center gap-1">
                      <button
                        type="button"
                        onClick={() => abrir(pacote)}
                        aria-label={`Editar ${pacote.nome}`}
                        title="Editar"
                        className="inline-flex h-9 w-9 items-center justify-center rounded-lg text-slate-500 transition hover:bg-slate-100 hover:text-slate-900"
                      >
                        <Pencil size={15} />
                      </button>
                      <button
                        type="button"
                        onClick={() => setExcluindo(pacote)}
                        aria-label={`Excluir ${pacote.nome}`}
                        title="Excluir"
                        className="inline-flex h-9 w-9 items-center justify-center rounded-lg text-slate-400 transition hover:bg-rose-50 hover:text-rose-600"
                      >
                        <Trash2 size={15} />
                      </button>
                    </div>
                  </div>
                </li>
              );
            })}
          </ul>
          {aVenda === 0 ? (
            <div className="border-t border-slate-100 px-5 py-3 text-xs font-medium text-amber-800">
              Nenhum pacote está à venda: as empresas não veem o que comprar.
            </div>
          ) : null}
        </div>
      )}

      <Modal
        aberto={Boolean(rascunho)}
        aoFechar={() => (salvando ? undefined : setRascunho(null))}
        titulo={rascunho?.id ? "Editar pacote" : "Novo pacote"}
        descricao="Vale só no mês da compra. Mudar o preço não mexe em compras já feitas."
        rodape={
          <>
            <button type="button" onClick={() => setRascunho(null)} disabled={salvando} className={BOTAO_SECUNDARIO}>
              Cancelar
            </button>
            <button type="button" onClick={() => void salvar()} disabled={salvando} className={BOTAO_PRIMARIO}>
              {salvando ? "Salvando…" : rascunho?.id ? "Salvar pacote" : "Criar pacote"}
            </button>
          </>
        }
      >
        {rascunho ? (
          <form
            className="grid gap-4"
            onSubmit={(evento) => {
              evento.preventDefault();
              void salvar();
            }}
          >
            <Campo rotulo="Nome">
              {(id) => (
                <input
                  id={id}
                  value={rascunho.nome}
                  onChange={(e) => setRascunho({ ...rascunho, nome: e.target.value.slice(0, 60) })}
                  placeholder="Ex.: Essencial"
                  className={CLASSE_DO_CAMPO}
                  autoFocus
                />
              )}
            </Campo>
            <Campo rotulo="Descrição curta" ajuda="Opcional. Aparece no cartão do pacote.">
              {(id) => (
                <input
                  id={id}
                  value={rascunho.descricao}
                  onChange={(e) => setRascunho({ ...rascunho, descricao: e.target.value.slice(0, 160) })}
                  placeholder="Ex.: Para quem emite algumas notas por semana"
                  className={CLASSE_DO_CAMPO}
                />
              )}
            </Campo>
            <div className="grid gap-4 sm:grid-cols-2">
              <Campo rotulo="Notas no mês">
                {(id) => (
                  <input
                    id={id}
                    value={rascunho.quantidade}
                    onChange={(e) => setRascunho({ ...rascunho, quantidade: e.target.value.replace(/\D/g, "").slice(0, 6) })}
                    inputMode="numeric"
                    placeholder="100"
                    className={`${CLASSE_DO_CAMPO} tabular-nums`}
                  />
                )}
              </Campo>
              <Campo rotulo="Preço (R$)">
                {(id) => (
                  <input
                    id={id}
                    value={rascunho.preco}
                    onChange={(e) => setRascunho({ ...rascunho, preco: e.target.value.replace(/[^\d.,]/g, "").slice(0, 12) })}
                    onBlur={() => {
                      const valor = decimalDoCampo(rascunho.preco);
                      if (Number.isFinite(valor)) setRascunho({ ...rascunho, preco: decimalParaCampo(Math.round(valor * 100) / 100) });
                    }}
                    inputMode="decimal"
                    placeholder="49,90"
                    className={`${CLASSE_DO_CAMPO} tabular-nums`}
                  />
                )}
              </Campo>
            </div>

            <div className="rounded-xl border border-slate-200 bg-slate-50/70 px-4 py-3 text-sm">
              {previaValida ? (
                <div className="grid gap-1">
                  <p className="text-slate-700">
                    A empresa paga <strong className="text-slate-900">{moeda(porNotaDaPrevia, 3)}</strong> por nota.
                  </p>
                  <p className={porNotaDaPrevia - custoExcedente >= 0 ? "text-emerald-700" : "text-rose-700"}>
                    Margem de <strong>{moeda(porNotaDaPrevia - custoExcedente, 3)}</strong> por nota e até{" "}
                    <strong>{moeda((porNotaDaPrevia - custoExcedente) * previa.quantidade)}</strong> no pacote, contando a nota excedente da Spedy (
                    {moeda(custoExcedente, 3)}).
                  </p>
                </div>
              ) : (
                <p className="text-slate-500">Preencha notas e preço para ver quanto sai cada nota e a sua margem.</p>
              )}
            </div>

            <div className="grid gap-3">
              <label className="flex items-center justify-between gap-4 rounded-xl border border-slate-200 px-4 py-3">
                <span>
                  <span className="block text-sm font-medium text-slate-800">À venda</span>
                  <span className="block text-xs text-slate-500">Desligado, o pacote some da tela de Assinatura.</span>
                </span>
                <Interruptor ligado={rascunho.ativo} rotulo="À venda" aoMudar={(ativo) => setRascunho({ ...rascunho, ativo })} />
              </label>
              <label className="flex items-center justify-between gap-4 rounded-xl border border-slate-200 px-4 py-3">
                <span>
                  <span className="block text-sm font-medium text-slate-800">Mais escolhido</span>
                  <span className="block text-xs text-slate-500">Ganha destaque na vitrine. Só um pacote fica marcado.</span>
                </span>
                <Interruptor ligado={rascunho.destaque} rotulo="Mais escolhido" aoMudar={(destaque) => setRascunho({ ...rascunho, destaque })} />
              </label>
            </div>

            <Campo rotulo="Posição na vitrine" ajuda="Menor aparece primeiro. Empate: o de menos notas vem antes.">
              {(id) => (
                <input
                  id={id}
                  value={rascunho.ordem}
                  onChange={(e) => setRascunho({ ...rascunho, ordem: e.target.value.replace(/[^\d-]/g, "").replace(/(?!^)-/g, "").slice(0, 5) })}
                  inputMode="numeric"
                  className={`${CLASSE_DO_CAMPO} max-w-[140px] tabular-nums`}
                />
              )}
            </Campo>

            {erroDoForm ? <Recado tom="erro">{erroDoForm}</Recado> : null}
            <button type="submit" hidden aria-hidden tabIndex={-1} />
          </form>
        ) : null}
      </Modal>

      <Modal
        aberto={Boolean(excluindo)}
        aoFechar={() => setExcluindo(null)}
        titulo="Excluir este pacote?"
        descricao={
          excluindo ? (
            <>
              &ldquo;{excluindo.nome}&rdquo; sai da venda na hora. Compras já feitas continuam no histórico com o nome e o preço da época.
              Se a ideia é só pausar, desligue &ldquo;À venda&rdquo;.
            </>
          ) : null
        }
        rodape={
          <>
            <button type="button" onClick={() => setExcluindo(null)} className={BOTAO_SECUNDARIO}>
              Voltar
            </button>
            <button
              type="button"
              onClick={() => void excluir()}
              disabled={Boolean(excluindo && ocupado === excluindo.id)}
              className="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"
            >
              {excluindo && ocupado === excluindo.id ? "Excluindo…" : "Excluir pacote"}
            </button>
          </>
        }
      />
    </div>
  );
}
