"use client";

/*
  A lista de insumos.

  Mora aqui, e nao na pagina, porque quem a usa e a central de Estoque — e
  arquivo de pagina do Next so pode exportar coisa de pagina. A rota antiga
  (/dashboard/production/materials) ficou so como atalho que redireciona.
*/

import { RendimentosAConfirmar } from "@/components/producao/rendimentos-a-confirmar";
import { useState, useEffect } from "react";
import { Plus, Pencil, Trash2, Search, Loader2, Package, X, Save, AlertTriangle, PackagePlus, Truck } from "lucide-react";
import CaixaDeConfirmacao, { type Confirmacao } from "@/components/ui/caixa-de-confirmacao";
import { Aviso } from "@/components/ui/aviso";
import { PageHeader } from "@/components/ui/page-header";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { usePermissoes } from "@/lib/permissoes-do-usuario";
import { formatMoneyInput, parseMoneyInput, formatMoney } from "@/utils/formatters";
import { ModalDeInsumo, UNIDADES_DE_INSUMO } from "@/components/producao/modal-de-insumo";
import { iconeDoInsumo } from "@/lib/icone-do-item";
import {
  FORMATOS, conteudoDaEmbalagem, formatoValido,
} from "@/lib/precificacao/formato-de-compra";

/* Quem vende este insumo, vindo de supplier_materials.linked_material_id.
   E o outro lado da mesma ligacao que a tela de fornecedores escreve. */
type FornecedorDoInsumo = {
  id: string;
  supplierId: string;
  supplierName: string;
  itemName: string;
  sku: string | null;
  unit: string;
  purchaseUnit: string | null;
  lastUnitPrice: number;
  lastPurchaseAt: string | null;
  leadTimeDays: number | null;
  preferred: boolean;
};

interface Material {
  id: string;
  name: string;
  unit: string;
  cost_per_unit: number;
  waste_pct_default: number;
  is_active: boolean;
  /* Estoque é opt-in por insumo: nada muda para quem não liga. */
  track_stock?: boolean;
  is_service?: boolean | null;
  current_stock?: number;
  min_stock_alert?: number | null;
  /* A língua da compra: bobina, resma, chapa… A conversão para a unidade de
     consumo é do sistema, nunca da calculadora do usuário. */
  purchase_format?: string | null;
  roll_width_m?: number | null;
  roll_length_m?: number | null;
  package_qty?: number | null;
  sheet_width_m?: number | null;
  sheet_height_m?: number | null;
}

const numeroDoCampo = (v: string) => Number(v.replace(",", ".")) || 0;
const campoDoNumero = (n: number | null | undefined) =>
  n != null && n > 0 ? String(n).replace(".", ",") : "";

interface Movimento {
  id: string;
  kind: "entrada" | "saida" | "estorno" | "ajuste" | "perda";
  quantity: number;
  unit_cost: number | null;
  balance_after: number;
  notes: string | null;
  created_at: string;
}

const ROTULO_MOVIMENTO: Record<Movimento["kind"], string> = {
  entrada: "Entrada",
  saida: "Saída (venda)",
  estorno: "Devolução",
  ajuste: "Ajuste de contagem",
  perda: "Perda na produção",
};

const qtdEnxuta = (n: number) =>
  new Intl.NumberFormat("pt-BR", { maximumFractionDigits: 3 }).format(n || 0);

/* Avatar vivo para a linha: a inicial num gradiente saturado da casa,
   estável pelo nome. */
const VIVOS = [
  "bg-gradient-to-br from-violet-500 to-purple-600",
  "bg-gradient-to-br from-sky-500 to-blue-600",
  "bg-gradient-to-br from-emerald-500 to-teal-600",
  "bg-gradient-to-br from-amber-400 to-orange-500",
  "bg-gradient-to-br from-rose-500 to-pink-600",
  "bg-gradient-to-br from-indigo-500 to-violet-600",
];
const corDoNome = (nome: string) => {
  let soma = 0;
  for (let i = 0; i < nome.length; i++) soma += nome.charCodeAt(i);
  return VIVOS[soma % VIVOS.length];
};

