/* ============================================================
   PCP — Movimentações: gráfico Entradas × Saídas + estoque mínimo
   (shares global scope; useState etc. from ui.jsx)
   ============================================================ */

// Serie é calculada dinâmicamente em Movimentacoes() a partir de app.movimentos

function LineChart({ data }) {
  const [hi, setHi] = useState(null);
  const pts = data.points, n = pts.length, min = data.min;
  const W = 720, H = 280, padL = 48, padR = 20, padT = 18, padB = 32;
  const maxV = Math.max(min, ...pts.flatMap((p) => [p.entrada, p.saida])) * 1.14;
  const x = (i) => padL + (n === 1 ? 0 : (i / (n - 1)) * (W - padL - padR));
  const y = (v) => padT + (1 - v / maxV) * (H - padT - padB);
  const line = (k) => pts.map((p, i) => `${i ? "L" : "M"}${x(i).toFixed(1)} ${y(p[k]).toFixed(1)}`).join(" ");
  const area = (k) => `${line(k)} L${x(n - 1).toFixed(1)} ${y(0)} L${x(0).toFixed(1)} ${y(0)} Z`;
  const ticks = 4;
  const tickVals = Array.from({ length: ticks + 1 }, (_, i) => Math.round((maxV / ticks) * i));

  const onMove = (e) => {
    const r = e.currentTarget.getBoundingClientRect();
    const rx = ((e.clientX - r.left) / r.width) * W;
    let i = Math.round((rx - padL) / ((W - padL - padR) / Math.max(n - 1, 1)));
    setHi(Math.max(0, Math.min(n - 1, i)));
  };

  return (
    <div style={{ position: "relative" }}>
      <svg viewBox={`0 0 ${W} ${H}`} width="100%" style={{ display: "block", overflow: "visible" }}
        onMouseMove={onMove} onMouseLeave={() => setHi(null)}>
        <defs>
          <linearGradient id="gEnt" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="var(--ok)" stopOpacity="0.22" />
            <stop offset="100%" stopColor="var(--ok)" stopOpacity="0" />
          </linearGradient>
          <linearGradient id="gSai" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="var(--crit)" stopOpacity="0.18" />
            <stop offset="100%" stopColor="var(--crit)" stopOpacity="0" />
          </linearGradient>
        </defs>

        {/* gridlines + y labels */}
        {tickVals.map((tv, i) => (
          <g key={i}>
            <line x1={padL} x2={W - padR} y1={y(tv)} y2={y(tv)} stroke="var(--line)" strokeWidth="1" />
            <text x={padL - 8} y={y(tv) + 3.5} textAnchor="end" fontSize="10.5" fill="var(--muted)" fontFamily="var(--num)">{DB.NUM(tv)}</text>
          </g>
        ))}

        {/* x labels */}
        {pts.map((p, i) => (
          <text key={i} x={x(i)} y={H - padB + 18} textAnchor="middle" fontSize="10.5"
            fill={hi === i ? "var(--ink)" : "var(--muted)"} fontFamily="var(--num)" fontWeight={hi === i ? 600 : 400}>{p.label}</text>
        ))}

        {/* areas */}
        <path d={area("entrada")} fill="url(#gEnt)" />
        <path d={area("saida")} fill="url(#gSai)" />

        {/* min stock dashed reference */}
        <line x1={padL} x2={W - padR} y1={y(min)} y2={y(min)} stroke="var(--warn)" strokeWidth="1.6" strokeDasharray="6 5" />
        <text x={W - padR} y={y(min) - 6} textAnchor="end" fontSize="10.5" fill="var(--warn)" fontWeight="600">Estoque mín.</text>

        {/* lines */}
        <path d={line("saida")} fill="none" stroke="var(--crit)" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" />
        <path d={line("entrada")} fill="none" stroke="var(--ok)" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" />

        {/* hover guide + dots */}
        {hi != null && <line x1={x(hi)} x2={x(hi)} y1={padT} y2={H - padB} stroke="var(--line-strong)" strokeWidth="1" strokeDasharray="3 3" />}
        {pts.map((p, i) => (
          <g key={i} style={{ opacity: hi == null || hi === i ? 1 : 0.45 }}>
            <circle cx={x(i)} cy={y(p.entrada)} r={hi === i ? 4.5 : 3} fill="var(--surface)" stroke="var(--ok)" strokeWidth="2" />
            <circle cx={x(i)} cy={y(p.saida)} r={hi === i ? 4.5 : 3} fill="var(--surface)" stroke="var(--crit)" strokeWidth="2" />
          </g>
        ))}
      </svg>

      {hi != null && (
        <div style={{ position: "absolute", top: 0, left: `${(x(hi) / W) * 100}%`,
          transform: `translateX(${hi > n / 2 ? "-108%" : "8%"})`, pointerEvents: "none",
          background: "var(--overlay)", border: "1px solid var(--line-strong)", borderRadius: "var(--radius)",
          boxShadow: "var(--shadow)", padding: "9px 11px", minWidth: 132 }}>
          <div style={{ fontSize: 11.5, color: "var(--muted)", marginBottom: 6, fontWeight: 600 }}>{pts[hi].label}</div>
          <div className="row" style={{ justifyContent: "space-between", gap: 14, fontSize: 12.5 }}>
            <span className="row gap6"><span style={{ width: 8, height: 8, borderRadius: 2, background: "var(--ok)" }} />Entrada</span>
            <b className="mono" style={{ color: "var(--ok)" }}>+{DB.NUM(pts[hi].entrada)}</b>
          </div>
          <div className="row" style={{ justifyContent: "space-between", gap: 14, fontSize: 12.5, marginTop: 4 }}>
            <span className="row gap6"><span style={{ width: 8, height: 8, borderRadius: 2, background: "var(--crit)" }} />Saída</span>
            <b className="mono" style={{ color: "var(--crit)" }}>−{DB.NUM(pts[hi].saida)}</b>
          </div>
          <div className="row" style={{ justifyContent: "space-between", gap: 14, fontSize: 12, marginTop: 6, paddingTop: 6, borderTop: "1px solid var(--line)" }}>
            <span className="muted">Saldo</span>
            <b className="mono">{pts[hi].entrada - pts[hi].saida >= 0 ? "+" : ""}{DB.NUM(pts[hi].entrada - pts[hi].saida)}</b>
          </div>
        </div>
      )}
    </div>
  );
}

