"use client";

/*
 * Composição (Custos) no estoque novo: cada linha diz QUANDO sai do estoque
 *  - Sempre;
 *  - Pela variação (a célula da mesma cor/tamanho que o cliente escolheu);
 *  - Só se a opção X = Y (caixa só se Entrega = Caixa);
 *  - Só custo (entra no preço, nunca sai do estoque);
 * e, se precisar, a quantidade por variação (DTF P 0,06 / GG 0,09).
 *
 * Etiqueta "baixa do estoque" × "só custo": processo e mão de obra são só
 * custo; insumo sem controle também.
 */

import { useEffect, useMemo, useState, type MouseEvent } from "react";
import { Loader2, Settings2, Trash2, Sparkles, Factory } from "lucide-react";
import { Janela } from "./gaveta";
import { CampoNumero, EtiquetaDaBaixa } from "./primitivos";
import { PreviaDoProduto } from "./previa-do-produto";
import { Aviso } from "@/components/ui/aviso";
import { pedirJson } from "@/lib/estoque/use-estoque-v2";
import {
  atributosDeEscolhaUnica,
  celulaDaEscolha,
  combinacoesParaAGrade,
  dinheiro,
  escolhasDaCombinacao,
  gradeValida,
  mesmoNome,
  qtd,
  resumoDaGrade,
  textoDaCombinacao,
  textoQuandoSai,
  unidade,
  valoresDaCelula,
} from "@/lib/estoque/regras";
import type { AtributoDoProduto, Combinacao, ItemDoEstoque, ModoDoProduto, QuandoSai } from "@/lib/estoque/tipos";

export type LinhaV2 = {
  id: string;
  material_id: string;
  consumption_qty: number;
  waste_pct: number;
  cost_total: number;
  pieces_per_unit?: number | null;
  consumption_base?: string | null;
  quando_sai?: QuandoSai | null;
  condicao_opcao_id?: string | null;
  condicao_atributo?: string | null;
  condicao_valor?: string | null;
  qtd_por_variacao?: Array<{ combinacao: Combinacao; quantidade: number | string }> | null;
  celulas?: Array<{ combinacao: Combinacao; celula_id: string }> | null;
  materials?: { name?: string; unit?: string | null; cost_per_unit?: number | string | null; track_stock?: boolean | null; is_service?: boolean | null; grade?: unknown; papel?: string | null } | null;
};

export type ContextoDoProduto = {
  modo: ModoDoProduto;
  atributos: AtributoDoProduto[];
  receitas: Array<{ option_id: string; atributo: string | null; opcao: string | null; material: string; unidade: string; quantidade: number }>;
};

export function baixaDoEstoque(l: LinhaV2) {
  return Boolean(l.materials?.track_stock) && !l.materials?.is_service && l.quando_sai !== "so_custo";
}

const chave = (c: Combinacao) => JSON.stringify(Object.entries(c).map(([k, v]) => [k.toLowerCase(), String(v).toLowerCase()]).sort());

/* ------------------------------------------------------------- o editor */

