"use client";

/*
 * A gaveta de um item do estoque: a grade com o saldo de cada célula, os
 * botões do dia a dia (Entrada, Contagem, Perda, Registrar produção), quem
 * usa o item e a linha do tempo com a origem de cada movimento.
 *
 * Produto pronto: cada célula mostra qual variação do catálogo sai dela.
 */

import { useCallback, useEffect, useMemo, useState, type ReactNode } from "react";
import Link from "next/link";
import {
  ClipboardCheck,
  Factory,
  Loader2,
  PackageMinus,
  PackagePlus,
  Pencil,
  Settings2,
  ExternalLink,
  History,
  Grid3x3,
  Boxes,
  Undo2,
} from "lucide-react";
import { Gaveta } from "./gaveta";
import { JanelaDeLancamento, type ModoDoLancamento } from "./lancamento";
import { FormularioDoItem } from "./formulario-do-item";
import { RegistrarProducao } from "./registrar-producao";
import { LinhaDoTempo } from "./linha-do-tempo";
import { JanelaDaProducao } from "./janela-da-producao";
import { RostoDoItem, Saldo, SeloDaSituacao, situacaoDoSaldo } from "./primitivos";
import { ModalDeInsumo } from "@/components/producao/modal-de-insumo";
import { Aviso } from "@/components/ui/aviso";
import { pedirJson, type SituacaoDoEstoque } from "@/lib/estoque/use-estoque-v2";
import {
  celulaDaEscolha,
  combinacoesParaAGrade,
  desenharGrade,
  dinheiro,
  escolhasDaCombinacao,
  qtd,
  resumoDaGrade,
  textoDaCombinacao,
  textoQuandoSai,
  unidade,
  normalizar,
  valoresDaCelula,
} from "@/lib/estoque/regras";
import type { AtributoDoProduto, Celula, ItemDoEstoque, LinhaDoMapa } from "@/lib/estoque/tipos";

type ProdutoLigado = { id: string; nome: string; atributos: AtributoDoProduto[]; mapa: LinhaDoMapa[] };
type ProducaoRecente = { id: string; quantidade: number; criado_em: string; desfeita_em: string | null; produto: string | null; celula: Celula | null };