function Movimentacoes({ app }) {
  const [per, setPer] = useState("dia");

  // Parse das datas de cada movimento (formato "DD MMM" salvo pelo addMov)
  const parseDataMov = (s) => {
    if (!s) return null;
    if (/^\d{4}-\d{2}-\d{2}/.test(s)) return new Date(s + "T00:00:00");
    const m = /^(\d{1,2})\s*([a-zç]{3,})/i.exec(s);
    if (!m) return null;
    const ms = ["jan","fev","mar","abr","mai","jun","jul","ago","set","out","nov","dez"];
    const mn = ms.indexOf(m[2].toLowerCase().slice(0, 3));
    if (mn < 0) return null;
    const hoje = new Date();
    return new Date(hoje.getFullYear(), mn, +m[1]);
  };

  // Buckets de tempo conforme período selecionado
  const data = (() => {
    const hoje = new Date();
    const buckets = [];
    let mkLabel;
    if (per === "dia") {
      for (let i = 13; i >= 0; i--) {
        const d = new Date(hoje.getFullYear(), hoje.getMonth(), hoje.getDate() - i);
        buckets.push({ label: String(d.getDate()).padStart(2, "0"), date: d, entrada: 0, saida: 0 });
      }
      mkLabel = "últimos 14 dias";
    } else if (per === "semana") {
      for (let i = 7; i >= 0; i--) {
        const d = new Date(hoje.getFullYear(), hoje.getMonth(), hoje.getDate() - i * 7);
        buckets.push({ label: i === 0 ? "Atual" : "S-" + i, date: d, entrada: 0, saida: 0 });
      }
      mkLabel = "últimas 8 semanas";
    } else if (per === "mes") {
      for (let i = 11; i >= 0; i--) {
        const d = new Date(hoje.getFullYear(), hoje.getMonth() - i, 1);
        buckets.push({ label: d.toLocaleDateString("pt-BR", { month: "short" }).replace(".", ""), date: d, entrada: 0, saida: 0 });
      }
      mkLabel = "12 meses";
    } else {
      for (let i = 4; i >= 0; i--) {
        const d = new Date(hoje.getFullYear() - i, 0, 1);
        buckets.push({ label: String(d.getFullYear()), date: d, entrada: 0, saida: 0 });
      }
      mkLabel = "5 anos";
    }
    const bucketIdx = (d) => {
      if (per === "dia") {
        for (let i = 0; i < buckets.length; i++) {
          const b = buckets[i];
          if (d.getFullYear() === b.date.getFullYear() && d.getMonth() === b.date.getMonth() && d.getDate() === b.date.getDate()) return i;
        }
        return -1;
      }
      if (per === "semana") {
        const diff = Math.floor((hoje - d) / (1000 * 60 * 60 * 24 * 7));
        const idx = buckets.length - 1 - diff;
        return idx >= 0 && idx < buckets.length ? idx : -1;
      }
      if (per === "mes") {
        for (let i = 0; i < buckets.length; i++) {
          const b = buckets[i];
          if (d.getFullYear() === b.date.getFullYear() && d.getMonth() === b.date.getMonth()) return i;
        }
        return -1;
      }
      // ano
      for (let i = 0; i < buckets.length; i++) {
        if (d.getFullYear() === buckets[i].date.getFullYear()) return i;
      }
      return -1;
    };
    (app.movimentos || []).forEach((m) => {
      const d = parseDataMov(m.data);
      if (!d) return;
      const idx = bucketIdx(d);
      if (idx < 0) return;
      if (m.tipo === "entrada") buckets[idx].entrada += +m.qtd || 0;
      else if (m.tipo === "saida") buckets[idx].saida += +m.qtd || 0;
    });
    return { unitNote: `${mkLabel} · soma das quantidades`, min: 0, points: buckets };
  })();

  const totalEnt = data.points.reduce((s, p) => s + p.entrada, 0);
  const totalSai = data.points.reduce((s, p) => s + p.saida, 0);
  const liq = totalEnt - totalSai;
  const abaixoMin = app.estoque.filter((e) => e.status !== "ok").length;
  const un = "";

  const icoFor = (t) => t === "entrada" ? { ico: "arrowUp", tone: "ok", sign: "+" } : t === "saida" ? { ico: "arrowDown", tone: "crit", sign: "−" } : { ico: "list", tone: "muted", sign: "" };

  return (
    <div className="view-inner">
      <div className="page-head head-row">
        <div>
          <div className="crumb">Operação</div>
          <h1 className="page-title">Movimentações</h1>
          <p className="page-sub">Entradas, saídas e nível de estoque ao longo do tempo</p>
        </div>
        <div className="row gap8">
          <Btn icon="download" onClick={() => app.openModal("exportar", { entity: "movimentações" })}>Exportar</Btn>
          {(app.movimentos || []).length > 0 && (
            <Btn icon="trash" onClick={() => app.openModal("confirm", {
              title: "Limpar todas as movimentações?",
              danger: true,
              message: <>Isso remove o <b>histórico</b> das {(app.movimentos || []).length} movimentações registradas. <b>Não estorna saldos</b> — o estoque atual continua igual.</>,
              confirmLabel: "Limpar tudo",
              successMsg: "Histórico apagado",
              onConfirm: () => { app.movimentosApi.replaceAll([]); if (app.logEvento) app.logEvento("limpar_movimentacoes", null, { quantidade: (app.movimentos || []).length }); },
            })}>Limpar tudo</Btn>
          )}
          <Btn icon="arrowDown" variant="primary" onClick={() => app.setRoute("estoque")}>Dar baixa</Btn>
        </div>
      </div>

      <div className="metrics" style={{ gridTemplateColumns: "repeat(4, 1fr)", marginBottom: 18 }}>
        <MetricCard icon="arrowUp" label="Entradas no período" value={DB.NUM(totalEnt)} unit={un} state="ok" />
        <MetricCard icon="arrowDown" label="Saídas no período" value={DB.NUM(totalSai)} unit={un} />
        <MetricCard icon={liq >= 0 ? "trendUp" : "trendDown"} label="Saldo líquido" value={(liq >= 0 ? "+" : "−") + DB.NUM(Math.abs(liq))} unit={un} state={liq >= 0 ? "ok" : "warn"} />
        <MetricCard icon="alert" label="Abaixo do mínimo" value={abaixoMin} foot="itens" state="crit" onClick={() => app.setRoute("estoque")} />
      </div>

      <div className="card" style={{ marginBottom: 16 }}>
        <div className="card-head" style={{ flexWrap: "wrap", rowGap: 10 }}>
          <h3>Fluxo de estoque</h3>
          <span className="sub">{data.unitNote}</span>
          <span className="spacer" />
          <div className="row gap16" style={{ marginRight: 6 }}>
            <span className="row gap6 small"><span style={{ width: 12, height: 3, borderRadius: 2, background: "var(--ok)" }} />Entradas</span>
            <span className="row gap6 small"><span style={{ width: 12, height: 3, borderRadius: 2, background: "var(--crit)" }} />Saídas</span>
            <span className="row gap6 small"><span style={{ width: 12, height: 0, borderTop: "2px dashed var(--warn)" }} />Estoque mín.</span>
          </div>
          <div className="seg">
            {[["dia", "Dia"], ["semana", "Semana"], ["mes", "Mês"], ["ano", "Ano"]].map(([k, l]) => (
              <button key={k} className={per === k ? "on" : ""} onClick={() => setPer(k)}>{l}</button>
            ))}
          </div>
        </div>
        <div className="card-pad">
          <LineChart data={data} />
        </div>
      </div>

      <div className="card">
        <div className="card-head">
          <h3>Histórico de movimentações</h3>
          <span className="spacer" />
          <div className="input" style={{ width: 230, height: 32 }}><Icon name="search" size={15} /><input placeholder="Buscar item ou OP…" /></div>
          <Btn size="sm" icon="filter" onClick={() => app.openModal("filtros", { kind: "movimentacoes" })}>Filtrar</Btn>
        </div>
        <div className="tbl-wrap">
          <table className="tbl">
            <thead><tr><th>Tipo</th><th>Item</th><th>Motivo</th><th className="num">Qtd</th><th>Data</th><th></th></tr></thead>
            <tbody>
              {(app.movimentos || []).map((m) => {
                const f = icoFor(m.tipo);
                return (
                  <tr key={m._id} className="clickable">
                    <td>
                      <span className="row gap8" style={{ color: `var(--${f.tone === "muted" ? "muted" : f.tone})`, fontWeight: 600, fontSize: 12.5 }}>
                        <Icon name={f.ico} size={15} />{m.tipo === "entrada" ? "Entrada" : m.tipo === "saida" ? "Baixa" : "Inventário"}
                      </span>
                    </td>
                    <td><span className="sku">{m.sku}</span> <span className="strong">{m.item}</span></td>
                    <td className="muted">{m.motivo}</td>
                    <td className="num">{m.qtd > 0 ? <span className="mono strong" style={{ color: `var(--${f.tone})` }}>{f.sign}{DB.NUM(m.qtd)} {m.un}</span> : <span className="muted">—</span>}</td>
                    <td className="muted">{m.data} <span className="faint small">{m.hora}</span></td>
                    <td><IconBtn icon="x" title="Excluir do histórico" onClick={() => app.movimentosApi.remove(m._id)} /></td>
                  </tr>
                );
              })}
              {(!app.movimentos || app.movimentos.length === 0) && (
                <tr><td colSpan="6"><div className="muted small" style={{ padding: "18px 4px" }}>Nenhuma movimentação registrada ainda. Receba uma compra ou finalize uma OP para começar.</div></td></tr>
              )}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

window.MOVIMENTOS = MOVIMENTOS;
Object.assign(window, { Movimentacoes });
