"use client";

import { useEffect, useMemo, useState } from "react";
import { Loader2, Minus, Plus } from "lucide-react";
import type { PainelDeProducao } from "@/lib/orders/eventos-de-producao";
import { corteNaBobina, quantidadeLegivel, unidadeLegivel, type AjusteDeRodagem } from "@/lib/orders/ficha-de-producao";

/**
 * Como este item vai ser feito: o que muda de pedido para pedido.
 *
 * O cadastro do produto diz o de sempre ("cabem 2 canecas numa folha"); quem
 * está na bancada sabe o de hoje ("couberam 3 artes"). E a lona: entra na
 * bobina junto com outros trabalhos (o normal) ou puxa um pedaço só para
 * ela. Só aparecem as linhas em que há o que decidir — caneca, argola e
 * tinta não têm pergunta.
 *
 * A linguagem é a do chão de fábrica: pergunta direta, resposta em frase
 * completa com o número grande. Salvar grava `order_items.production_plan`;
 * o banco refaz a baixa de estoque, e a ficha impressa e a lista de
 * separação passam a seguir o que foi marcado.
 */

type ItemDoPainel = PainelDeProducao["itens"][number];

const formatar = (n: number, casas = 2) =>
  new Intl.NumberFormat("pt-BR", { minimumFractionDigits: 0, maximumFractionDigits: casas }).format(n);

const teto = (n: number) => Math.ceil(Math.round(n * 10000) / 10000 - 0.001);

const plural = (n: number, um: string, varios: string) => `${formatar(n)} ${n === 1 ? um : varios}`;

/* "folha" vira "folhas", "chapa" vira "chapas"; "un" fica "un". */
function unidadeNoPlural(unidade: string, n: number) {
  const u = unidadeLegivel(unidade);
  if (n === 1 || u.length <= 2 || u.endsWith("s")) return u;
  return `${u}s`;
}

