/* global React, Icon, Button, Chip, brl, numBr */

// ─── Tabela de preço · seleção de produtos e preço negociado ────────────────
// Aqui a `tabela_preco_itens` finalmente serve pra alguma coisa: ela guarda
// QUAIS produtos a tabela cobre e, quando houver, o preço COMBINADO com aquele
// distribuidor (`preco_override`).
//
// Regra de preço da casa — uma só, escrita num lugar só (precoDaTabela):
//   1. preço negociado do item, se existir
//   2. senão, a base do canal da tabela menos o desconto padrão dela
//   3. senão, a base do canal
// O documento imprime essa regra e o pedido a aplica. Duas implementações da
// mesma regra é como preço passa a divergir entre o papel e a fatura.

// Qual coluna do produto cada tipo de tabela usa. Espelha o TIPOS_TABELA do
// Produtos_Forms e o getPrecoFromTabela do Pedidos — os três TÊM que concordar.
const TPI_BASE_POR_TIPO = {
  "Distribuidor":  "precoDiv",
  "Salão":         "precoSalao",
  "Cliente Final": "venda",
  "Promocional":   "precoPromo",
  "Personalizada": "venda",
};

// Chave do item na tabela. Produto solto: (id, null). Variação: (produtoId, id)
// — a variação tem id próprio e aponta pro pai. Sem essa distinção, o preço
// negociado do 500 ml cairia em cima do 1 L.
function tpiChave(x) {
  if (!x) return { produtoId: null, variacaoId: null };
  return x.produtoId
    ? { produtoId: x.produtoId, variacaoId: x.id }
    : { produtoId: x.id, variacaoId: null };
}
function tpiMesmoItem(a, b) {
  return a.produtoId === b.produtoId && (a.variacaoId || null) === (b.variacaoId || null);
}

// Base do canal, sem desconto e sem negociação.
function precoBaseTabela(x, tabela) {
  const campo = TPI_BASE_POR_TIPO[(tabela && (tabela.tipo || tabela.tipo_tabela)) || "Cliente Final"] || "venda";
  return Number(x[campo]) || Number(x.venda) || 0;
}

// A regra inteira. Devolve { preco, origem } — 'negociado' | 'tabela'.
// `itens` é o que veio de tmDb.loadTabelaItens (pode ser [] ou null).
function precoDaTabela(x, tabela, itens) {
  if (!x) return { preco: 0, origem: "tabela" };
  const chave = tpiChave(x);
  const neg = (itens || []).find(it => tpiMesmoItem(it, chave));
  if (neg && neg.override != null && neg.override !== "") {
    // numBr e nao Number: quando o documento e gerado DE DENTRO do formulario,
    // os itens ainda sao o rascunho — o override e a string que ela acabou de
    // digitar ("22,50"). Number daria NaN, o `|| 0` viraria zero e o papel sairia
    // com R$ 0,00 no produto negociado. Salvo, ja vem numerico; os dois casos
    // passam por aqui.
    return { preco: Math.round(numBr(neg.override) * 100) / 100, origem: "negociado" };
  }
  let preco = precoBaseTabela(x, tabela);
  // numBr, nao parseFloat: o desconto e digitado em campo de texto livre, e
  // "12,5%" tem que valer 12,5 aqui e no toDbTabelaPreco — se os dois lerem
  // diferente, o papel e o pedido divergem.
  const pct = numBr(String((tabela && (tabela.desconto || tabela.desconto_pct)) || "0").replace("%", ""));
  if (pct) preco = preco * (1 - pct / 100);
  return { preco: Math.round(preco * 100) / 100, origem: "tabela" };
}

