"use client";

/*
 * Novo insumo / novo produto pronto / editar os dados de um item.
 * A grade (até 2 eixos, ex.: Tamanho × Cor) se monta aqui: cada valor vira
 * uma célula com saldo próprio. Célula com saldo não sai da grade — o banco
 * recusa e a mensagem diz qual contar antes.
 */

import { useState, type KeyboardEvent } from "react";
import { Loader2, Plus, X, Grid3x3 } from "lucide-react";
import { Janela } from "./gaveta";
import { CampoNumero } from "./primitivos";
import { Switch } from "@/components/ui/switch";
import { Aviso } from "@/components/ui/aviso";
import { pedirJson } from "@/lib/estoque/use-estoque-v2";
import { dinheiro, mesmoNome, unidade } from "@/lib/estoque/regras";
import type { EixoDaGrade, ItemDoEstoque, Papel } from "@/lib/estoque/tipos";

const UNIDADES = [
  { valor: "un", rotulo: "Unidade (un)" },
  { valor: "m", rotulo: "Metro (m)" },
  { valor: "m2", rotulo: "Metro quadrado (m²)" },
  { valor: "folha", rotulo: "Folha" },
  { valor: "kg", rotulo: "Quilo (kg)" },
  { valor: "g", rotulo: "Grama (g)" },
  { valor: "l", rotulo: "Litro (l)" },
  { valor: "ml", rotulo: "Mililitro (ml)" },
];

const MODELOS_DE_EIXO: EixoDaGrade[] = [
  { nome: "Tamanho", valores: ["P", "M", "G", "GG"] },
  { nome: "Cor", valores: ["Branca", "Preta"] },
];

type Rascunho = {
  nome: string;
  unidade: string;
  grade: EixoDaGrade[];
  minimo: number;
  perda: number;
  custo: number;
  permitir_negativo: boolean;
  controla: boolean;
  conversoes: Array<{ unidade: string; fator: number }>;
};

function rascunhoDe(item: ItemDoEstoque | null, papel: Papel): Rascunho {
  if (!item) {
    return {
      nome: "",
      unidade: "un",
      grade: [],
      minimo: 0,
      perda: 0,
      custo: 0,
      /* Insumo nasce podendo ficar negativo (nunca trava venda, como sempre);
         produto pronto nasce travando no zero. */
      permitir_negativo: papel === "insumo",
      controla: true,
      conversoes: [],
    };
  }
  return {
    nome: item.nome,
    unidade: item.unidade,
    grade: item.grade.map((e) => ({ nome: e.nome, valores: [...e.valores] })),
    minimo: item.minimo ?? 0,
    perda: item.perda,
    custo: item.custo_medio,
    permitir_negativo: item.permitir_negativo,
    controla: item.controla,
    conversoes: item.conversoes.map((c) => ({ unidade: c.unidade, fator: Number(String(c.fator).replace(",", ".")) || 0 })),
  };
}