export function ListaDeInsumos({ embutida = false }: { embutida?: boolean }) {
  const { pode } = usePermissoes();
  const podeMexerEmInsumos = pode("materials.write");

  const [materials, setMaterials] = useState<Material[]>([]);
  const [loading, setLoading] = useState(true);
  const [searchTerm, setSearchTerm] = useState("");
  
  // Modal State
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [editingMaterial, setEditingMaterial] = useState<Material | null>(null);

  /* Modal de estoque: entrada de compra ou ajuste de contagem. */
  const [stockMaterial, setStockMaterial] = useState<Material | null>(null);
  const [stockMode, setStockMode] = useState<"entrada" | "ajuste">("entrada");
  const [stockQty, setStockQty] = useState("");
  const [stockTotal, setStockTotal] = useState("");
  /* Entrada no idioma da compra: N embalagens de tanto conteúdo, a tanto. */
  const [stockEmb, setStockEmb] = useState("1");
  const [stockConteudo, setStockConteudo] = useState("");
  const [stockLargura, setStockLargura] = useState("");
  const [stockComprimento, setStockComprimento] = useState("");
  const [stockPrecoEmb, setStockPrecoEmb] = useState("");
  const [stockNotes, setStockNotes] = useState("");
  const [stockMin, setStockMin] = useState("");
  const [stockSaving, setStockSaving] = useState(false);
  const [stockError, setStockError] = useState("");
  const [movimentos, setMovimentos] = useState<Movimento[]>([]);

  useEffect(() => {
    fetchMaterials();
  }, []);

  async function fetchMaterials() {
    try {
      const res = await fetch("/api/production/materials");
      if (!res.ok) {
        if (res.status === 401 || res.status === 403) return; // Silent fail if auth
        throw new Error("Falha ao carregar materiais");
      }
      const data = await res.json();
      setMaterials(data || []);
    } catch (error) {
      console.error('Error fetching materials:', error);
    } finally {
      setLoading(false);
    }
  }

  /* Formulário e gravação moraram aqui até virarem o ModalDeInsumo
     compartilhado com o assistente de precificação. */
  /* Uma chamada so para a empresa inteira: sao dezenas de linhas, e a tela e
     uma lista. Uma consulta por insumo seria uma ida ao banco por linha. */
  const [fornecedoresPorInsumo, setFornecedoresPorInsumo] = useState<Record<string, FornecedorDoInsumo[]>>({});
  const [reposicao, setReposicao] = useState<{
    itens: Array<{ id: string; name: string; unit: string; currentStock: number; minStockAlert: number; quantidadeSugerida: number; custoEstimado: number | null; supplierId: string | null; supplierName: string | null }>;
    semFornecedor: number;
    porFornecedor: Array<{ supplierId: string; supplierName: string; total: number; itens: Array<{ id: string; name: string; unit: string; quantidadeSugerida: number }> }>;
  } | null>(null);
  const [reposicaoAberta, setReposicaoAberta] = useState(false);

  useEffect(() => {
    let cancelado = false;
    fetch("/api/production/materials/fornecedores")
      .then((r) => (r.ok ? r.json() : null))
      .then((dados) => {
        if (cancelado || !dados?.porInsumo) return;
        setFornecedoresPorInsumo(dados.porInsumo as Record<string, FornecedorDoInsumo[]>);
      })
      .catch(() => {
        /* Saber de quem se compra e um extra: se falhar, a tela de estoque
           continua inteira. */
      });
    return () => {
      cancelado = true;
    };
  }, []);

  /* O campo "avisar abaixo de" existia desde sempre e nao avisava ninguem: era
     um numero guardado. Com o vinculo com o fornecedor, ele vira a pergunta de
     toda semana. Recarrega junto com a lista porque uma entrada de estoque
     pode tirar um item da lista de faltantes. */
  useEffect(() => {
    if (materials.length === 0) return;
    let cancelado = false;
    fetch("/api/production/materials/reposicao")
      .then((r) => (r.ok ? r.json() : null))
      .then((dados) => {
        if (cancelado || !dados?.ok) return;
        setReposicao({
          itens: dados.itens ?? [],
          semFornecedor: Number(dados.semFornecedor || 0),
          porFornecedor: dados.porFornecedor ?? [],
        });
      })
      .catch(() => {
        /* Aviso de reposicao e extra: falhar aqui nao pode derrubar a lista. */
      });
    return () => {
      cancelado = true;
    };
  }, [materials]);

  const handleOpenModal = (material?: Material) => {
    setEditingMaterial(material ?? null);
    setIsModalOpen(true);
  };

  const handleCloseModal = () => {
    setIsModalOpen(false);
    setEditingMaterial(null);
  };

  /* Era `confirm()` e `alert()` do navegador, que a casa nao usa em lugar
     nenhum: caixa do sistema operacional no meio de uma tela que tem desenho
     proprio, e sem jeito de explicar a consequencia. */
  const [confirmacao, setConfirmacao] = useState<Confirmacao | null>(null);
  const [excluindoId, setExcluindoId] = useState("");
  const [erroDaLista, setErroDaLista] = useState<string | null>(null);

  const pedirParaExcluir = (material: Material) => {
    const fornecedores = fornecedoresPorInsumo[material.id] ?? [];
    setConfirmacao({
      titulo: `Excluir o insumo "${material.name}"?`,
      texto:
        fornecedores.length > 0
          ? `${fornecedores.length} fornecedor(es) estão ligados a ele. A ligação sai junto; o histórico de compras continua.`
          : "O histórico de movimentações do estoque continua registrado.",
      confirmar: "Excluir insumo",
      tom: "perigo",
      aoConfirmar: () => {
        setConfirmacao(null);
        return handleDelete(material.id);
      },
    });
  };

  const handleDelete = async (id: string) => {
    setExcluindoId(id);
    setErroDaLista(null);
    try {
      const res = await fetch(`/api/production/materials?id=${id}`, {
        method: "DELETE",
      });

      if (!res.ok) {
        const json = await res.json().catch(() => null);
        throw new Error(json?.error || "Erro ao excluir.");
      }

      await fetchMaterials();
    } catch (err) {
      setErroDaLista(err instanceof Error ? err.message : "Erro ao excluir.");
    } finally {
      setExcluindoId("");
    }
  };

  const filteredMaterials = materials.filter(m =>
    m.name.toLowerCase().includes(searchTerm.toLowerCase())
  );

  const abrirEstoque = async (material: Material) => {
    setStockMaterial(material);
    setStockMode("entrada");
    setStockQty("");
    setStockTotal("");
    setStockEmb("1");
    setStockLargura(campoDoNumero(material.roll_width_m));
    setStockComprimento(campoDoNumero(material.roll_length_m));
    setStockConteudo(campoDoNumero(
      conteudoDaEmbalagem({
        formato: formatoValido(material.purchase_format),
        larguraM: material.roll_width_m,
        comprimentoM: material.roll_length_m,
        conteudoDaEmbalagem: material.package_qty,
        folhaLarguraM: material.sheet_width_m,
        folhaAlturaM: material.sheet_height_m,
      })
    ));
    setStockPrecoEmb("");
    setStockNotes("");
    setStockMin(material.min_stock_alert != null ? String(material.min_stock_alert) : "");
    setStockError("");
    setMovimentos([]);
    try {
      const res = await fetch(`/api/production/materials/estoque?material_id=${material.id}`, { cache: "no-store" });
      const json = await res.json().catch(() => null);
      if (res.ok) setMovimentos(json?.movimentos ?? []);
    } catch { /* extrato é conveniência; a falha dele não trava o modal */ }
  };

  /* Quantidade + valor total da compra: é como a pessoa pensa ("um rolo de
     500 m por R$ 200"). O custo unitário sai daí. */
  const custoUnitarioDaEntrada = () => {
    const qtd = parseFloat(stockQty.replace(",", ".")) || 0;
    const total = parseMoneyInput(stockTotal);
    return qtd > 0 ? total / qtd : 0;
  };

  const formatoDoEstoque = formatoValido(stockMaterial?.purchase_format);
  const entradaPorEmbalagem = stockMode === "entrada" && formatoDoEstoque !== "unidade";
  /* Bobina recalcula o conteúdo pelas dimensões desta compra — a bobina de
     hoje pode ter outro comprimento. */
  const conteudoDaEntrada = () =>
    formatoDoEstoque === "bobina"
      ? numeroDoCampo(stockLargura) * numeroDoCampo(stockComprimento)
      : numeroDoCampo(stockConteudo);

  const salvarEstoque = async () => {
    if (!stockMaterial) return;
    const qtd = parseFloat(stockQty.replace(",", ".")) || 0;
    setStockSaving(true);
    setStockError("");
    try {
      const corpo = entradaPorEmbalagem
        ? {
            material_id: stockMaterial.id,
            tipo: "entrada",
            embalagens: numeroDoCampo(stockEmb),
            conteudo: conteudoDaEntrada(),
            preco_embalagem: parseMoneyInput(stockPrecoEmb),
            notas: stockNotes || undefined,
          }
        : {
            material_id: stockMaterial.id,
            tipo: stockMode,
            quantidade: qtd,
            custo_unitario: stockMode === "entrada" ? custoUnitarioDaEntrada() : undefined,
            notas: stockNotes || undefined,
          };
      const res = await fetch("/api/production/materials/estoque", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(corpo),
      });
      const json = await res.json().catch(() => null);
      if (!res.ok) throw new Error(json?.error || "Erro ao salvar.");

      /* O alerta de mínimo mora no cadastro; salva junto quando mudou. */
      const minimo = stockMin.trim() === "" ? null : parseFloat(stockMin.replace(",", ".")) || 0;
      if (minimo !== (stockMaterial.min_stock_alert ?? null)) {
        await fetch("/api/production/materials", {
          method: "PUT",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ id: stockMaterial.id, min_stock_alert: minimo }),
        });
      }

      await fetchMaterials();
      setStockMaterial(null);
    } catch (err) {
      setStockError(err instanceof Error ? err.message : "Erro ao salvar.");
    } finally {
      setStockSaving(false);
    }
  };

  const badgeDeEstoque = (m: Material) => {
    if (!m.track_stock) return <span className="text-slate-400">—</span>;
    const saldo = m.current_stock ?? 0;
    const minimo = m.min_stock_alert;
    const baixo = saldo <= 0 || (minimo != null && saldo < minimo);
    return (
      <span
        className={`flex items-center gap-1 text-xs font-medium px-2 py-1 rounded-full w-fit ${
          baixo ? "text-red-600 bg-red-50" : "text-emerald-700 bg-emerald-50"
        }`}
        title={minimo != null ? `Alerta abaixo de ${qtdEnxuta(minimo)} ${m.unit}` : undefined}
      >
        {baixo && <AlertTriangle className="h-3 w-3" />}
        {qtdEnxuta(saldo)} {m.unit}
      </span>
    );
  };

  return (
    <div className="space-y-6">
      {/* Embutida na central de Estoque, a lista dispensa o cabeçalho próprio —
          o botão de cadastrar muda para a barra do card. */}
      {!embutida && (
        <PageHeader
          eyebrow="Produção"
          title="Insumos"
          subtitle="Gerencie os materiais usados na produção."
          actions={
            podeMexerEmInsumos ? (<Button onClick={() => handleOpenModal()} icon={<Plus size={16} />}>
              Novo Insumo
            </Button>) : null
          }
        />
      )}

      <RendimentosAConfirmar podeConfirmar={podeMexerEmInsumos} />

      <div className="ks-surface rounded-xl shadow-sm border border-[var(--ks-color-border-subtle)] overflow-hidden">
        {/* Toolbar */}
        <div className="p-4 border-b border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-subtle)]/30 flex flex-wrap items-center gap-3 justify-between">
          <div className="max-w-md flex-1 min-w-[220px] relative">
            <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" />
            <Input
              placeholder="Buscar insumos..."
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              className="pl-9"
            />
          </div>
          <div className="flex items-center gap-4 text-xs font-medium text-slate-500">
            <span className="flex items-center gap-1.5">
              <span className="w-1.5 h-1.5 rounded-full bg-[var(--ks-color-primary)]" />
              {materials.length} insumos
            </span>
            <span className="flex items-center gap-1.5">
              <span className="w-1.5 h-1.5 rounded-full bg-emerald-500" />
              {materials.filter((m) => m.track_stock).length} com controle
            </span>
            <span className="flex items-center gap-1.5">
              <span className="w-1.5 h-1.5 rounded-full bg-rose-500" />
              {materials.filter((m) => m.track_stock && ((m.current_stock ?? 0) <= 0 || (m.min_stock_alert != null && (m.current_stock ?? 0) < m.min_stock_alert))).length} para repor
            </span>
          </div>
          {embutida && podeMexerEmInsumos && (
            <Button onClick={() => handleOpenModal()} icon={<Plus size={16} />}>
              Novo Insumo
            </Button>
          )}
        </div>

        {loading ? (
          <div className="flex justify-center py-16">
            <Loader2 className="h-8 w-8 animate-spin text-primary" />
          </div>
        ) : filteredMaterials.length === 0 ? (
          <div className="flex flex-col items-center justify-center py-16 text-center">
            <div className="bg-slate-50 p-4 rounded-full mb-3">
              <Package className="h-8 w-8 text-slate-300" />
            </div>
            <h3 className="text-lg font-medium text-slate-900">Nenhum insumo encontrado</h3>
            <p className="text-slate-500 max-w-sm mt-1 mb-4">
              Cadastre as matérias-primas que você utiliza na produção dos seus produtos.
            </p>
            {podeMexerEmInsumos && (<Button variant="outline" onClick={() => handleOpenModal()}>
              Cadastrar Insumo
            </Button>)}
          </div>
        ) : (
          <div className="overflow-x-auto">
            <div className="min-w-[760px]">
              <div className="grid grid-cols-[minmax(0,1fr)_150px_110px_130px_100px_120px] gap-3 px-6 py-3 text-[10px] uppercase tracking-[0.14em] text-slate-400 font-semibold">
                <span>Nome</span>
                <span>Unidade</span>
                <span>Custo Unit.</span>
                <span>Estoque</span>
                <span>Perda Padrão</span>
                <span />
              </div>
              {filteredMaterials.map((material) => {
                const formato = formatoValido(material.purchase_format);
                const rotuloDoFormato = formato !== "unidade" ? FORMATOS[formato]?.rotulo : null;
                return (
                <div
                  key={material.id}
                  onClick={podeMexerEmInsumos ? () => void abrirEstoque(material) : undefined}
                  title={podeMexerEmInsumos ? "Estoque: entrada, ajuste e extrato" : undefined}
                  className={`grid grid-cols-[minmax(0,1fr)_150px_110px_130px_100px_120px] gap-3 items-center px-6 py-3.5 border-t border-slate-100/60 hover:bg-[var(--ks-color-bg-subtle)]/50 transition-colors ${podeMexerEmInsumos ? "cursor-pointer" : ""}`}
                >
                  <div className="flex items-center gap-3 min-w-0">
                    {iconeDoInsumo(material.name) ? (
                      // eslint-disable-next-line @next/next/no-img-element
                      <img
                        src={iconeDoInsumo(material.name) as string}
                        alt=""
                        className="h-10 w-10 object-contain shrink-0"
                      />
                    ) : (
                    <span className={`h-9 w-9 rounded-xl flex items-center justify-center text-sm font-bold text-white shadow-sm shrink-0 ${corDoNome(material.name)}`}>
                      {material.name.trim().charAt(0).toUpperCase()}
                    </span>
                    )}
                    <div className="min-w-0">
                      <p className="font-semibold text-sm text-[var(--ks-color-text-primary)] truncate">{material.name}</p>
                      {rotuloDoFormato && (
                        <p className="text-[11px] text-slate-400">comprado em {rotuloDoFormato.toLowerCase()}</p>
                      )}
                      {(() => {
                        /* De quem se compra: o preferido, ou o mais barato da
                           ultima compra. Antes, o unico vestigio de fornecedor
                           nesta tela era um texto de exemplo dentro do campo de
                           observacao. */
                        const lista = fornecedoresPorInsumo[material.id] ?? [];
                        if (lista.length === 0) return null;
                        const escolhido = lista.find((f) => f.preferred) ?? lista[0];
                        return (
                          <p className="text-[11px] text-slate-500 truncate flex items-center gap-1">
                            <Truck className="h-3 w-3 shrink-0 text-slate-400" />
                            {escolhido.supplierName}
                            {escolhido.lastUnitPrice > 0 ? ` · ${formatMoney(escolhido.lastUnitPrice)}` : ""}
                            {lista.length > 1 ? ` · +${lista.length - 1}` : ""}
                          </p>
                        );
                      })()}
                    </div>
                  </div>
                  <div className="text-sm text-slate-500">
                    {UNIDADES_DE_INSUMO.find(u => u.value === material.unit)?.label || material.unit}
                  </div>
                  <div>
                    <span className="text-sm font-semibold tabular-nums text-[var(--ks-color-text-primary)]">
                      {formatMoney(material.cost_per_unit)}
                    </span>
                  </div>
                  <div>
                    {material.track_stock ? (
                      badgeDeEstoque(material)
                    ) : (
                      <span className="text-[11px] text-slate-400">não controlado</span>
                    )}
                  </div>
                  <div>
                    {material.waste_pct_default > 0 ? (
                      <span className="text-amber-600 flex items-center gap-1 text-xs font-medium bg-amber-50 px-2 py-1 rounded-full w-fit">
                        {material.waste_pct_default}%
                      </span>
                    ) : (
                      <span className="text-slate-400">-</span>
                    )}
                  </div>
                  <div className="flex items-center justify-end gap-1">
                    {podeMexerEmInsumos && (<Button size="icon" variant="ghost" title="Estoque: entrada e ajuste"
                      onClick={(e) => { e.stopPropagation(); void abrirEstoque(material); }}>
                      <PackagePlus className="h-4 w-4 text-emerald-600" />
                    </Button>)}
                    {podeMexerEmInsumos && (<Button size="icon" variant="ghost" title="Editar insumo"
                      onClick={(e) => { e.stopPropagation(); handleOpenModal(material); }}>
                      <Pencil className="h-4 w-4 text-slate-500" />
                    </Button>)}
                    {podeMexerEmInsumos && (<Button size="icon" variant="ghost" title="Excluir insumo"
                      onClick={(e) => { e.stopPropagation(); pedirParaExcluir(material); }}>
                      <Trash2 className="h-4 w-4 text-red-400" />
                    </Button>)}
                  </div>
                </div>
                );
              })}
            </div>
          </div>
        )}
      </div>


      {reposicao && reposicao.itens.length > 0 ? (
        <div className="space-y-3">
          <Aviso
            titulo={
              reposicao.itens.length === 1
                ? "1 insumo está abaixo do mínimo"
                : `${reposicao.itens.length} insumos estão abaixo do mínimo`
            }
            acao={
              <button
                type="button"
                onClick={() => setReposicaoAberta((v) => !v)}
                className="ks-button ks-button-primary ks-button-sm"
              >
                {reposicaoAberta ? "Esconder" : "Ver o que comprar"}
              </button>
            }
          >
            {reposicao.porFornecedor.length > 0
              ? reposicao.porFornecedor.length === 1
                ? "Um fornecedor para chamar."
                : `${reposicao.porFornecedor.length} fornecedores para chamar.`
              : "Nenhum deles tem fornecedor ligado ainda."}
          </Aviso>

          {reposicaoAberta ? (
            <div className="space-y-3">
              {reposicao.porFornecedor.map((grupo) => (
                <div key={grupo.supplierId} className="ks-card p-3">
                  <div className="flex flex-wrap items-baseline justify-between gap-2">
                    <a
                      href={`/dashboard/fornecedores/meus-fornecedores/${grupo.supplierId}/compras`}
                      className="text-sm font-semibold text-[var(--ks-color-primary)] underline-offset-2 hover:underline"
                    >
                      {grupo.supplierName}
                    </a>
                    {grupo.total > 0 && (
                      <span className="text-xs text-slate-500">estimado {formatMoney(grupo.total)}</span>
                    )}
                  </div>
                  <ul className="mt-1.5 space-y-0.5">
                    {grupo.itens.map((item) => (
                      <li key={item.id} className="text-xs text-slate-600">
                        {item.name} — pedir {item.quantidadeSugerida} {item.unit}
                      </li>
                    ))}
                  </ul>
                </div>
              ))}

              {reposicao.semFornecedor > 0 && (
                <div className="rounded-xl bg-[var(--ks-color-bg-inset)] p-3 text-xs text-[var(--ks-color-text-muted)]">
                  {reposicao.semFornecedor === 1
                    ? "1 item está acabando e ainda não tem fornecedor ligado."
                    : `${reposicao.semFornecedor} itens estão acabando e ainda não têm fornecedor ligado.`}{" "}
                  Ligue na tela de compras do fornecedor para eles aparecerem aqui com preço e prazo.
                </div>
              )}
            </div>
          ) : null}
        </div>
      ) : null}

      {erroDaLista ? (
        <Aviso tom="ruim" aoFechar={() => setErroDaLista(null)}>
          {erroDaLista}
        </Aviso>
      ) : null}

      <ModalDeInsumo
        aberta={isModalOpen}
        insumo={editingMaterial}
        aoFechar={handleCloseModal}
        aoSalvar={() => void fetchMaterials()}
      />

      {/* Modal de estoque: dar entrada e ajustar contagem, com o extrato junto. */}
      {stockMaterial && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4 animate-in fade-in">
          <div className="bg-white rounded-xl shadow-xl w-full max-w-lg overflow-hidden animate-in zoom-in-95 duration-200 max-h-[90vh] flex flex-col">
            <div className="flex items-center justify-between p-4 border-b bg-slate-50/50">
              <div>
                <h2 className="text-lg font-semibold text-slate-800">Estoque · {stockMaterial.name}</h2>
                <p className="text-xs text-slate-500">
                  {stockMaterial.track_stock
                    ? <>Saldo atual: <strong>{qtdEnxuta(stockMaterial.current_stock ?? 0)} {stockMaterial.unit}</strong></>
                    : "Sem controle ainda — a primeira entrada liga o controle sozinha."}
                </p>
              </div>
              <Button size="icon" variant="ghost" onClick={() => setStockMaterial(null)}>
                <X className="h-4 w-4" />
              </Button>
            </div>

            <div className="p-6 space-y-4 overflow-y-auto">
              <div className="flex gap-2">
                <button type="button" onClick={() => setStockMode("entrada")}
                  className={`px-3 py-1.5 rounded-full text-xs font-semibold border transition ${
                    stockMode === "entrada" ? "bg-slate-800 text-white border-slate-800" : "text-slate-500 border-slate-200"}`}>
                  Entrada de compra
                </button>
                <button type="button" onClick={() => setStockMode("ajuste")}
                  className={`px-3 py-1.5 rounded-full text-xs font-semibold border transition ${
                    stockMode === "ajuste" ? "bg-slate-800 text-white border-slate-800" : "text-slate-500 border-slate-200"}`}>
                  Ajuste de contagem
                </button>
              </div>

              {stockMode === "entrada" && entradaPorEmbalagem ? (
                <>
                  <div className="grid grid-cols-2 gap-4">
                    <div className="space-y-2">
                      <label className="text-sm font-medium text-slate-700">
                        Quantas {FORMATOS[formatoDoEstoque].embalagens}?
                      </label>
                      <Input inputMode="decimal" value={stockEmb} placeholder="1"
                        onChange={e => setStockEmb(e.target.value)} />
                    </div>
                    <div className="space-y-2">
                      <label className="text-sm font-medium text-slate-700">
                        Preço por {FORMATOS[formatoDoEstoque].embalagem}
                      </label>
                      <Input value={stockPrecoEmb} placeholder="0,00"
                        onChange={e => setStockPrecoEmb(formatMoneyInput(e.target.value))} />
                    </div>
                  </div>
                  {formatoDoEstoque === "bobina" ? (
                    <div className="grid grid-cols-2 gap-4">
                      <div className="space-y-2">
                        <label className="text-sm font-medium text-slate-700">Largura (m)</label>
                        <Input inputMode="decimal" value={stockLargura} placeholder="1,60"
                          onChange={e => setStockLargura(e.target.value)} />
                      </div>
                      <div className="space-y-2">
                        <label className="text-sm font-medium text-slate-700">Comprimento (m)</label>
                        <Input inputMode="decimal" value={stockComprimento} placeholder="50"
                          onChange={e => setStockComprimento(e.target.value)} />
                      </div>
                    </div>
                  ) : (
                    <div className="space-y-2">
                      <label className="text-sm font-medium text-slate-700">
                        Conteúdo de cada ({stockMaterial.unit})
                      </label>
                      <Input inputMode="decimal" value={stockConteudo} placeholder="500"
                        onChange={e => setStockConteudo(e.target.value)} />
                    </div>
                  )}
                  {(() => {
                    /* A conversão mostrada antes de salvar: quem confere o
                       preview confia no que entra. */
                    const n = numeroDoCampo(stockEmb);
                    const conteudo = conteudoDaEntrada();
                    const preco = parseMoneyInput(stockPrecoEmb);
                    if (n > 0 && conteudo > 0 && preco > 0) {
                      return (
                        <p className="text-xs text-slate-500">
                          Entram <strong>{qtdEnxuta(n * conteudo)} {stockMaterial.unit}</strong> a{" "}
                          <strong>{formatMoney(preco / conteudo)}</strong> por {stockMaterial.unit}. O custo do
                          insumo vira a média do que você já tem com esta compra.
                        </p>
                      );
                    }
                    return null;
                  })()}
                </>
              ) : stockMode === "entrada" ? (
                <>
                  <div className="grid grid-cols-2 gap-4">
                    <div className="space-y-2">
                      <label className="text-sm font-medium text-slate-700">Quantidade ({stockMaterial.unit})</label>
                      <Input inputMode="decimal" value={stockQty} placeholder="500"
                        onChange={e => setStockQty(e.target.value)} />
                    </div>
                    <div className="space-y-2">
                      <label className="text-sm font-medium text-slate-700">Valor pago (total)</label>
                      <Input value={stockTotal} placeholder="0,00"
                        onChange={e => setStockTotal(formatMoneyInput(e.target.value))} />
                    </div>
                  </div>
                  {custoUnitarioDaEntrada() > 0 && (
                    <p className="text-xs text-slate-500">
                      Sai a <strong>{formatMoney(custoUnitarioDaEntrada())}</strong> por {stockMaterial.unit}. O
                      custo do insumo vira a média do que você já tem com esta compra.
                    </p>
                  )}
                </>
              ) : (
                <div className="space-y-2">
                  <label className="text-sm font-medium text-slate-700">Saldo contado ({stockMaterial.unit})</label>
                  <Input inputMode="decimal" value={stockQty} placeholder="0"
                    onChange={e => setStockQty(e.target.value)} />
                  <p className="text-xs text-slate-500">
                    Contou na prateleira e deu diferente do sistema? Informe o que existe de verdade.
                  </p>
                </div>
              )}

              <div className="grid grid-cols-2 gap-4">
                <div className="space-y-2">
                  <label className="text-sm font-medium text-slate-700">Avisar abaixo de</label>
                  <Input inputMode="decimal" value={stockMin} placeholder="Ex: 50"
                    onChange={e => setStockMin(e.target.value)} />
                </div>
                <div className="space-y-2">
                  <label className="text-sm font-medium text-slate-700">Observação</label>
                  <Input value={stockNotes} placeholder="Ex: fornecedor X"
                    onChange={e => setStockNotes(e.target.value)} />
                </div>
              </div>

              {stockError && (
                <div className="text-sm text-red-600 bg-red-50 p-3 rounded-md flex items-center gap-2">
                  <AlertTriangle className="h-4 w-4" />
                  {stockError}
                </div>
              )}

              {/* Quem vende este insumo, do mais barato para o mais caro.
                  E a comparacao que o modulo de fornecedores prometia e nunca
                  fez: antes, cada fornecedor tinha a propria lista de
                  materiais e os precos nunca se encontravam. */}
              {(fornecedoresPorInsumo[stockMaterial.id]?.length ?? 0) > 0 && (
                <div>
                  <div className="text-xs font-semibold text-slate-500 mb-2">Quem vende este insumo</div>
                  <div className="space-y-1">
                    {(fornecedoresPorInsumo[stockMaterial.id] ?? []).map((fornecedor, posicao) => (
                      <div
                        key={fornecedor.id}
                        className="flex items-baseline justify-between gap-2 rounded-lg bg-slate-50 px-3 py-2 text-xs"
                      >
                        <div className="min-w-0">
                          <span className="font-medium text-slate-700">{fornecedor.supplierName}</span>
                          {fornecedor.preferred && (
                            <span className="ml-2 rounded-full bg-indigo-100 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider text-indigo-700">
                              preferido
                            </span>
                          )}
                          {posicao === 0 && !fornecedor.preferred && fornecedor.lastUnitPrice > 0 && (
                            <span className="ml-2 rounded-full bg-emerald-100 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider text-emerald-700">
                              mais barato
                            </span>
                          )}
                          <div className="truncate text-[11px] text-slate-400">
                            {fornecedor.itemName}
                            {fornecedor.sku ? ` · ${fornecedor.sku}` : ""}
                            {fornecedor.leadTimeDays !== null ? ` · entrega em ${fornecedor.leadTimeDays} dia(s)` : ""}
                          </div>
                        </div>
                        <div className="shrink-0 text-right">
                          <div className="font-semibold text-slate-700">
                            {fornecedor.lastUnitPrice > 0 ? formatMoney(fornecedor.lastUnitPrice) : "sem compra"}
                          </div>
                          {fornecedor.lastPurchaseAt && (
                            <div className="text-[11px] text-slate-400">
                              {new Date(`${fornecedor.lastPurchaseAt}T12:00:00`).toLocaleDateString("pt-BR")}
                            </div>
                          )}
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
              )}

              {movimentos.length > 0 && (
                <div>
                  <div className="text-xs font-semibold text-slate-500 mb-2">Últimos movimentos</div>
                  <div className="space-y-1 max-h-44 overflow-y-auto pr-1">
                    {movimentos.map((mv) => (
                      <div key={mv.id} className="flex items-baseline justify-between gap-2 text-xs bg-slate-50 rounded-lg px-3 py-2">
                        <div className="min-w-0">
                          <span className={mv.kind === "saida" ? "text-red-600 font-medium" : mv.kind === "entrada" ? "text-emerald-700 font-medium" : "text-slate-700 font-medium"}>
                            {ROTULO_MOVIMENTO[mv.kind]}
                          </span>
                          <span className="text-slate-400 ml-2">
                            {new Date(mv.created_at).toLocaleDateString("pt-BR")}
                          </span>
                          {mv.notes && <div className="text-[11px] text-slate-400 truncate">{mv.notes}</div>}
                        </div>
                        <div className="text-right shrink-0">
                          <div className={mv.kind === "saida" ? "text-red-600" : ""}>
                            {mv.kind === "saida" || (mv.kind === "ajuste" && mv.quantity < 0) ? "−" : "+"}
                            {qtdEnxuta(Math.abs(mv.quantity))} {stockMaterial.unit}
                          </div>
                          <div className="text-[10px] text-slate-400">saldo {qtdEnxuta(mv.balance_after)}</div>
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
              )}
            </div>

            <div className="flex justify-end gap-3 p-4 border-t">
              <Button type="button" variant="ghost" onClick={() => setStockMaterial(null)}>
                Cancelar
              </Button>
              <Button onClick={() => void salvarEstoque()} disabled={stockSaving}>
                {stockSaving ? <Loader2 className="h-4 w-4 animate-spin mr-2" /> : <Save className="h-4 w-4 mr-2" />}
                {stockMode === "entrada" ? "Registrar entrada" : "Ajustar saldo"}
              </Button>
            </div>
          </div>
        </div>
      )}

      <CaixaDeConfirmacao
        pedido={confirmacao}
        ocupado={Boolean(excluindoId)}
        aoFechar={() => setConfirmacao(null)}
      />
    </div>
  );
}
