"use client";

/*
 * Entrada, Contagem e Perda — a mesma janela, com a grade inteira para
 * lançar várias células de uma vez (P/M/G × Branca/Preta, cada uma com o seu
 * número). Item sem grade = um campo só.
 *
 * Contagem: o campo já vem com o saldo de agora; a pessoa troca pelo que
 * contou e vê a diferença ao lado. Só as células mexidas viram movimento.
 */

import { useMemo, useState } from "react";
import { Loader2, PackagePlus, ClipboardCheck, PackageMinus } from "lucide-react";
import { Janela } from "./gaveta";
import { CampoNumero } from "./primitivos";
import { Aviso } from "@/components/ui/aviso";
import { pedirJson } from "@/lib/estoque/use-estoque-v2";
import { desenharGrade, qtd, qtdComSinal, unidade, valoresDaCelula, dinheiro } from "@/lib/estoque/regras";
import type { Celula, ItemDoEstoque } from "@/lib/estoque/tipos";

export type ModoDoLancamento = "entrada" | "contagem" | "perda";

const TEXTOS: Record<ModoDoLancamento, { titulo: string; texto: string; botao: string; Icone: typeof PackagePlus }> = {
  entrada: {
    titulo: "Entrada",
    texto: "Chegou mercadoria sem pedido de compra? Diga quanto entrou em cada célula. Com custo, o custo médio do item se atualiza.",
    botao: "Dar entrada",
    Icone: PackagePlus,
  },
  contagem: {
    titulo: "Contagem",
    texto: "Escreva o que você contou na prateleira. O sistema acerta o saldo e guarda a diferença na linha do tempo.",
    botao: "Salvar contagem",
    Icone: ClipboardCheck,
  },
  perda: {
    titulo: "Perda",
    texto: "Quebrou, manchou, venceu? Diga quanto se perdeu em cada célula e o motivo.",
    botao: "Registrar perda",
    Icone: PackageMinus,
  },
};