function EditorDeEixo({
  eixo,
  aoMudar,
  aoTirar,
}: {
  eixo: EixoDaGrade;
  aoMudar: (e: EixoDaGrade) => void;
  aoTirar: () => void;
}) {
  const [novo, setNovo] = useState("");
  const somar = () => {
    const partes = novo
      .split(/[,;]/)
      .map((p) => p.trim())
      .filter(Boolean)
      .filter((p) => !eixo.valores.some((v) => mesmoNome(v, p)));
    if (partes.length) aoMudar({ ...eixo, valores: [...eixo.valores, ...partes] });
    setNovo("");
  };
  const teclar = (e: KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter" || e.key === ",") {
      e.preventDefault();
      somar();
    }
  };
  return (
    <div className="rounded-xl border border-[var(--ks-color-border-subtle)] p-3">
      <div className="flex items-center gap-2">
        <input
          value={eixo.nome}
          onChange={(e) => aoMudar({ ...eixo, nome: e.target.value })}
          placeholder="Nome do eixo (ex.: Tamanho)"
          className="ks-field font-semibold"
          aria-label="Nome do eixo"
          maxLength={40}
        />
        <button type="button" onClick={aoTirar} className="ks-icon-button shrink-0" aria-label="Tirar este eixo">
          <X size={16} />
        </button>
      </div>
      <div className="mt-2 flex flex-wrap items-center gap-1.5">
        {eixo.valores.map((v) => (
          <span key={v} className="inline-flex items-center gap-1 rounded-full bg-[var(--ks-brand-50)] py-1 pl-2.5 pr-1 text-xs font-semibold text-[var(--ks-brand-700)]">
            {v}
            <button
              type="button"
              onClick={() => aoMudar({ ...eixo, valores: eixo.valores.filter((x) => x !== v) })}
              className="rounded-full p-0.5 hover:bg-white"
              aria-label={`Tirar ${v}`}
            >
              <X size={11} />
            </button>
          </span>
        ))}
        <input
          value={novo}
          onChange={(e) => setNovo(e.target.value)}
          onKeyDown={teclar}
          onBlur={somar}
          placeholder={eixo.valores.length ? "mais um…" : "P, M, G (Enter para somar)"}
          className="min-w-[120px] flex-1 rounded-full border border-dashed border-[var(--ks-color-border-strong)] bg-transparent px-3 py-1 text-xs outline-none focus:border-[var(--ks-color-primary)]"
          aria-label={`Valores de ${eixo.nome || "eixo"}`}
        />
      </div>
    </div>
  );
}