const DATA = new Intl.DateTimeFormat("pt-BR", { day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit" });

function Secao({ Icone, titulo, texto, acao, children }: { Icone: typeof Boxes; titulo: string; texto?: string; acao?: ReactNode; children: ReactNode }) {
  return (
    <section className="border-t border-[var(--ks-color-border-subtle)] px-5 pb-4 pt-5 first:border-t-0 sm:px-6">
      <header className="mb-3 flex flex-wrap items-start justify-between gap-3">
        <div className="flex min-w-0 items-start gap-3">
          <span
            className="flex h-8 w-8 shrink-0 items-center justify-center rounded-xl text-white"
            style={{ background: "linear-gradient(135deg, var(--ks-brand-500) 0%, var(--ks-brand-700) 100%)", boxShadow: "0 6px 16px rgba(95, 49, 214, 0.24)" }}
          >
            <Icone size={16} />
          </span>
          <div className="min-w-0">
            <h3 className="text-[15px] font-extrabold tracking-tight text-[var(--ks-color-text-primary)]">{titulo}</h3>
            {texto ? <p className="text-[12.5px] leading-5 text-[var(--ks-color-text-muted)]">{texto}</p> : null}
          </div>
        </div>
        {acao}
      </header>
      {children}
    </section>
  );
}

export function GavetaDoItem({
  itemId,
  situacao,
  aoFechar,
  aoMudar,
}: {
  itemId: string | null;
  situacao: SituacaoDoEstoque;
  aoFechar: () => void;
  /** O item mudou (saldo, dados): a lista recarrega. */
  aoMudar: () => void;
}) {
  const [item, setItem] = useState<ItemDoEstoque | null>(null);
  const [erro, setErro] = useState<string | null>(null);
  const [aviso, setAviso] = useState<string | null>(null);
  const [lancamento, setLancamento] = useState<{ modo: ModoDoLancamento; celula?: string | null } | null>(null);
  const [editando, setEditando] = useState(false);
  const [dadosDeCompra, setDadosDeCompra] = useState(false);
  const [produzindo, setProduzindo] = useState(false);
  const [celulaEscolhida, setCelulaEscolhida] = useState<string | null>(null);
  const [recarregar, setRecarregar] = useState(0);
  const [ligados, setLigados] = useState<ProdutoLigado[]>([]);
  const [producoes, setProducoes] = useState<ProducaoRecente[]>([]);
  const [producaoAberta, setProducaoAberta] = useState<string | null>(null);

  const carregar = useCallback(async () => {
    if (!itemId) return;
    try {
      const r = await pedirJson<{ itens: ItemDoEstoque[] }>(`/api/estoque/itens?id=${itemId}`);
      setItem(r.itens[0] ?? null);
      if (!r.itens[0]) setErro("Item não encontrado.");
    } catch (e) {
      setErro((e as Error).message);
    }
  }, [itemId]);

  useEffect(() => {
    setItem(null);
    setErro(null);
    setAviso(null);
    setCelulaEscolhida(null);
    setLigados([]);
    setProducoes([]);
    void carregar();
  }, [carregar]);

  /* Produto pronto: os produtos do catálogo que saem dele, com atributos e
     troca manual, para cada célula dizer qual variação a usa. */
  const idsLigados = useMemo(() => (item?.usos ?? []).filter((u) => u.como === "pronto").map((u) => u.produto_id), [item]);
  useEffect(() => {
    if (!item || item.papel !== "pronto") return;
    let vivo = true;
    Promise.all(
      idsLigados.slice(0, 6).map((id) =>
        pedirJson<{ produto: { id: string; nome: string; mapa: LinhaDoMapa[] }; atributos: AtributoDoProduto[] }>(`/api/estoque/produto/${id}`)
          .then((r) => ({ id, nome: r.produto.nome, atributos: r.atributos, mapa: r.produto.mapa }))
          .catch(() => null)
      )
    ).then((lista) => vivo && setLigados(lista.filter((x): x is ProdutoLigado => Boolean(x))));
    pedirJson<{ producoes: ProducaoRecente[] }>(`/api/estoque/producao?item=${item.id}`)
      .then((r) => vivo && setProducoes(r.producoes ?? []))
      .catch(() => undefined);
    return () => {
      vivo = false;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [item?.id, item?.papel, idsLigados.join(","), recarregar]);

  const quemUsaACelula = useMemo(() => {
    const mapa = new Map<string, string[]>();
    if (!item) return mapa;
    for (const p of ligados) {
      for (const comb of combinacoesParaAGrade(p.atributos, item.grade)) {
        const r = celulaDaEscolha(item.grade, item.celulas, escolhasDaCombinacao(comb), p.mapa);
        if (!r.celula) continue;
        const arr = mapa.get(r.celula.celula_id) ?? [];
        /* Variação com o mesmo nome da célula: basta o nome do produto. */
        const mesma = normalizar(textoDaCombinacao(comb)) === normalizar(valoresDaCelula(r.celula));
        /* Um produto só e a variação com o mesmo nome da célula: nada a dizer
           (a seção "Vendido como" já mostra o produto). */
        if (mesma && ligados.length === 1) continue;
        const texto = mesma ? p.nome : `${p.nome}: ${textoDaCombinacao(comb)}`;
        if (!arr.includes(texto)) arr.push(texto);
        mapa.set(r.celula.celula_id, arr);
      }
    }
    return mapa;
  }, [item, ligados]);

  function depoisDeMexer(mensagem: string) {
    setLancamento(null);
    setAviso(mensagem);
    setRecarregar((n) => n + 1);
    void carregar();
    aoMudar();
  }

  const grade = item ? desenharGrade(item.grade, item.celulas) : null;
  const saldoTotal = item ? item.celulas.reduce((s, c) => s + c.saldo, 0) : 0;
  const pode = situacao.podeEscrever;

  function quadrado(c: Celula | null, rotulo: string) {
    if (!c) return <div className="flex h-[68px] items-center justify-center rounded-xl border border-dashed border-slate-200 text-xs text-slate-300">—</div>;
    const s = situacaoDoSaldo(c.saldo, c.minimo, c.controla);
    const usos = quemUsaACelula.get(c.celula_id) ?? [];
    const escolhida = celulaEscolhida === c.celula_id;
    return (
      <button
        type="button"
        onClick={() => setCelulaEscolhida(escolhida ? null : c.celula_id)}
        title={`${rotulo}: ${qtd(c.saldo)} ${unidade(c.unidade)}${usos.length ? ` · ${usos.join(", ")}` : ""}`}
        className={`group flex h-full min-h-[68px] w-full flex-col items-stretch justify-between rounded-xl border px-2.5 py-2 text-left transition-all ${
          escolhida
            ? "border-[var(--ks-brand-600)] bg-[var(--ks-brand-50)] shadow-[0_6px_18px_-8px_rgba(95,49,214,0.6)]"
            : "border-[var(--ks-color-border-subtle)] bg-white hover:border-[var(--ks-brand-300)]"
        }`}
      >
        <span
          className={`ks-num text-lg font-extrabold tabular-nums leading-none ${
            s === "negativo" || s === "zerado" ? "text-rose-600" : s === "minimo" ? "text-violet-700" : "text-[var(--ks-color-text-primary)]"
          }`}
        >
          {qtd(c.saldo)}
        </span>
        {usos.length ? (
          <span className="mt-1 line-clamp-2 text-[10px] leading-tight text-[var(--ks-color-text-soft)]">{usos.slice(0, 3).join(" · ")}{usos.length > 3 ? "…" : ""}</span>
        ) : (
          <span className="mt-1 text-[10px] text-[var(--ks-color-text-soft)]">{s === "minimo" ? "abaixo do mínimo" : s === "zerado" ? "sem estoque" : s === "negativo" ? "negativo" : unidade(c.unidade)}</span>
        )}
      </button>
    );
  }

  const celulaSel = item?.celulas.find((c) => c.celula_id === celulaEscolhida) ?? null;
  const produtosParaProduzir = (item?.usos ?? []).filter((u) => u.como === "pronto").map((u) => ({ id: u.produto_id, nome: u.produto }));

  return (
    <>
      <Gaveta
        aberta={Boolean(itemId)}
        aoFechar={aoFechar}
        rotulo={item ? `Item ${item.nome}` : "Item do estoque"}
        largura={820}
        sobretitulo={item ? (item.papel === "pronto" ? "Produto pronto" : "Insumo") : "Estoque"}
        titulo={
          item ? (
            <span className="flex items-center gap-2.5">
              <RostoDoItem nome={item.nome} papel={item.papel} tamanho={30} />
              <span className="truncate">{item.nome}</span>
            </span>
          ) : (
            "Carregando…"
          )
        }
        subtitulo={
          item ? (
            <span className="flex flex-wrap items-center gap-x-3 gap-y-1">
              <span>
                Saldo <Saldo valor={saldoTotal} un={item.unidade} />
              </span>
              <span>· custo médio {dinheiro(item.custo_medio)} / {unidade(item.unidade)}</span>
              {item.minimo !== null ? <span>· mínimo {qtd(item.minimo)}</span> : null}
              {item.perda ? <span>· perda padrão {qtd(item.perda)}%</span> : null}
              {item.conversoes.map((c) => (
                <span key={c.unidade}>
                  · 1 {c.unidade} = {qtd(Number(String(c.fator).replace(",", ".")))} {unidade(item.unidade)}
                </span>
              ))}
              {!item.controla ? <SeloDaSituacao situacao="sem_controle" texto="não controla (só custo)" /> : null}
              {item.permitir_negativo ? <span className="text-[11px] text-[var(--ks-color-text-soft)]">· pode ficar negativo</span> : <span className="text-[11px] text-[var(--ks-color-text-soft)]">· para no zero</span>}
            </span>
          ) : null
        }
        topo={
          item && pode ? (
            <div className="flex flex-wrap gap-2">
              <button type="button" onClick={() => setLancamento({ modo: "entrada", celula: celulaEscolhida })} className="ks-button ks-button-primary ks-button-sm">
                <PackagePlus size={15} /> Entrada
              </button>
              <button type="button" onClick={() => setLancamento({ modo: "contagem", celula: celulaEscolhida })} className="ks-button ks-button-secondary ks-button-sm">
                <ClipboardCheck size={15} /> Contagem
              </button>
              <button type="button" onClick={() => setLancamento({ modo: "perda", celula: celulaEscolhida })} className="ks-button ks-button-secondary ks-button-sm">
                <PackageMinus size={15} /> Perda
              </button>
              {item.papel === "pronto" && produtosParaProduzir.length ? (
                <button type="button" onClick={() => setProduzindo(true)} className="ks-button ks-button-secondary ks-button-sm">
                  <Factory size={15} /> Registrar produção
                </button>
              ) : null}
              {situacao.podeCadastrar ? (
                <button type="button" onClick={() => setEditando(true)} className="ks-button ks-button-ghost ks-button-sm">
                  <Pencil size={14} /> Dados e grade
                </button>
              ) : null}
              {situacao.podeCadastrar && item.papel === "insumo" ? (
                <button type="button" onClick={() => setDadosDeCompra(true)} className="ks-button ks-button-ghost ks-button-sm" title="Bobina, folha, embalagem: o que a conta da composição usa">
                  <Settings2 size={14} /> Compra e consumo
                </button>
              ) : null}
            </div>
          ) : null
        }
      >
        {erro ? (
          <div className="p-5">
            <Aviso tom="ruim">{erro}</Aviso>
          </div>
        ) : !item ? (
          <div className="flex justify-center py-16">
            <Loader2 className="h-7 w-7 animate-spin text-[var(--ks-color-primary)]" />
          </div>
        ) : (
          <div>
            {aviso ? (
              <div className="px-5 pt-4 sm:px-6">
                <Aviso tom="bom" aoFechar={() => setAviso(null)}>
                  {aviso}
                </Aviso>
              </div>
            ) : null}

            <Secao
              Icone={Grid3x3}
              titulo={grade?.eixoDasLinhas ? `Grade · ${resumoDaGrade(item.grade)}` : "Saldo"}
              texto={
                grade?.eixoDasLinhas
                  ? "Cada célula tem o seu saldo; o total é a soma. Toque numa célula para lançar só nela e ver a linha do tempo dela."
                  : "Sem grade: um saldo só. Precisa separar por tamanho ou cor? Em Dados e grade."
              }
            >
              {grade?.eixoDasColunas ? (
                <div className="-mx-1 overflow-x-auto px-1 pb-1">
                  <table className="border-separate border-spacing-1.5">
                    <thead>
                      <tr>
                        <th className="w-16 text-left text-[10px] font-semibold uppercase tracking-[0.12em] text-slate-400" />
                        {grade.colunas.map((col) => (
                          <th key={String(col)} className="w-[132px] min-w-[96px] text-left text-xs font-semibold text-[var(--ks-color-text-secondary)]">
                            {col}
                          </th>
                        ))}
                        <th className="w-14 text-right text-[10px] font-semibold uppercase tracking-[0.12em] text-slate-400">Total</th>
                      </tr>
                    </thead>
                    <tbody>
                      {grade.linhas.map((linha) => (
                        <tr key={String(linha.valor)}>
                          <td className="whitespace-nowrap pr-1 text-sm font-bold text-[var(--ks-color-text-primary)]">{linha.valor}</td>
                          {linha.celulas.map((x) => (
                            <td key={String(x.coluna)} className="h-[68px]">
                              {quadrado(x.celula, `${linha.valor} / ${x.coluna}`)}
                            </td>
                          ))}
                          <td className="ks-num text-right text-sm font-bold tabular-nums text-[var(--ks-color-text-secondary)]">
                            {qtd(linha.celulas.reduce((s, x) => s + (x.celula?.saldo ?? 0), 0))}
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              ) : grade?.eixoDasLinhas ? (
                <div className="grid grid-cols-2 gap-2 sm:grid-cols-4 lg:grid-cols-6">
                  {grade.linhas.map((linha) => (
                    <div key={String(linha.valor)}>
                      <p className="mb-1 text-xs font-bold text-[var(--ks-color-text-secondary)]">{linha.valor}</p>
                      {quadrado(linha.celulas[0].celula, String(linha.valor))}
                    </div>
                  ))}
                </div>
              ) : (
                <div className="max-w-[220px]">{quadrado(grade?.linhas[0]?.celulas[0]?.celula ?? null, item.nome)}</div>
              )}

              {celulaSel ? (
                <div className="mt-3 flex flex-wrap items-center gap-2 rounded-xl bg-[var(--ks-brand-50)] px-3 py-2">
                  <span className="mr-auto text-sm font-semibold text-[var(--ks-brand-700)]">
                    {celulaSel.rotulo}: {qtd(celulaSel.saldo)} {unidade(celulaSel.unidade)}
                  </span>
                  {pode ? (
                    <>
                      <button type="button" onClick={() => setLancamento({ modo: "entrada", celula: celulaSel.celula_id })} className="ks-button ks-button-secondary ks-button-sm">
                        <PackagePlus size={14} /> Entrada
                      </button>
                      <button type="button" onClick={() => setLancamento({ modo: "contagem", celula: celulaSel.celula_id })} className="ks-button ks-button-secondary ks-button-sm">
                        <ClipboardCheck size={14} /> Contar
                      </button>
                      <button type="button" onClick={() => setLancamento({ modo: "perda", celula: celulaSel.celula_id })} className="ks-button ks-button-secondary ks-button-sm">
                        <PackageMinus size={14} /> Perda
                      </button>
                    </>
                  ) : null}
                </div>
              ) : null}

              {grade && grade.foraDaGrade.length ? (
                <Aviso tom="atencao" className="mt-3" titulo="Saldo em célula que saiu da grade">
                  {grade.foraDaGrade.map((c) => `${c.rotulo}: ${qtd(c.saldo)}`).join(" · ")}. Faça a contagem dessas células (zerar) para limpar.
                </Aviso>
              ) : null}
            </Secao>

            <Secao
              Icone={Boxes}
              titulo={item.papel === "pronto" ? "Vendido como" : "Quem usa"}
              texto={
                item.papel === "pronto"
                  ? "Produtos do catálogo que saem deste item quando vendem."
                  : "Produtos cuja composição tira este insumo do estoque (na venda sob encomenda ou na produção)."
              }
            >
              {(item.usos ?? []).length === 0 ? (
                <p className="text-sm text-[var(--ks-color-text-muted)]">
                  {item.papel === "pronto"
                    ? "Nenhum produto ligado ainda. Abra o produto, aba Estoque, e escolha “Produto pronto”."
                    : "Nenhuma composição usa este insumo. Ele só se mexe por entrada, contagem e perda."}
                </p>
              ) : (
                <ul>
                  {(item.usos ?? []).map((u) => (
                    <li key={`${u.produto_id}-${u.como}`} className="flex items-center justify-between gap-3 border-t border-slate-100/60 py-2 first:border-t-0">
                      <Link href={`/dashboard/products/${u.produto_id}`} className="min-w-0 truncate text-sm font-semibold text-[var(--ks-color-text-primary)] hover:text-[var(--ks-color-primary)]">
                        {u.produto}
                      </Link>
                      <span className="flex shrink-0 items-center gap-2 text-xs text-[var(--ks-color-text-muted)]">
                        {u.como === "pronto" ? "sai daqui na venda" : u.como === "receita" ? "receita da opção" : textoQuandoSai({ quando_sai: u.quando_sai })}
                        <ExternalLink size={12} />
                      </span>
                    </li>
                  ))}
                </ul>
              )}
            </Secao>

            {item.papel === "pronto" && producoes.length ? (
              <Secao Icone={Factory} titulo="Produções recentes" texto="O que entrou aqui por produção. Desfazer devolve os insumos (se as peças ainda não saíram).">
                <ul>
                  {producoes.slice(0, 8).map((p) => (
                    <li key={p.id} className="flex items-center justify-between gap-3 border-t border-slate-100/60 py-2 first:border-t-0">
                      <button type="button" onClick={() => setProducaoAberta(p.id)} className="min-w-0 text-left text-sm hover:text-[var(--ks-color-primary)]">
                        <span className={`font-semibold ${p.desfeita_em ? "text-slate-400 line-through" : "text-[var(--ks-color-text-primary)]"}`}>
                          +{qtd(p.quantidade)} {p.celula ? `em ${p.celula.rotulo}` : ""}
                        </span>
                        <span className="block text-xs text-[var(--ks-color-text-muted)]">{DATA.format(new Date(p.criado_em))}{p.desfeita_em ? " · desfeita" : ""}</span>
                      </button>
                      {!p.desfeita_em && pode ? (
                        <button type="button" onClick={() => setProducaoAberta(p.id)} className="ks-button ks-button-ghost ks-button-sm">
                          <Undo2 size={14} /> Ver / desfazer
                        </button>
                      ) : null}
                    </li>
                  ))}
                </ul>
              </Secao>
            ) : null}

            <Secao
              Icone={History}
              titulo={celulaSel ? `Linha do tempo · ${celulaSel.rotulo}` : "Linha do tempo"}
              texto="Tudo que entrou e saiu, com a origem: clique no pedido, na compra ou na produção para abrir."
              acao={
                celulaSel ? (
                  <button type="button" onClick={() => setCelulaEscolhida(null)} className="ks-button ks-button-ghost ks-button-sm">
                    Ver o item todo
                  </button>
                ) : null
              }
            >
              <LinhaDoTempo item={item.id} celula={celulaEscolhida} recarregar={recarregar} aoAbrirProducao={setProducaoAberta} compacta />
            </Secao>
          </div>
        )}
      </Gaveta>

      <JanelaDeLancamento
        item={lancamento ? item : null}
        modo={lancamento?.modo ?? null}
        celulaInicial={lancamento?.celula ?? null}
        aoFechar={() => setLancamento(null)}
        aoConcluir={depoisDeMexer}
      />
      <FormularioDoItem
        aberto={editando}
        papel={item?.papel ?? "insumo"}
        item={item}
        aoFechar={() => setEditando(false)}
        aoSalvar={(novo) => {
          setEditando(false);
          setItem(novo);
          setAviso("Dados salvos.");
          aoMudar();
        }}
      />
      {item && item.papel === "insumo" ? (
        /* O modal de sempre é z-50; o embrulho o põe acima da gaveta. */
        <div className="relative z-[126]">
        <ModalDeInsumo
          aberta={dadosDeCompra}
          insumo={
            dadosDeCompra
              ? {
                  id: item.id,
                  name: item.nome,
                  unit: item.unidade,
                  cost_per_unit: item.custo_medio,
                  waste_pct_default: item.perda,
                  purchase_format: item.formato_de_compra,
                  is_service: item.servico,
                  ...item.compra,
                }
              : null
          }
          aoFechar={() => setDadosDeCompra(false)}
          aoSalvar={() => {
            setDadosDeCompra(false);
            void carregar();
            aoMudar();
          }}
        />
        </div>
      ) : null}
      <RegistrarProducao
        aberta={produzindo}
        produtos={produtosParaProduzir}
        aoFechar={() => setProduzindo(false)}
        aoConcluir={() => {
          setRecarregar((n) => n + 1);
          void carregar();
          aoMudar();
        }}
      />
      <JanelaDaProducao
        producaoId={producaoAberta}
        aoFechar={() => setProducaoAberta(null)}
        aoMudar={() => {
          setRecarregar((n) => n + 1);
          void carregar();
          aoMudar();
        }}
      />
    </>
  );
}