export function PlanoDeRodagem({
  orderId,
  item,
  medida,
  podeEditar,
  aoSalvar,
  titulo,
}: {
  orderId: string;
  item: ItemDoPainel;
  /* Largura, altura e peças do item, para mostrar a conta antes de salvar. */
  medida: { larguraM: number; alturaM: number; pecas: number };
  podeEditar: boolean;
  aoSalvar: (painel: PainelDeProducao) => void;
  /* Na página do pedido o bloco fica fora do item: o título diz de qual é. */
  titulo?: string | null;
}) {
  const ajustaveis = useMemo(() => item.insumos.filter((i) => i.ajustavel), [item.insumos]);
  const [rascunho, setRascunho] = useState<Record<string, AjusteDeRodagem>>({});
  const [salvando, setSalvando] = useState(false);
  const [erro, setErro] = useState<string | null>(null);
  const [salvoAgora, setSalvoAgora] = useState(false);

  /* O rascunho nasce do que está gravado; quando o painel recarrega, alinha. */
  useEffect(() => {
    setRascunho({ ...(item.plano.insumos ?? {}) });
  }, [item.plano]);

  if (ajustaveis.length === 0) return null;

  const mudou = JSON.stringify(normalizar(rascunho)) !== JSON.stringify(normalizar(item.plano.insumos ?? {}));

  const salvar = async () => {
    setSalvando(true);
    setErro(null);
    try {
      const res = await fetch(`/api/orders/${orderId}/producao`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ acao: "plano", order_item_id: item.id, insumos: normalizar(rascunho) }),
      });
      const json = (await res.json().catch(() => null)) as (PainelDeProducao & { error?: string }) | null;
      if (!res.ok || !json || json.error) throw new Error(json?.error || "Não deu para salvar. Tente de novo.");
      aoSalvar(json);
      setSalvoAgora(true);
      setTimeout(() => setSalvoAgora(false), 2500);
    } catch (e) {
      setErro(e instanceof Error ? e.message : "Não deu para salvar. Tente de novo.");
    } finally {
      setSalvando(false);
    }
  };

  const definir = (chave: string, ajuste: AjusteDeRodagem) =>
    setRascunho((r) => ({ ...r, [chave]: { ...r[chave], ...ajuste } }));

  return (
    <section className="ks-surface mt-3 overflow-hidden rounded-xl border border-[var(--ks-color-border-subtle)]">
      <header className="flex flex-wrap items-start justify-between gap-3 border-b border-[var(--ks-color-border-subtle)] px-4 py-3">
        <div className="min-w-0">
          <h4 className="text-sm font-bold text-[var(--ks-color-text-primary)]">
            Como este item vai ser feito{titulo ? <span className="font-semibold text-[var(--ks-color-text-muted)]"> · {titulo}</span> : null}
          </h4>
          <p className="mt-0.5 hidden text-xs text-[var(--ks-color-text-muted)] sm:block">
            Responda o que muda de pedido para pedido. A conta do material sai na hora. Ao salvar, a ficha impressa, a lista de
            separação e a baixa do estoque seguem o que você marcou.
          </p>
        </div>
        {podeEditar ? (
          <div className="flex items-center gap-2 shrink-0">
            {!mudou && salvoAgora ? <span className="ks-chip ks-chip-success text-[11px]">Salvo</span> : null}
            {mudou ? (
              <button type="button" onClick={salvar} disabled={salvando} className="ks-button ks-button-primary ks-button-sm">
                {salvando ? <Loader2 size={14} className="animate-spin" /> : null}
                {salvando ? "Salvando…" : "Salvar"}
              </button>
            ) : null}
          </div>
        ) : null}
      </header>

      <ul className="divide-y divide-[var(--ks-color-border-subtle)]">
        {ajustaveis.map((insumo) => {
          const ajuste = rascunho[insumo.chave] ?? {};

          /* ---------------------------------------------------------- folha */
          if (insumo.ajustavel === "rendimento") {
            const deSempre = insumo.rendimentoDoCadastro ?? (insumo.rendimentoEstimado ? insumo.rendimento : null);
            const escolhido = Number(ajuste.rendimento) > 0 ? Number(ajuste.rendimento) : null;
            const n = escolhido ?? insumo.rendimento ?? 1;
            const folhas = medida.pecas > 0 ? teto(medida.pecas / n) : 0;
            const sobraPct = folhas > 0 ? Math.round((folhas - medida.pecas / n) * 100) : 0;
            const unidadeUma = unidadeLegivel(insumo.unidade);
            const atalhos = Array.from(new Set([1, 2, 3, 4, 6, deSempre ?? 0].filter((v) => v > 0))).sort((a, b) => a - b);
            return (
              <li key={insumo.chave} className="grid gap-3 px-4 py-3 lg:grid-cols-[minmax(0,1fr)_auto] lg:items-center">
                <div className="min-w-0">
                  <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">
                    {insumo.nome}: quantas peças cabem em uma {unidadeUma}?
                  </p>
                  <div className="mt-2 flex flex-wrap items-center gap-2">
                    {atalhos.map((v) => (
                      <button
                        key={v}
                        type="button"
                        disabled={!podeEditar}
                        onClick={() => definir(insumo.chave, { rendimento: v === deSempre && !escolhido ? null : v })}
                        className={`ks-chip cursor-pointer ${n === v ? "ks-chip-solid" : "ks-chip-neutral"}`}
                        title={v === deSempre ? "O de sempre, pelo cadastro do produto" : undefined}
                      >
                        {v}
                        {v === deSempre ? " · de sempre" : ""}
                      </button>
                    ))}
                    <span className="inline-flex items-center gap-1">
                      <button
                        type="button"
                        disabled={!podeEditar || n <= 1}
                        onClick={() => definir(insumo.chave, { rendimento: Math.max(1, n - 1) })}
                        className="ks-button ks-button-icon ks-button-sm"
                        aria-label="Uma peça a menos por folha"
                      >
                        <Minus size={14} />
                      </button>
                      <input
                        type="number"
                        inputMode="numeric"
                        min={1}
                        step={1}
                        value={n}
                        disabled={!podeEditar}
                        onChange={(e) => {
                          const v = Math.round(Number(e.target.value.replace(",", ".")));
                          definir(insumo.chave, { rendimento: Number.isFinite(v) && v > 0 ? v : null });
                        }}
                        className="ks-field w-16 text-center text-sm font-bold"
                        aria-label={`Peças por ${unidadeUma}`}
                      />
                      <button
                        type="button"
                        disabled={!podeEditar}
                        onClick={() => definir(insumo.chave, { rendimento: n + 1 })}
                        className="ks-button ks-button-icon ks-button-sm"
                        aria-label="Uma peça a mais por folha"
                      >
                        <Plus size={14} />
                      </button>
                    </span>
                  </div>
                  <p className="mt-1.5 text-xs text-[var(--ks-color-text-muted)]">
                    {deSempre
                      ? `Pelo cadastro do produto, cabem ${formatar(deSempre)}${insumo.rendimentoEstimado ? " (número deduzido de um cadastro antigo: confira)" : ""}.`
                      : "O cadastro do produto não diz quantas cabem."}
                    {escolhido && escolhido !== deSempre ? " Neste pedido você marcou diferente." : ""}
                  </p>
                </div>
                <div className="lg:text-right">
                  <div className="text-[var(--ks-color-text-primary)]">
                    <span className="ks-num text-2xl font-extrabold text-[var(--ks-color-primary)]">{formatar(folhas)}</span>{" "}
                    <span className="text-sm font-semibold">{unidadeNoPlural(insumo.unidade, folhas)}</span>
                  </div>
                  <div className="text-xs text-[var(--ks-color-text-muted)]">
                    para {plural(medida.pecas, "peça", "peças")}
                    {sobraPct > 0 ? ` · sobra ${sobraPct}% da última ${unidadeUma}` : " · sem sobra"}
                  </div>
                </div>
              </li>
            );
          }

          /* --------------------------------------------------------- bobina */
          const sozinha = ajuste.rodagem === "sozinho";
          const largura = insumo.larguraBobinaM ?? insumo.corte?.larguraBobinaM ?? 0;
          const corte = largura > 0 ? corteNaBobina(largura, medida.larguraM, medida.alturaM, medida.pecas) : null;
          const juntoLegivel = quantidadeLegivel(insumo.quantidadePrevista, insumo.unidade);
          const areaDaPeca = quantidadeLegivel(insumo.quantidadeLiquida, insumo.unidade);
          const gastoSozinha = corte ? corte.comprimentoM * largura : null;
          const gastoEscolhido = sozinha && gastoSozinha ? `${formatar(gastoSozinha)} m²` : `${formatar(juntoLegivel.valor)} ${juntoLegivel.unidade}`;
          const opcoes: { valor: "casado" | "sozinho"; rotulo: string; explicacao: string; gasto: string }[] = [
            {
              valor: "casado",
              rotulo: "Junto com outros trabalhos",
              explicacao: `O de sempre. A bobina é aproveitada com outros pedidos, então conta só o tamanho da peça (${formatar(areaDaPeca.valor)} ${areaDaPeca.unidade}) mais a perda normal.`,
              gasto: `${formatar(juntoLegivel.valor)} ${juntoLegivel.unidade}`,
            },
            {
              valor: "sozinho",
              rotulo: "Sozinha na bobina",
              explicacao: corte
                ? `Você puxa ${formatar(corte.comprimentoM)} m da bobina de ${formatar(largura)} m só para esta peça: ${corte.porFaixa} ${corte.porFaixa === 1 ? "peça por fileira" : "peças por fileira"}${corte.girada ? ", deitadas" : ""}. Conta a largura inteira, mesmo o que sobra na lateral.`
                : largura > 0
                  ? `A peça é maior que a bobina de ${formatar(largura)} m nos dois sentidos: fica o tamanho da peça, e a bancada resolve com emenda.`
                  : "O cadastro do insumo não diz a largura da bobina.",
              gasto: gastoSozinha ? `${formatar(gastoSozinha)} m²` : `${formatar(juntoLegivel.valor)} ${juntoLegivel.unidade}`,
            },
          ];
          return (
            <li key={insumo.chave} className="grid gap-3 px-4 py-3 lg:grid-cols-[minmax(0,1fr)_auto] lg:items-center">
              <div className="min-w-0">
                <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">
                  {insumo.nome}: vai na bobina junto com outros trabalhos ou sozinha?
                </p>
                <div className="mt-2 grid gap-2 sm:grid-cols-2">
                  {opcoes.map((o) => {
                    const ativa = (sozinha ? "sozinho" : "casado") === o.valor;
                    return (
                      <button
                        key={o.valor}
                        type="button"
                        disabled={!podeEditar}
                        onClick={() => definir(insumo.chave, { rodagem: o.valor === "sozinho" ? "sozinho" : null })}
                        className="rounded-lg border px-3 py-2 text-left transition"
                        style={
                          ativa
                            ? { borderColor: "var(--ks-color-primary)", background: "var(--ks-color-brand-50, rgba(68,37,167,0.06))" }
                            : { borderColor: "var(--ks-color-border-subtle)" }
                        }
                        aria-pressed={ativa}
                      >
                        <span className="flex items-center justify-between gap-2">
                          <span className="text-sm font-semibold text-[var(--ks-color-text-primary)]">{o.rotulo}</span>
                          <span className={`ks-chip text-[11px] ${ativa ? "ks-chip-solid" : "ks-chip-neutral"}`}>{o.gasto}</span>
                        </span>
                        <span className="mt-1 block text-xs text-[var(--ks-color-text-muted)]">{o.explicacao}</span>
                      </button>
                    );
                  })}
                </div>
              </div>
              <div className="lg:text-right">
                <div className="text-[var(--ks-color-text-primary)]">
                  <span className="ks-num text-2xl font-extrabold text-[var(--ks-color-primary)]">{gastoEscolhido.split(" ")[0]}</span>{" "}
                  <span className="text-sm font-semibold">{gastoEscolhido.split(" ").slice(1).join(" ")} de {insumo.nome}</span>
                </div>
                <div className="text-xs text-[var(--ks-color-text-muted)]">
                  {sozinha ? "sozinha na bobina" : "junto com outros trabalhos"} · {plural(medida.pecas, "peça", "peças")} de{" "}
                  {formatar(medida.larguraM)} m × {formatar(medida.alturaM)} m
                </div>
              </div>
            </li>
          );
        })}
      </ul>
      {erro ? <div className="border-t border-[var(--ks-color-border-subtle)] px-4 py-2 text-xs text-[var(--ks-color-status-danger)]">{erro}</div> : null}
    </section>
  );
}

/* Só o que tem valor entra no plano: sem escolha é "segue o cadastro". */
function normalizar(insumos: Record<string, AjusteDeRodagem>): Record<string, AjusteDeRodagem> {
  const saida: Record<string, AjusteDeRodagem> = {};
  for (const [chave, ajuste] of Object.entries(insumos)) {
    const limpo: AjusteDeRodagem = {};
    if (Number(ajuste.rendimento) > 0) limpo.rendimento = Number(ajuste.rendimento);
    if (ajuste.rodagem === "sozinho") limpo.rodagem = "sozinho";
    if (limpo.rendimento !== undefined || limpo.rodagem !== undefined) saida[chave] = limpo;
  }
  return saida;
}