function EditorQuandoSai({
  linha,
  contexto,
  aoFechar,
  aoSalvar,
}: {
  linha: LinhaV2 | null;
  contexto: ContextoDoProduto;
  aoFechar: () => void;
  aoSalvar: (nova: LinhaV2) => void;
}) {
  const [quando, setQuando] = useState<QuandoSai>("sempre");
  const [atributo, setAtributo] = useState("");
  const [valor, setValor] = useState("");
  const [variaPor, setVariaPor] = useState<string>("");
  const [qtds, setQtds] = useState<Record<string, number>>({});
  const [manual, setManual] = useState<Array<{ combinacao: Combinacao; celula_id: string }>>([]);
  const [item, setItem] = useState<ItemDoEstoque | null>(null);
  const [salvando, setSalvando] = useState(false);
  const [erro, setErro] = useState<string | null>(null);
  const [chaveAberta, setChaveAberta] = useState("");

  const chaveAgora = linha?.id ?? "";
  if (chaveAgora !== chaveAberta) {
    setChaveAberta(chaveAgora);
    setErro(null);
    if (linha) {
      const temGrade = gradeValida(linha.materials?.grade).length > 0;
      setQuando((linha.quando_sai as QuandoSai) || (temGrade ? "pela_variacao" : "sempre"));
      setAtributo(linha.condicao_atributo ?? "");
      setValor(linha.condicao_valor ?? "");
      const lista = linha.qtd_por_variacao ?? [];
      const primeiro = lista[0] ? Object.keys(lista[0].combinacao)[0] ?? "" : "";
      setVariaPor(primeiro);
      const q: Record<string, number> = {};
      for (const x of lista) {
        const v = Object.values(x.combinacao)[0];
        if (v) q[v] = Number(String(x.quantidade).replace(",", ".")) || 0;
      }
      setQtds(q);
      setManual(linha.celulas ?? []);
    }
  }

  useEffect(() => {
    if (!linha) return;
    let vivo = true;
    setItem(null);
    pedirJson<{ itens: ItemDoEstoque[] }>(`/api/estoque/itens?id=${linha.material_id}`)
      .then((r) => vivo && setItem(r.itens[0] ?? null))
      .catch(() => undefined);
    return () => {
      vivo = false;
    };
  }, [linha]);

  const unicos = atributosDeEscolhaUnica(contexto.atributos);
  const todos = contexto.atributos;
  const attrDaCondicao = todos.find((a) => mesmoNome(a.name, atributo));
  const attrDaVariacao = todos.find((a) => mesmoNome(a.name, variaPor));
  const combinacoes = useMemo(() => (item ? combinacoesParaAGrade(contexto.atributos, item.grade) : []), [item, contexto.atributos]);

  if (!linha) return <Janela aberta={false} aoFechar={aoFechar} titulo="">{null}</Janela>;
  const temGrade = item ? item.grade.length > 0 : gradeValida(linha.materials?.grade).length > 0;
  const un = unidade(linha.materials?.unit);

  async function salvar() {
    if (!linha) return;
    if (quando === "se_opcao" && (!atributo || !valor)) return setErro("Escolha a opção e o valor que fazem esta linha sair.");
    setSalvando(true);
    setErro(null);
    const opcao = attrDaCondicao?.options.find((o) => mesmoNome(o.label, valor));
    try {
      const nova = await pedirJson<LinhaV2>("/api/production/composition/materials", {
        method: "PATCH",
        corpo: {
          id: linha.id,
          quando_sai: quando,
          condicao_atributo: quando === "se_opcao" ? atributo : null,
          condicao_valor: quando === "se_opcao" ? valor : null,
          condicao_opcao_id: quando === "se_opcao" ? opcao?.id ?? null : null,
          qtd_por_variacao:
            variaPor && attrDaVariacao
              ? attrDaVariacao.options
                  .filter((o) => qtds[o.label] !== undefined && qtds[o.label] > 0)
                  .map((o) => ({ combinacao: { [attrDaVariacao.name]: o.label }, quantidade: qtds[o.label] }))
              : [],
          celulas: quando === "pela_variacao" || quando === "sempre" ? manual : [],
        },
      });
      aoSalvar(nova);
    } catch (e) {
      setErro((e as Error).message);
    } finally {
      setSalvando(false);
    }
  }

  const OPCOES: Array<{ id: QuandoSai; titulo: string; texto: string }> = [
    {
      id: "sempre",
      titulo: "Sempre",
      texto: temGrade ? "Sai em toda venda. Como o item tem grade, a célula segue a escolha do cliente." : "Sai em toda venda (ex.: pó, tinta, embalagem padrão).",
    },
    {
      id: "pela_variacao",
      titulo: "Pela variação",
      texto: "Sai a célula da mesma cor/tamanho que o cliente escolheu (camiseta G preta → camiseta lisa G / Preta).",
    },
    { id: "se_opcao", titulo: "Só se escolher uma opção", texto: "Ex.: caixa só se Entrega = Caixa; embrulho só se Embrulho = Sim." },
    { id: "so_custo", titulo: "Só custo", texto: "Entra no preço, mas nunca sai do estoque." },
  ];

  return (
    <Janela
      aberta={Boolean(linha)}
      aoFechar={aoFechar}
      largura={760}
      titulo={`Quando sai: ${linha.materials?.name ?? "insumo"}`}
      texto={`${qtd(linha.consumption_qty)} ${un} por peça${linha.waste_pct ? ` + ${qtd(linha.waste_pct)}% de perda` : ""}. ${
        linha.materials?.track_stock ? "Este insumo é controlado." : "Este insumo não é controlado: só custo, seja qual for a escolha."
      }`}
      rodape={
        <>
          <button type="button" onClick={aoFechar} className="ks-button ks-button-secondary">
            Cancelar
          </button>
          <button type="button" onClick={() => void salvar()} disabled={salvando} className="ks-button ks-button-primary">
            {salvando ? <Loader2 size={15} className="animate-spin" /> : null} Salvar
          </button>
        </>
      }
    >
      <div className="space-y-5">
        <div role="radiogroup" aria-label="Quando sai" className="grid gap-2 sm:grid-cols-2">
          {OPCOES.map((o) => (
            <button
              key={o.id}
              type="button"
              role="radio"
              aria-checked={quando === o.id}
              aria-label={o.titulo}
              onClick={() => setQuando(o.id)}
              className={`rounded-xl border-2 px-3 py-2.5 text-left transition-colors ${
                quando === o.id ? "border-[var(--ks-brand-600)] bg-[var(--ks-brand-50)]" : "border-[var(--ks-color-border-subtle)] hover:border-[var(--ks-brand-300)]"
              }`}
            >
              <span className="block text-sm font-bold text-[var(--ks-color-text-primary)]">{o.titulo}</span>
              <span className="block text-xs leading-5 text-[var(--ks-color-text-muted)]">{o.texto}</span>
            </button>
          ))}
        </div>

        {quando === "se_opcao" ? (
          <div className="grid gap-3 rounded-xl bg-[var(--ks-color-bg-subtle)]/60 p-3 sm:grid-cols-2">
            <label className="text-xs font-medium text-[var(--ks-color-text-soft)]">
              Quando o cliente escolher em
              <select value={atributo} onChange={(e) => { setAtributo(e.target.value); setValor(""); }} className="ks-field mt-1">
                <option value="">Escolha o atributo…</option>
                {todos.map((a) => (
                  <option key={a.name} value={a.name}>
                    {a.name}
                  </option>
                ))}
              </select>
            </label>
            <label className="text-xs font-medium text-[var(--ks-color-text-soft)]">
              a opção
              <select value={valor} onChange={(e) => setValor(e.target.value)} disabled={!attrDaCondicao} className="ks-field mt-1">
                <option value="">Escolha a opção…</option>
                {(attrDaCondicao?.options ?? []).map((o) => (
                  <option key={o.id ?? o.label} value={o.label}>
                    {o.label}
                  </option>
                ))}
              </select>
            </label>
            {!todos.length ? <p className="text-xs text-rose-600 sm:col-span-2">O produto não tem variações: crie o atributo (ex.: Entrega) na aba Variações.</p> : null}
          </div>
        ) : null}

        {quando !== "so_custo" ? (
          <section>
            <div className="flex flex-wrap items-center justify-between gap-2">
              <div>
                <p className="text-sm font-bold text-[var(--ks-color-text-primary)]">Quantidade muda com a variação?</p>
                <p className="text-xs text-[var(--ks-color-text-muted)]">Ex.: DTF do P gasta 0,06 m²; do GG, 0,09 m². Sem valor, vale {qtd(linha.consumption_qty)} {un}.</p>
              </div>
              <select value={variaPor} onChange={(e) => setVariaPor(e.target.value)} className="ks-field w-auto min-w-[180px]" aria-label="Quantidade muda por">
                <option value="">Não: sempre {qtd(linha.consumption_qty)} {un}</option>
                {unicos.map((a) => (
                  <option key={a.name} value={a.name}>
                    Muda por {a.name}
                  </option>
                ))}
              </select>
            </div>
            {attrDaVariacao ? (
              <div className="mt-3 grid grid-cols-2 gap-2 sm:grid-cols-4">
                {attrDaVariacao.options.map((o) => (
                  <label key={o.id ?? o.label} className="text-xs font-semibold text-[var(--ks-color-text-secondary)]">
                    {o.label}
                    <CampoNumero
                      valor={qtds[o.label] ?? 0}
                      aoMudar={(n) => setQtds((a) => ({ ...a, [o.label]: n }))}
                      rotulo={`Quantidade para ${o.label}`}
                      sufixo={un}
                      placeholder={qtd(linha.consumption_qty)}
                      className="mt-1"
                    />
                  </label>
                ))}
              </div>
            ) : null}
          </section>
        ) : null}

        {(quando === "pela_variacao" || quando === "sempre") && temGrade && item ? (
          <section>
            <p className="text-sm font-bold text-[var(--ks-color-text-primary)]">De qual célula sai em cada variação</p>
            <p className="text-xs text-[var(--ks-color-text-muted)]">
              {item.nome} tem grade {resumoDaGrade(item.grade)}. O sistema liga pelo nome; troque só o que não bater.
            </p>
            <div className="mt-2 max-h-[260px] overflow-y-auto">
              <table className="w-full text-sm">
                <tbody>
                  {combinacoes.map((comb) => {
                    const auto = celulaDaEscolha(item.grade, item.celulas, escolhasDaCombinacao(comb), []);
                    const escolhida = manual.find((m) => chave(m.combinacao) === chave(comb));
                    return (
                      <tr key={chave(comb)} className="border-t border-slate-100/60 first:border-t-0">
                        <td className="py-1.5 pr-3 font-semibold text-[var(--ks-color-text-primary)]">{textoDaCombinacao(comb)}</td>
                        <td className="py-1.5">
                          <select
                            value={escolhida?.celula_id ?? ""}
                            onChange={(e) =>
                              setManual((a) => {
                                const resto = a.filter((m) => chave(m.combinacao) !== chave(comb));
                                return e.target.value ? [...resto, { combinacao: comb, celula_id: e.target.value }] : resto;
                              })
                            }
                            className={`ks-field ${!auto.celula && !escolhida ? "!border-rose-300" : ""}`}
                            aria-label={`Célula de ${textoDaCombinacao(comb)}`}
                          >
                            <option value="">{auto.celula ? `Automático: ${valoresDaCelula(auto.celula)}` : "Não achou pelo nome — escolha"}</option>
                            {item.celulas.map((c) => (
                              <option key={c.celula_id} value={c.celula_id}>
                                {valoresDaCelula(c)} (saldo {qtd(c.saldo)})
                              </option>
                            ))}
                          </select>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </section>
        ) : null}

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

/* ------------------------------------------------------------- a lista */

export function ListaDaComposicaoV2({
  materiais,
  contexto,
  aoMudarLinha,
  aoRemover,
}: {
  materiais: LinhaV2[];
  contexto: ContextoDoProduto | null;
  aoMudarLinha: (l: LinhaV2) => void;
  aoRemover: (e: MouseEvent, id: string) => void;
}) {
  const [editando, setEditando] = useState<LinhaV2 | null>(null);
  const base = materiais.filter((m) => m.quando_sai !== "se_opcao").reduce((s, m) => s + (Number(m.cost_total) || 0), 0);
  const porOpcao = materiais.filter((m) => m.quando_sai === "se_opcao");

  return (
    <div className="overflow-hidden rounded-xl border border-[var(--ks-color-border-subtle)] bg-white">
      <div className="hidden grid-cols-[minmax(0,1fr)_170px_120px_110px_76px] gap-3 bg-[var(--ks-color-bg-subtle)]/40 px-4 py-2.5 text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-400 md:grid">
        <span>Material</span>
        <span>Quando sai</span>
        <span className="text-right">Qtd por peça</span>
        <span className="text-right">Custo</span>
        <span />
      </div>
      {materiais.length === 0 ? (
        <p className="px-4 py-6 text-center text-sm text-slate-400">Nenhum material adicionado.</p>
      ) : (
        materiais.map((m) => {
          const baixa = baixaDoEstoque(m);
          const un = unidade(m.materials?.unit);
          const grade = resumoDaGrade(m.materials?.grade);
          const variaveis = (m.qtd_por_variacao ?? []).length;
          const botaoQuando = (
            <button
              type="button"
              onClick={() => setEditando(m)}
              className="rounded-lg px-2 py-1 text-left text-sm font-semibold text-[var(--ks-color-primary)] hover:bg-[var(--ks-brand-50)]"
              title="Mudar quando sai"
            >
              {textoQuandoSai(m)}
              <Settings2 size={13} className="ml-1 inline" />
            </button>
          );
          const quantidade = (
            <p className="ks-num text-sm tabular-nums text-[var(--ks-color-text-secondary)] md:text-right">
              {Number(m.pieces_per_unit) > 0 ? `${m.pieces_per_unit} por ${un}` : `${qtd(m.consumption_qty)} ${un}`}
              {m.waste_pct ? <span className="text-[11px] text-slate-400"> +{qtd(m.waste_pct)}%</span> : null}
              {variaveis ? <span className="block text-[11px] text-[var(--ks-color-primary)]">muda por variação ({variaveis})</span> : null}
            </p>
          );
          const custo = (
            <p className="ks-num text-right text-sm font-semibold tabular-nums text-[var(--ks-color-text-primary)]">
              {m.quando_sai === "se_opcao" ? (
                <span title="Não entra no custo base: só quando a opção é escolhida">
                  +{dinheiro(m.cost_total)}
                  <span className="block text-[10px] font-normal text-[var(--ks-color-text-soft)]">quando escolhida</span>
                </span>
              ) : (
                dinheiro(m.cost_total)
              )}
            </p>
          );
          const remover = (
            <button
              type="button"
              className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-red-500 transition-colors hover:bg-red-50 hover:text-red-700"
              onClick={(e) => aoRemover(e, m.id)}
              title="Remover material"
              aria-label={`Remover ${m.materials?.name ?? "material"}`}
            >
              <Trash2 className="h-4 w-4" />
            </button>
          );
          const nome = (
            <div className="min-w-0 flex-1">
              <p className="truncate text-sm font-semibold text-[var(--ks-color-text-primary)]">{m.materials?.name}</p>
              <div className="mt-0.5 flex flex-wrap items-center gap-1.5">
                <EtiquetaDaBaixa
                  baixa={baixa}
                  titulo={baixa ? "Sai do estoque na venda (sob encomenda) ou na produção" : m.materials?.track_stock ? "Marcada como só custo" : "Insumo sem controle de estoque: só custo"}
                />
                {grade ? <span className="text-[11px] text-[var(--ks-color-text-soft)]">grade {grade}</span> : null}
              </div>
            </div>
          );
          return (
            <div key={m.id} className="border-t border-slate-100/60 px-4 py-3 first:border-t-0">
              {/* Celular: nome e lixeira em cima; quando sai, quantidade e custo embaixo. */}
              <div className="md:hidden">
                <div className="flex items-start gap-2">
                  {nome}
                  {remover}
                </div>
                <div className="mt-1.5 flex flex-wrap items-end justify-between gap-x-3 gap-y-1">
                  <div className="-ml-2">{botaoQuando}</div>
                  <div className="ml-auto flex items-end gap-4">
                    {quantidade}
                    {custo}
                  </div>
                </div>
              </div>
              <div className="hidden grid-cols-[minmax(0,1fr)_170px_120px_110px_76px] items-center gap-3 md:grid">
                {nome}
                <div>{botaoQuando}</div>
                {quantidade}
                {custo}
                <div className="flex justify-end">{remover}</div>
              </div>
            </div>
          );
        })
      )}

      {contexto?.receitas.length ? (
        <div className="border-t border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-subtle)]/30 px-4 py-3">
          <p className="text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-400">Receitas das opções (aba Variações)</p>
          {contexto.receitas.map((r) => (
            <div key={`${r.option_id}-${r.material}`} className="flex flex-wrap items-center justify-between gap-2 py-1.5 text-sm">
              <span className="text-[var(--ks-color-text-primary)]">
                <strong>{r.material}</strong> · {qtd(r.quantidade)} {unidade(r.unidade)} por peça
              </span>
              <span className="text-xs font-semibold text-[var(--ks-color-text-secondary)]">
                Só se {r.atributo ?? "a opção"} = {r.opcao ?? "?"}
              </span>
            </div>
          ))}
        </div>
      ) : null}

      <div className="flex flex-wrap items-center justify-end gap-x-5 gap-y-1 border-t border-[var(--ks-color-border-subtle)] px-4 py-3 text-sm">
        <span className="text-[var(--ks-color-text-muted)]">
          Custo base dos materiais <strong className="ks-num text-[var(--ks-color-text-primary)]">{dinheiro(base)}</strong>
        </span>
        {porOpcao.length ? (
          <span className="text-[var(--ks-color-text-muted)]">
            {porOpcao.map((m) => `+${dinheiro(m.cost_total)} se ${m.condicao_valor ?? "a opção"}`).join(" · ")}
          </span>
        ) : null}
      </div>

      {contexto ? (
        <EditorQuandoSai
          linha={editando}
          contexto={contexto}
          aoFechar={() => setEditando(null)}
          aoSalvar={(nova) => {
            setEditando(null);
            aoMudarLinha(nova);
          }}
        />
      ) : null}
    </div>
  );
}

/* ---------------------------------------------- "Ao vender 1 sai…" no pé */

export function ResumoDaComposicao({ produtoId, contexto, recarregar }: { produtoId: string; contexto: ContextoDoProduto; recarregar: number }) {
  const producao = contexto.modo === "pronto";
  return (
    <section className="rounded-2xl border border-[var(--ks-color-border-subtle)] bg-white p-5">
      <h3 className="flex items-center gap-2 text-[15px] font-extrabold tracking-tight text-[var(--ks-color-text-primary)]">
        {producao ? <Factory size={16} className="text-[var(--ks-color-primary)]" /> : <Sparkles size={16} className="text-[var(--ks-color-primary)]" />}
        {producao ? "Ao produzir, sai…" : "Ao vender, sai…"}
      </h3>
      <p className="mb-4 text-[13px] text-[var(--ks-color-text-muted)]">
        {producao
          ? "Este produto sai pronto da prateleira: a composição sai do estoque quando você registra a produção (não na venda)."
          : contexto.modo === "nenhum"
            ? "Este produto não controla estoque (aba Estoque): a composição é só custo. Só os serviços e receitas de opção escolhidos saem."
            : "Sob encomenda: cada venda tira estas linhas do estoque. Escolha uma combinação e confira."}
      </p>
      <PreviaDoProduto key={recarregar} produtoId={produtoId} atributos={contexto.atributos} mostrar={producao ? "producao" : "venda"} recarregar={recarregar} />
    </section>
  );
}