// ── Seletor ─────────────────────────────────────────────────────────────────
// props: { itens, onChange, produtos, variacoes, tabela }
function TabelaPrecoItensSelector({ itens, onChange, produtos, variacoes, tabela }) {
  const [busca, setBusca]   = React.useState("");
  const [fLinha, setFLinha] = React.useState("");
  const [soDentro, setSoDentro] = React.useState(false);

  const lista = itens || [];
  const dentro = (chave) => lista.some(it => tpiMesmoItem(it, chave));
  const itemDe = (chave) => lista.find(it => tpiMesmoItem(it, chave));

  // Linhas do seletor: produto sem variação vira 1 linha; produto COM variação
  // vira uma linha por variação (o pai não é selecionável, porque o preço que
  // vale é o da variação).
  const linhas = [];
  (produtos || []).forEach(p => {
    if (p.tipo === "insumo") return;                       // insumo não vai pra tabela de venda
    const vars = (variacoes || []).filter(v => v.produtoId === p.id);
    if (p.temVariacoes && vars.length > 0) {
      vars.forEach(v => linhas.push({
        chave: tpiChave(v), rotulo: `${p.name || p.nome} · ${v.nome || ""}`.trim(),
        sku: v.sku || p.sku, linha: p.linha, cat: p.cat || p.categoria, alvo: v, ehVariacao: true,
      }));
    } else {
      linhas.push({
        chave: tpiChave(p), rotulo: p.name || p.nome || "",
        sku: p.sku, linha: p.linha, cat: p.cat || p.categoria, alvo: p, ehVariacao: false,
      });
    }
  });

  const q = busca.trim().toLowerCase();
  const visiveis = linhas.filter(l => {
    if (soDentro && !dentro(l.chave)) return false;
    if (fLinha && l.linha !== fLinha) return false;
    if (!q) return true;
    return (l.rotulo || "").toLowerCase().includes(q) || (l.sku || "").toLowerCase().includes(q);
  });

  const linhasOpts = Array.from(new Set(linhas.map(l => l.linha).filter(Boolean))).sort();

  const alterna = (l) => {
    if (dentro(l.chave)) onChange(lista.filter(it => !tpiMesmoItem(it, l.chave)));
    else onChange(lista.concat([{ ...l.chave, override: null }]));
  };
  const setOverride = (l, v) => {
    onChange(lista.map(it => tpiMesmoItem(it, l.chave) ? { ...it, override: v } : it));
  };
  const adicionarVisiveis = () => {
    const novos = visiveis.filter(l => !dentro(l.chave)).map(l => ({ ...l.chave, override: null }));
    if (novos.length) onChange(lista.concat(novos));
  };

  return (
    <div>
      <div className="toolbar" style={{ gap: 8, marginBottom: 12, flexWrap: "wrap" }}>
        <input className="input" style={{ flex: 1, minWidth: 220 }} value={busca}
          onChange={(e) => setBusca(e.target.value)} placeholder="Buscar por nome ou SKU…" />
        <select className="input" style={{ width: 190 }} value={fLinha} onChange={(e) => setFLinha(e.target.value)}>
          <option value="">Todas as linhas</option>
          {linhasOpts.map(l => <option key={l} value={l}>{l}</option>)}
        </select>
        <Chip active={soDentro} onClick={() => setSoDentro(!soDentro)}>Só os da tabela ({lista.length})</Chip>
        {visiveis.some(l => !dentro(l.chave)) && (
          <Button variant="secondary" size="sm" icon="plus" onClick={adicionarVisiveis}>
            Adicionar os {visiveis.filter(l => !dentro(l.chave)).length} visíveis
          </Button>
        )}
      </div>

      {visiveis.length === 0 && (
        <div style={{ padding: "28px 0", textAlign: "center", color: "var(--tm-fg-3)", fontSize: 12.5 }}>
          {soDentro && lista.length === 0
            ? "Nenhum produto na tabela ainda — desmarque o filtro e escolha os primeiros."
            : "Nenhum produto encontrado com esse filtro."}
        </div>
      )}

      {visiveis.length > 0 && (
        <div className="tpi-lista">
          <div className="tpi-row tpi-head">
            <div />
            <div>Produto</div>
            <div className="right">Preço da tabela</div>
            <div className="right">Preço negociado</div>
            <div className="right">Diferença</div>
          </div>
          {visiveis.slice(0, 300).map((l, i) => {
            const on   = dentro(l.chave);
            const item = itemDe(l.chave);
            // itens = [] de propósito: esta coluna mostra a base da tabela
            // (canal menos desconto), que é justamente o que o negociado supera.
            const base = precoDaTabela(l.alvo, tabela, []).preco;
            const neg  = item && item.override !== null && item.override !== "" ? numBr(item.override) : null;
            const dif  = neg != null && base > 0 ? ((neg - base) / base) * 100 : null;
            return (
              <div key={l.chave.produtoId + ":" + (l.chave.variacaoId || "-") + ":" + i}
                   className={"tpi-row" + (on ? " on" : "")}>
                <div><input type="checkbox" checked={on} onChange={() => alterna(l)} /></div>
                <div className="tpi-nome">
                  <div className="n">{l.rotulo}</div>
                  <div className="s">{l.sku}{l.linha ? ` · ${l.linha}` : ""}{l.ehVariacao ? " · variação" : ""}</div>
                </div>
                <div className="right tpi-base">R$ {brl(base)}</div>
                <div className="right">
                  {/* Só quem está NA tabela pode ter preço negociado — campo de
                      texto solto em linha não selecionada seria promessa falsa. */}
                  {on ? (
                    <input className="input num right" style={{ width: 108 }}
                      value={item && item.override != null ? item.override : ""}
                      onChange={(e) => setOverride(l, e.target.value)}
                      placeholder={brl(base)} />
                  ) : <span style={{ color: "var(--tm-fg-4)", fontSize: 11.5 }}>—</span>}
                </div>
                <div className="right">
                  {neg != null && dif != null ? (
                    <span className={"badge2 " + (dif < -0.5 ? "b-warn" : dif > 0.5 ? "b-ok" : "b-info")}>
                      {dif > 0 ? "+" : ""}{dif.toFixed(1).replace(".", ",")}%
                    </span>
                  ) : <span style={{ color: "var(--tm-fg-4)", fontSize: 11.5 }}>—</span>}
                </div>
              </div>
            );
          })}
          {visiveis.length > 300 && (
            <div style={{ padding: "10px 12px", fontSize: 11.5, color: "var(--tm-fg-3)" }}>
              Mostrando os primeiros 300 de {visiveis.length}. Use a busca ou o filtro de linha para chegar no resto.
            </div>
          )}
        </div>
      )}
    </div>
  );
}

Object.assign(window, {
  TabelaPrecoItensSelector, precoDaTabela, precoBaseTabela, tpiChave, tpiMesmoItem, TPI_BASE_POR_TIPO,
});