export function FormularioDoItem({
  aberto,
  papel,
  item,
  aoFechar,
  aoSalvar,
}: {
  aberto: boolean;
  papel: Papel;
  item: ItemDoEstoque | null;
  aoFechar: () => void;
  aoSalvar: (item: ItemDoEstoque) => void;
}) {
  const [chave, setChave] = useState("");
  const [r, setR] = useState<Rascunho>(() => rascunhoDe(item, papel));
  const [salvando, setSalvando] = useState(false);
  const [erro, setErro] = useState<string | null>(null);

  const chaveAgora = aberto ? `${item?.id ?? "novo"}:${papel}` : "";
  if (chaveAgora !== chave) {
    setChave(chaveAgora);
    setR(rascunhoDe(item, papel));
    setErro(null);
  }

  const mudar = (p: Partial<Rascunho>) => setR((a) => ({ ...a, ...p }));
  const celulas = r.grade.reduce((n, e) => n * Math.max(1, e.valores.length), 1);
  const ehPronto = (item?.papel ?? papel) === "pronto";

  async function salvar() {
    if (!r.nome.trim()) return setErro("Dê um nome ao item.");
    const grade = r.grade.filter((e) => e.nome.trim() || e.valores.length);
    if (grade.some((e) => !e.nome.trim())) return setErro("Cada eixo da grade precisa de um nome (ex.: Tamanho).");
    if (grade.some((e) => !e.valores.length)) return setErro("Cada eixo da grade precisa de pelo menos um valor.");
    if (grade.length === 2 && mesmoNome(grade[0].nome, grade[1].nome)) return setErro("Os dois eixos têm o mesmo nome.");
    setSalvando(true);
    setErro(null);
    try {
      const resposta = await pedirJson<{ item: ItemDoEstoque | null }>("/api/estoque/itens", {
        method: "POST",
        corpo: {
          ...(item ? { id: item.id } : { papel }),
          nome: r.nome.trim(),
          unidade: r.unidade,
          grade,
          minimo: r.minimo > 0 ? r.minimo : null,
          perda: r.perda,
          permitir_negativo: r.permitir_negativo,
          controla: r.controla,
          conversoes: r.conversoes.filter((c) => c.unidade.trim() && c.fator > 0),
          ...(item ? {} : { custo: r.custo }),
        },
      });
      if (resposta.item) aoSalvar(resposta.item);
    } catch (e) {
      setErro((e as Error).message);
    } finally {
      setSalvando(false);
    }
  }

  return (
    <Janela
      aberta={aberto}
      aoFechar={aoFechar}
      largura={680}
      titulo={item ? `Dados de ${item.nome}` : ehPronto ? "Novo produto pronto" : "Novo insumo"}
      texto={
        item
          ? "Nome, unidade, grade e regras do item. O saldo não muda aqui: ele só mexe por entrada, contagem, perda, produção e venda."
          : ehPronto
            ? "Peça já feita, guardada para vender (ex.: caneca estampada, camiseta pronta). Depois ligue o produto do catálogo a ela."
            : "Material que vira produto (ex.: camiseta lisa, DTF, tinta). A composição do produto diz quanto sai de cada um."
      }
      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}
            {item ? "Salvar dados" : "Criar item"}
          </button>
        </>
      }
    >
      <div className="space-y-5">
        <div className="grid gap-3 sm:grid-cols-[minmax(0,1fr)_200px]">
          <label className="text-xs font-medium text-[var(--ks-color-text-soft)]">
            Nome
            <input
              value={r.nome}
              onChange={(e) => mudar({ nome: e.target.value })}
              placeholder={ehPronto ? "Ex.: Caneca Dia dos Pais" : "Ex.: Camiseta lisa algodão"}
              className="ks-field mt-1"
              maxLength={160}
              autoFocus={!item}
            />
          </label>
          <label className="text-xs font-medium text-[var(--ks-color-text-soft)]">
            Unidade do saldo
            <select value={r.unidade} onChange={(e) => mudar({ unidade: e.target.value })} className="ks-field mt-1">
              {UNIDADES.some((u) => u.valor === r.unidade) ? null : <option value={r.unidade}>{unidade(r.unidade)}</option>}
              {UNIDADES.map((u) => (
                <option key={u.valor} value={u.valor}>
                  {u.rotulo}
                </option>
              ))}
            </select>
          </label>
        </div>

        <section>
          <div className="flex flex-wrap items-center justify-between gap-2">
            <div>
              <p className="flex items-center gap-1.5 text-sm font-bold text-[var(--ks-color-text-primary)]">
                <Grid3x3 size={15} className="text-[var(--ks-color-primary)]" /> Grade
              </p>
              <p className="text-xs text-[var(--ks-color-text-muted)]">
                {r.grade.length
                  ? `Saldo separado em ${celulas} ${celulas === 1 ? "célula" : "células"} (${r.grade.map((e) => e.nome || "?").join(" × ")}).`
                  : "Sem grade: um saldo só. Tem tamanho ou cor? Monte a grade e cada combinação ganha o seu saldo."}
              </p>
            </div>
            {r.grade.length < 2 ? (
              <button
                type="button"
                onClick={() => mudar({ grade: [...r.grade, { ...MODELOS_DE_EIXO[r.grade.length], valores: [...MODELOS_DE_EIXO[r.grade.length].valores] }] })}
                className="ks-button ks-button-secondary ks-button-sm"
              >
                <Plus size={14} /> {r.grade.length ? "Segundo eixo" : "Montar grade"}
              </button>
            ) : null}
          </div>
          {r.grade.length ? (
            <div className="mt-3 grid gap-2 sm:grid-cols-2">
              {r.grade.map((e, i) => (
                <EditorDeEixo
                  key={i}
                  eixo={e}
                  aoMudar={(novo) => mudar({ grade: r.grade.map((x, j) => (j === i ? novo : x)) })}
                  aoTirar={() => mudar({ grade: r.grade.filter((_, j) => j !== i) })}
                />
              ))}
            </div>
          ) : null}
        </section>

        <div className="grid gap-3 sm:grid-cols-3">
          <label className="text-xs font-medium text-[var(--ks-color-text-soft)]">
            Avisar abaixo de
            <CampoNumero valor={r.minimo} aoMudar={(n) => mudar({ minimo: n })} rotulo="Mínimo" sufixo={unidade(r.unidade)} className="mt-1" />
            <span className="mt-1 block text-[11px] text-[var(--ks-color-text-soft)]">Mínimo por célula.</span>
          </label>
          {!ehPronto ? (
            <label className="text-xs font-medium text-[var(--ks-color-text-soft)]">
              Perda padrão
              <CampoNumero valor={r.perda} aoMudar={(n) => mudar({ perda: n })} rotulo="Perda padrão" sufixo="%" className="mt-1" />
              <span className="mt-1 block text-[11px] text-[var(--ks-color-text-soft)]">Sugerida nas composições novas.</span>
            </label>
          ) : null}
          {item ? (
            <div className="text-xs font-medium text-[var(--ks-color-text-soft)]">
              Custo médio
              <p className="ks-num mt-1 flex h-10 items-center text-sm font-bold text-[var(--ks-color-text-primary)]">
                {dinheiro(item.custo_medio)} <span className="ml-1 font-normal text-slate-400">/ {unidade(item.unidade)}</span>
              </p>
              <span className="block text-[11px] text-[var(--ks-color-text-soft)]">Muda sozinho a cada entrada, compra ou produção com custo.</span>
            </div>
          ) : (
            <label className="text-xs font-medium text-[var(--ks-color-text-soft)]">
              Custo por {unidade(r.unidade)}
              <CampoNumero valor={r.custo} aoMudar={(n) => mudar({ custo: n })} rotulo="Custo" sufixo="R$" className="mt-1" />
            </label>
          )}
        </div>

        <div className="divide-y divide-[var(--ks-n-100)] rounded-xl border border-[var(--ks-color-border-subtle)] px-4">
          <div className="flex items-start justify-between gap-4 py-3">
            <div>
              <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">Controla estoque</p>
              <p className="text-xs text-[var(--ks-color-text-muted)]">
                Desligado, o item só entra no custo: a venda e a produção não tiram nada dele.
              </p>
            </div>
            <Switch checked={r.controla} onCheckedChange={(v) => mudar({ controla: v })} aria-label="Controla estoque" />
          </div>
          <div className="flex items-start justify-between gap-4 py-3">
            <div>
              <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">Pode ficar negativo</p>
              <p className="text-xs text-[var(--ks-color-text-muted)]">
                Ligado, a venda passa mesmo sem saldo e o número fica negativo (você repõe depois). Desligado, a loja, o PDV e o orçamento
                param no zero.
              </p>
            </div>
            <Switch checked={r.permitir_negativo} onCheckedChange={(v) => mudar({ permitir_negativo: v })} aria-label="Pode ficar negativo" />
          </div>
        </div>

        <section>
          <div className="flex items-center justify-between gap-2">
            <div>
              <p className="text-sm font-bold text-[var(--ks-color-text-primary)]">Conversões</p>
              <p className="text-xs text-[var(--ks-color-text-muted)]">
                Compra em rolo ou caixa e o saldo é em {unidade(r.unidade)}? Diga quanto vale cada um e lance a entrada do jeito que chegou.
              </p>
            </div>
            <button type="button" onClick={() => mudar({ conversoes: [...r.conversoes, { unidade: r.unidade === "un" ? "caixa" : "rolo", fator: 0 }] })} className="ks-button ks-button-secondary ks-button-sm shrink-0">
              <Plus size={14} /> Conversão
            </button>
          </div>
          {r.conversoes.length ? (
            <div className="mt-2 space-y-2">
              {r.conversoes.map((c, i) => (
                <div key={i} className="flex flex-wrap items-center gap-2 text-sm">
                  <span className="text-[var(--ks-color-text-muted)]">1</span>
                  <input
                    value={c.unidade}
                    onChange={(e) => mudar({ conversoes: r.conversoes.map((x, j) => (j === i ? { ...x, unidade: e.target.value } : x)) })}
                    className="ks-field w-32"
                    aria-label="Unidade da conversão"
                    maxLength={20}
                  />
                  <span className="text-[var(--ks-color-text-muted)]">=</span>
                  <CampoNumero
                    valor={c.fator}
                    aoMudar={(n) => mudar({ conversoes: r.conversoes.map((x, j) => (j === i ? { ...x, fator: n } : x)) })}
                    rotulo="Quanto vale"
                    sufixo={unidade(r.unidade)}
                    className="w-36"
                  />
                  <button type="button" onClick={() => mudar({ conversoes: r.conversoes.filter((_, j) => j !== i) })} className="ks-icon-button" aria-label="Tirar conversão">
                    <X size={15} />
                  </button>
                </div>
              ))}
            </div>
          ) : null}
        </section>

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