export function JanelaDeLancamento({
  item,
  modo,
  celulaInicial,
  aoFechar,
  aoConcluir,
}: {
  item: ItemDoEstoque | null;
  modo: ModoDoLancamento | null;
  celulaInicial?: string | null;
  aoFechar: () => void;
  aoConcluir: (mensagem: string) => void;
}) {
  const aberta = Boolean(item && modo);
  const [chave, setChave] = useState("");
  const [valores, setValores] = useState<Record<string, number | undefined>>({});
  const [unidadeEscolhida, setUnidadeEscolhida] = useState("");
  const [custo, setCusto] = useState<number>(0);
  const [observacao, setObservacao] = useState("");
  const [todas, setTodas] = useState<number>(0);
  const [salvando, setSalvando] = useState(false);
  const [erro, setErro] = useState<string | null>(null);

  /* Abriu para outro item/modo: recomeça (ajuste de estado na renderização). */
  const chaveAgora = aberta ? `${item!.id}:${modo}:${celulaInicial ?? ""}` : "";
  if (chaveAgora !== chave) {
    setChave(chaveAgora);
    setErro(null);
    setObservacao("");
    setCusto(0);
    setTodas(0);
    setUnidadeEscolhida(item?.unidade ?? "");
    const inicio: Record<string, number | undefined> = {};
    if (item && modo === "contagem") for (const c of item.celulas) inicio[c.celula_id] = c.saldo;
    setValores(inicio);
  }

  const grade = useMemo(() => (item ? desenharGrade(item.grade, item.celulas) : null), [item]);
  const unidades = useMemo(() => {
    if (!item) return [];
    const lista = [item.unidade, ...item.conversoes.map((c) => c.unidade)];
    return Array.from(new Set(lista.filter(Boolean)));
  }, [item]);
  const fator = useMemo(() => {
    if (!item || !unidadeEscolhida || unidadeEscolhida === item.unidade) return 1;
    const c = item.conversoes.find((x) => x.unidade === unidadeEscolhida);
    return c ? Number(String(c.fator).replace(",", ".")) || 1 : 1;
  }, [item, unidadeEscolhida]);

  if (!item || !modo) return <Janela aberta={false} aoFechar={aoFechar} titulo="">{null}</Janela>;

  const t = TEXTOS[modo];
  const celulas = item.celulas;
  const mexidas = celulas.filter((c) => {
    const v = valores[c.celula_id];
    if (v === undefined) return false;
    return modo === "contagem" ? Math.abs(v - c.saldo) > 0.00001 : v > 0;
  });
  const total = mexidas.reduce((s, c) => s + (modo === "contagem" ? (valores[c.celula_id] ?? 0) - c.saldo : valores[c.celula_id] ?? 0), 0);

  function preencherTodas() {
    const novo: Record<string, number | undefined> = { ...valores };
    for (const c of celulas) novo[c.celula_id] = todas;
    setValores(novo);
  }

  async function salvar() {
    if (!mexidas.length) {
      setErro(modo === "contagem" ? "Nenhuma célula mudou: o que você contou é igual ao saldo." : "Informe a quantidade de pelo menos uma célula.");
      return;
    }
    setSalvando(true);
    setErro(null);
    try {
      if (modo === "contagem") {
        const r = await pedirJson<{ mudou: number }>("/api/estoque/contar", {
          method: "POST",
          corpo: { linhas: mexidas.map((c) => ({ celula_id: c.celula_id, saldo: valores[c.celula_id] })), observacao: observacao || null },
        });
        aoConcluir(`Contagem salva: ${r.mudou} ${r.mudou === 1 ? "célula acertada" : "células acertadas"}.`);
      } else {
        await pedirJson("/api/estoque/lancar", {
          method: "POST",
          corpo: {
            tipo: modo,
            linhas: mexidas.map((c) => ({ celula_id: c.celula_id, quantidade: valores[c.celula_id] })),
            unidade: unidadeEscolhida && unidadeEscolhida !== item!.unidade ? unidadeEscolhida : null,
            custo: modo === "entrada" && custo > 0 ? custo : null,
            observacao: observacao || null,
          },
        });
        aoConcluir(
          modo === "entrada"
            ? `Entrada de ${qtd(total * fator)} ${unidade(item!.unidade)} em ${item!.nome}.`
            : `Perda de ${qtd(total * fator)} ${unidade(item!.unidade)} registrada.`
        );
      }
    } catch (e) {
      const dados = (e as { dados?: { feitos?: number; total?: number } }).dados;
      setErro(
        dados?.feitos
          ? `${dados.feitos} de ${dados.total} células entraram; a seguinte parou: ${(e as Error).message}`
          : (e as Error).message
      );
    } finally {
      setSalvando(false);
    }
  }

  function campo(c: Celula | null, rotulo: string) {
    if (!c) return <span className="block text-center text-xs text-slate-300">—</span>;
    const v = valores[c.celula_id];
    const diferenca = modo === "contagem" && v !== undefined ? v - c.saldo : 0;
    return (
      <div className="min-w-[88px]">
        <CampoNumero
          valor={v ?? 0}
          zeroVazio={modo !== "contagem"}
          aoMudar={(n) => setValores((a) => ({ ...a, [c.celula_id]: n }))}
          rotulo={`${t.titulo} de ${rotulo}`}
          autoFocus={celulaInicial === c.celula_id}
          destaque={celulaInicial === c.celula_id}
          permiteNegativo={modo === "contagem"}
        />
        <p className="mt-1 text-right text-[11px] text-[var(--ks-color-text-soft)]">
          {modo === "contagem" ? (
            Math.abs(diferenca) > 0.00001 ? (
              <span className={diferenca > 0 ? "font-semibold text-emerald-600" : "font-semibold text-rose-600"}>
                {qtdComSinal(diferenca)} (era {qtd(c.saldo)})
              </span>
            ) : (
              <>tem {qtd(c.saldo)}</>
            )
          ) : (
            <>tem {qtd(c.saldo)}</>
          )}
        </p>
      </div>
    );
  }

  return (
    <Janela
      aberta={aberta}
      aoFechar={aoFechar}
      largura={grade && grade.colunas.length > 3 ? 860 : 640}
      titulo={
        <span className="flex items-center gap-2">
          <t.Icone className="h-5 w-5 text-[var(--ks-color-primary)]" />
          {t.titulo} · {item.nome}
        </span>
      }
      texto={t.texto}
      rodape={
        <>
          <span className="mr-auto text-sm text-[var(--ks-color-text-muted)]">
            {mexidas.length ? (
              <>
                {mexidas.length} {mexidas.length === 1 ? "célula" : "células"} ·{" "}
                <strong className="text-[var(--ks-color-text-primary)]">
                  {modo === "contagem" ? qtdComSinal(total) : qtd(total)} {unidade(modo === "contagem" ? item.unidade : unidadeEscolhida || item.unidade)}
                </strong>
                {modo !== "contagem" && fator !== 1 ? ` = ${qtd(total * fator)} ${unidade(item.unidade)}` : null}
              </>
            ) : (
              "Nada lançado ainda"
            )}
          </span>
          <button type="button" onClick={aoFechar} className="ks-button ks-button-secondary">
            Cancelar
          </button>
          <button type="button" onClick={() => void salvar()} disabled={salvando} className={`ks-button ${modo === "perda" ? "bg-[#e13a58] text-white" : "ks-button-primary"}`}>
            {salvando ? <Loader2 size={15} className="animate-spin" /> : null}
            {t.botao}
          </button>
        </>
      }
    >
      <div className="space-y-4">
        {modo !== "contagem" && celulas.length > 1 ? (
          <div className="flex flex-wrap items-end gap-2 rounded-xl bg-[var(--ks-color-bg-subtle)]/60 p-3">
            <label className="min-w-[140px] flex-1 text-xs font-medium text-[var(--ks-color-text-soft)]">
              Mesma quantidade em todas as células
              <CampoNumero valor={todas} aoMudar={setTodas} rotulo="Quantidade para todas" className="mt-1" />
            </label>
            <button type="button" onClick={preencherTodas} className="ks-button ks-button-secondary ks-button-sm">
              Preencher
            </button>
          </div>
        ) : null}

        {grade && grade.eixoDasColunas ? (
          <div className="-mx-1 overflow-x-auto px-1">
            <table className="w-full border-separate border-spacing-x-2 border-spacing-y-1.5">
              <thead>
                <tr>
                  <th className="text-left text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-400">
                    {grade.eixoDasLinhas} \ {grade.eixoDasColunas}
                  </th>
                  {grade.colunas.map((col) => (
                    <th key={String(col)} className="text-right text-xs font-semibold text-[var(--ks-color-text-secondary)]">
                      {col}
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {grade.linhas.map((linha) => (
                  <tr key={String(linha.valor)}>
                    <td className="whitespace-nowrap pr-2 align-top pt-2.5 text-sm font-semibold text-[var(--ks-color-text-primary)]">{linha.valor}</td>
                    {linha.celulas.map((x) => (
                      <td key={String(x.coluna)} className="align-top">
                        {campo(x.celula, `${linha.valor} / ${x.coluna}`)}
                      </td>
                    ))}
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        ) : (
          <div className="grid gap-3 sm:grid-cols-2">
            {(grade?.linhas ?? []).map((linha) => (
              <label key={String(linha.valor)} className="flex items-start justify-between gap-3 rounded-xl border border-[var(--ks-color-border-subtle)] px-3 py-2.5">
                <span className="pt-2 text-sm font-semibold text-[var(--ks-color-text-primary)]">
                  {linha.valor ?? "Quantidade"}
                  {grade?.eixoDasLinhas ? <span className="block text-[11px] font-normal text-[var(--ks-color-text-soft)]">{grade.eixoDasLinhas}</span> : null}
                </span>
                {campo(linha.celulas[0].celula, linha.valor ?? item.nome)}
              </label>
            ))}
          </div>
        )}

        {grade && grade.foraDaGrade.length ? (
          <Aviso tom="neutro" titulo="Células fora da grade, ainda com saldo">
            {grade.foraDaGrade.map((c) => `${valoresDaCelula(c)}: ${qtd(c.saldo)}`).join(" · ")}. Conte (zere) para elas saírem de vez.
            <div className="mt-2 grid gap-2 sm:grid-cols-3">{grade.foraDaGrade.map((c) => <div key={c.celula_id}>{campo(c, valoresDaCelula(c))}</div>)}</div>
          </Aviso>
        ) : null}

        <div className="grid gap-3 sm:grid-cols-2">
          {modo === "entrada" ? (
            <>
              {unidades.length > 1 ? (
                <label className="text-xs font-medium text-[var(--ks-color-text-soft)]">
                  Contei em
                  <select value={unidadeEscolhida} onChange={(e) => setUnidadeEscolhida(e.target.value)} className="ks-field mt-1">
                    {unidades.map((u) => {
                      const c = item.conversoes.find((x) => x.unidade === u);
                      return (
                        <option key={u} value={u}>
                          {unidade(u)}
                          {c ? ` (1 = ${qtd(Number(String(c.fator).replace(",", ".")))} ${unidade(item.unidade)})` : ""}
                        </option>
                      );
                    })}
                  </select>
                </label>
              ) : null}
              <label className="text-xs font-medium text-[var(--ks-color-text-soft)]">
                Custo por {unidade(unidadeEscolhida || item.unidade)} (opcional)
                <CampoNumero valor={custo} aoMudar={setCusto} rotulo="Custo por unidade" sufixo="R$" className="mt-1" />
                <span className="mt-1 block text-[11px] text-[var(--ks-color-text-soft)]">Custo médio de hoje: {dinheiro(item.custo_medio)} por {unidade(item.unidade)}</span>
              </label>
            </>
          ) : null}
          <label className={`text-xs font-medium text-[var(--ks-color-text-soft)] ${modo === "entrada" && unidades.length > 1 ? "sm:col-span-2" : ""}`}>
            {modo === "perda" ? "Motivo" : "Observação"} {modo === "perda" ? "" : "(opcional)"}
            <input
              value={observacao}
              onChange={(e) => setObservacao(e.target.value)}
              placeholder={modo === "perda" ? "Ex.: manchou na prensa" : modo === "contagem" ? "Ex.: inventário de outubro" : "Ex.: nota 1234"}
              className="ks-field mt-1"
              maxLength={300}
            />
          </label>
        </div>

        {erro ? (
          <Aviso tom="ruim" aoFechar={() => setErro(null)}>
            {erro}
          </Aviso>
        ) : null}
      </div>
    </Janela>
  );
}
