/* ============================================================
   PCP — Screens part 2: PCP, Financeiro, secondary screens
   ============================================================ */

// ---------------------------------------------------------------
// PCP — Ordens de Produção
// ---------------------------------------------------------------
const OP_STATUS = {
  planejado: { label: "Planejado", tone: undefined },
  producao: { label: "Em produção", tone: "accent" },
  finalizado: { label: "Finalizado", tone: "ok" },
};

function PCP({ app }) {
  const [tab, setTab] = useState("ordens");
  return (
    <div className="view-inner">
      <div className="page-head head-row">
        <div>
          <div className="crumb">Operação</div>
          <h1 className="page-title">PCP · Ordens de Produção</h1>
          <p className="page-sub">{app.counts.opsAbertas} OPs abertas · {app.ops.filter((o) => o.status === "producao").length} em produção · {app.ops.filter((o) => o.atrasada).length} atrasada{app.ops.filter((o) => o.atrasada).length === 1 ? "" : "s"}</p>
        </div>
        <div className="spacer" />
        <div className="row gap8">
          <Btn icon="layers" onClick={() => app.openModal("novaOP")}>Gerar OPs em lote</Btn>
          <Btn icon="plus" variant="primary" onClick={() => app.openModal("novaOP")}>Nova OP</Btn>
        </div>
      </div>

      <div className="toolbar" style={{ marginBottom: 16 }}>
        <div className="seg">
          {[["ordens", "Ordens", "clipboard"], ["programas", "Programas", "layers"], ["prog", "Programação", "gantt"], ["sug", "A produzir & comprar", "cart"]].map(([k, l, ic]) => (
            <button key={k} className={tab === k ? "on" : ""} onClick={() => setTab(k)}><Icon name={ic} size={14} />{l}</button>
          ))}
        </div>
        <span className="spacer" />
        {tab === "ordens" && <Btn icon="printer" size="sm" onClick={() => { app.toast("Gerando relatório de OPs…", "info"); const d = PCPExport.data("pedidos", app); PCPExport.printTable("Ordens de Produção", [{ key: "op", label: "OP" }, { key: "produto", label: "Produto" }, { key: "pedido", label: "Pedido" }, { label: "Prog.", num: true, map: (o) => o.prod + "/" + o.planej }, { key: "etapa", label: "Etapa" }, { key: "prio", label: "Prio", num: true }, { label: "Status", map: (o) => OP_STATUS[o.status].label }], app.ops, [["OPs abertas", app.counts.opsAbertas]]); }}>Imprimir</Btn>}
      </div>

      {tab === "ordens" && <PcpOrdens app={app} />}
      {tab === "programas" && <PcpProgramas app={app} />}
      {tab === "prog" && <PcpProgramacao app={app} />}
      {tab === "sug" && <PcpSugestoes app={app} />}
    </div>
  );
}

function PcpProgramas({ app }) {
  const [novoNome, setNovoNome] = useState("");
  const [expandido, setExpandido] = useState(null);
  const [pickerFor, setPickerFor] = useState(null); // programaId

  const addPrograma = () => {
    const nome = novoNome.trim();
    if (!nome) return;
    if ((app.programas || []).some((p) => p.nome.toLowerCase() === nome.toLowerCase())) {
      app.toast("Já existe um programa com esse nome", "warn"); return;
    }
    app.programasApi.add({ nome, opIds: [] }, true);
    setNovoNome("");
    app.toast(`Programa "${nome}" criado`, "ok");
  };
  const removePrograma = (prog) => app.openModal("confirm", {
    title: `Excluir "${prog.nome}"?`,
    message: <>O programa será removido. As OPs continuam existindo.</>,
    successMsg: `"${prog.nome}" excluído`,
    onConfirm: () => app.programasApi.remove(prog._id),
  });
  const removeOPdoPrograma = (prog, opId) => {
    app.programasApi.update(prog._id, { opIds: (prog.opIds || []).filter((x) => x !== opId) });
  };
  const addOPsAoPrograma = (prog, opIds) => {
    const next = Array.from(new Set([...(prog.opIds || []), ...opIds]));
    app.programasApi.update(prog._id, { opIds: next });
    setPickerFor(null);
    app.toast(`${opIds.length} OP${opIds.length === 1 ? "" : "s"} adicionada${opIds.length === 1 ? "" : "s"}`, "ok");
  };

  // OPs ainda não atribuídas a NENHUM programa
  const opsLivres = (app.ops || []).filter((o) => {
    if (o.status === "finalizado" || o.status === "cancelado") return false;
    return !(app.programas || []).some((p) => (p.opIds || []).includes(o._id));
  });

  return (
    <div className="col gap16">
      <div className="card card-pad">
        <div className="small muted" style={{ marginBottom: 10 }}>
          Programas agrupam OPs por lote/cliente/turno. Crie um programa e adicione as OPs que devem rodar juntas. O progresso mostra a média ponderada de cada etapa entre as OPs do programa.
        </div>
        <div className="row gap8">
          <div className="input grow" style={{ height: 34 }}>
            <Icon name="layers" size={15} />
            <input value={novoNome} onChange={(e) => setNovoNome(e.target.value)} placeholder="Nome do programa (ex.: PE35, Lote semana 26)" onKeyDown={(e) => e.key === "Enter" && addPrograma()} />
          </div>
          <Btn variant="primary" icon="plus" onClick={addPrograma} disabled={!novoNome.trim()}>Novo programa</Btn>
        </div>
      </div>

      {(app.programas || []).length === 0 ? (
        <div className="card" style={{ padding: "30px 0" }}>
          <Empty icon="layers" title="Nenhum programa cadastrado">Crie um programa acima e arraste OPs pra ele.</Empty>
        </div>
      ) : (app.programas || []).map((prog) => {
        const aberto = expandido === prog._id;
        const prog_op_ids = prog.opIds || [];
        const opsDoPrograma = prog_op_ids.map((id) => app.ops.find((o) => o._id === id)).filter(Boolean);
        const progresso = app.progressoPrograma(prog);
        return (
          <div key={prog._id} className="card">
            <div className="card-head" style={{ flexWrap: "wrap", rowGap: 8 }}>
              <span className="m-ico" style={{ width: 32, height: 32, borderRadius: 8, background: "var(--accent-tint)", color: "var(--accent)", display: "grid", placeItems: "center", flex: "none" }}>
                <Icon name="layers" size={16} />
              </span>
              <div>
                <div className="strong" style={{ fontSize: 14 }}>{prog.nome}</div>
                <div className="small muted">{opsDoPrograma.length} OP{opsDoPrograma.length === 1 ? "" : "s"} · {progresso.totalProd}/{progresso.totalPlanej} un</div>
              </div>
              <span className="spacer" />
              <Btn size="sm" icon="plus" onClick={() => setPickerFor(pickerFor === prog._id ? null : prog._id)}>Adicionar OP</Btn>
              <Btn size="sm" icon={aberto ? "chevronUp" : "chevronDown"} onClick={() => setExpandido(aberto ? null : prog._id)}>{aberto ? "Fechar" : "Detalhes"}</Btn>
              <IconBtn icon="trash" title="Excluir programa" onClick={() => removePrograma(prog)} />
            </div>

            {progresso.etapas.length > 0 && (
              <div className="card-pad" style={{ borderTop: "1px solid var(--line)" }}>
                <div className="col gap8">
                  {progresso.etapas.map((e) => (
                    <div key={e.nome}>
                      <div className="row" style={{ justifyContent: "space-between", marginBottom: 4 }}>
                        <span className="small">{e.nome}</span>
                        <span className="small mono strong">{e.pct}%</span>
                      </div>
                      <Bar value={e.pct} tone={e.pct === 100 ? "ok" : undefined} />
                    </div>
                  ))}
                </div>
              </div>
            )}

            {pickerFor === prog._id && (
              <PickerOPs app={app} opsLivres={opsLivres} onCancel={() => setPickerFor(null)} onAdd={(ids) => addOPsAoPrograma(prog, ids)} />
            )}

            {aberto && (
              <div style={{ borderTop: "1px solid var(--line)" }}>
                {opsDoPrograma.length === 0 ? (
                  <div className="card-pad"><div className="small muted">Sem OPs no programa ainda. Use "Adicionar OP" acima.</div></div>
                ) : (
                  <div className="tbl-wrap">
                    <table className="tbl">
                      <thead><tr><th>OP</th><th>Produto</th><th className="num">Prog.</th><th>Etapa atual</th><th>Status</th><th></th></tr></thead>
                      <tbody>
                        {opsDoPrograma.map((o) => (
                          <tr key={o._id} className="clickable" onClick={() => app.openModal("opDetail", { op: o })}>
                            <td><span className="mono strong">{o.op}</span></td>
                            <td>{o.produto}</td>
                            <td className="num">{o.prod}/{o.planej}</td>
                            <td className="muted">{o.etapa}</td>
                            <td><Badge tone={OP_STATUS[o.status].tone} dotted>{OP_STATUS[o.status].label}</Badge></td>
                            <td onClick={(e) => e.stopPropagation()}>
                              <IconBtn icon="x" title="Remover do programa" onClick={() => removeOPdoPrograma(prog, o._id)} />
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                )}
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
}

function PickerOPs({ app, opsLivres, onCancel, onAdd }) {
  const [sel, setSel] = useState({});
  const ids = Object.keys(sel).filter((id) => sel[id]);
  const toggle = (id) => setSel((s) => ({ ...s, [id]: !s[id] }));
  return (
    <div className="card-pad" style={{ borderTop: "1px solid var(--line)", background: "var(--bg)" }}>
      <div className="row" style={{ marginBottom: 8 }}>
        <span className="strong" style={{ fontSize: 13 }}>OPs disponíveis</span>
        <span className="small muted" style={{ marginLeft: 8 }}>{opsLivres.length} sem programa</span>
        <span className="spacer" />
        <Btn size="sm" onClick={onCancel}>Cancelar</Btn>
        <Btn size="sm" variant="primary" icon="check" disabled={ids.length === 0} onClick={() => onAdd(ids)}>Adicionar {ids.length || ""}</Btn>
      </div>
      {opsLivres.length === 0 ? (
        <div className="small muted" style={{ padding: "8px 0" }}>Nenhuma OP disponível (todas estão em algum programa ou finalizadas).</div>
      ) : (
        <div className="lines">
          <div className="lrow lhead" style={{ gridTemplateColumns: "36px 100px 1fr 80px 1fr" }}>
            <div></div><div>OP</div><div>Produto</div><div className="right">Planej.</div><div>Etapa atual</div>
          </div>
          {opsLivres.map((o) => (
            <div key={o._id} className="lrow" style={{ gridTemplateColumns: "36px 100px 1fr 80px 1fr", padding: "8px 0" }}>
              <div style={{ display: "grid", placeItems: "center" }}>
                <input type="checkbox" checked={!!sel[o._id]} onChange={() => toggle(o._id)} />
              </div>
              <div style={{ padding: "0 12px", alignSelf: "center" }}><span className="mono strong">{o.op}</span></div>
              <div style={{ padding: "0 12px", alignSelf: "center", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{o.produto}</div>
              <div className="right mono" style={{ padding: "0 12px", alignSelf: "center" }}>{o.planej}</div>
              <div className="muted small" style={{ padding: "0 12px", alignSelf: "center" }}>{o.etapa}</div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function PcpOrdens({ app }) {
  return (
    <div className="card tbl-wrap">
      <table className="tbl">
        <thead>
          <tr>
            <th>OP</th><th>Produto</th><th>Pedido</th><th className="num">Prog.</th>
            <th style={{ width: 150 }}>Progresso</th><th>Etapa atual</th><th>Prio.</th><th>Status</th><th></th>
          </tr>
        </thead>
        <tbody>
          {app.ops.map((o) => {
            const pct = Math.round((o.prod / o.planej) * 100);
            return (
              <tr key={o._id} className={(o.atrasada ? "row-warn " : "") + "clickable"} onClick={() => app.openModal("opDetail", { op: o })}>
                <td><span className="mono strong">{o.op}</span></td>
                <td className="strong" style={{ maxWidth: 220, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{o.produto}</td>
                <td className="mono muted">{Array.isArray(o.itens) && o.itens.length > 1 ? `${o.itens.length} pedidos` : (o.pedido || (Array.isArray(o.itens) && o.itens[0] ? o.itens[0].os : "—"))}</td>
                <td className="num">{o.prod}/{o.planej}</td>
                <td>
                  <div className="row gap8">
                    <Bar value={pct} tone={o.status === "finalizado" ? "ok" : o.atrasada ? "warn" : undefined} style={{ flex: 1 }} />
                    <span className="small muted mono" style={{ width: 30 }}>{pct}%</span>
                  </div>
                </td>
                <td>{o.atrasada ? <Badge tone="warn" dotted>{o.etapa}</Badge> : <span className="muted">{o.etapa}</span>}</td>
                <td><span className="prio" style={{ color: o.prio >= 7 ? "var(--crit)" : "var(--muted)" }}><Icon name="zap" size={12} />{o.prio}</span></td>
                <td><Badge tone={OP_STATUS[o.status].tone} dotted>{OP_STATUS[o.status].label}</Badge></td>
                <td onClick={(e) => e.stopPropagation()}>
                  <RowMenu items={[
                    { icon: "eye", label: "Abrir OP", onClick: () => app.openModal("opDetail", { op: o }) },
                    { icon: "box", label: "Registrar consumo", onClick: () => app.openModal("opDetail", { op: o }) },
                    { icon: "printer", label: "Imprimir OP", onClick: () => PCPExport.printOP(o, app) },
                    o.status !== "finalizado" ? { icon: "check", label: "Marcar finalizada", onClick: () => app.finalizarOP(o._id) } : { icon: "refresh", label: "Reabrir OP", onClick: () => app.opsApi.update(o._id, { status: "producao", etapa: "Montagem" }) },
                    { sep: true },
                    { icon: "x", label: "Cancelar OP", onClick: () => app.openModal("confirm", { title: "Cancelar " + o.op + "?", message: <>A OP será marcada como cancelada.{o.prod > 0 ? <> As <b>{o.prod} un</b> já consumidas permanecem baixadas do estoque.</> : ""}</>, confirmLabel: "Cancelar OP", successMsg: o.op + " cancelada", onConfirm: () => app.cancelarOP(o._id) }) },
                    { icon: "trash", label: "Excluir OP", danger: true, onClick: () => app.openModal("confirm", { title: "Excluir " + o.op + "?", message: <>A ordem de <b>{o.produto}</b> será removida do sistema. Considere "Cancelar OP" pra manter o histórico.</>, successMsg: o.op + " excluída", onConfirm: () => app.opsApi.remove(o._id) }) },
                  ]} />
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

const RES_META = { "Corte CNC": "1 operador", "Solda 1": "2 operadores", "Solda 2": "1 operador", "Pintura": "cabine 1", "Montagem": "bancada" };
const RES_ORDER = ["Corte CNC", "Solda 1", "Solda 2", "Pintura", "Montagem"];
const UNASSIGNED = "Não alocado";

function PcpProgramacao({ app }) {
  // semana corrente: seg–sex (5 dias) a partir da próxima segunda (ou de hoje se hoje é seg)
  const days = (() => {
    const hoje = new Date();
    const dow = hoje.getDay(); // 0 = dom ... 6 = sab
    const offsetSeg = dow === 0 ? 1 : (dow > 5 ? (8 - dow) : (1 - dow));
    const seg = new Date(hoje.getFullYear(), hoje.getMonth(), hoje.getDate() + offsetSeg);
    const wd = ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab"];
    const arr = [];
    for (let i = 0; i < 5; i++) {
      const d = new Date(seg.getFullYear(), seg.getMonth(), seg.getDate() + i);
      arr.push({ label: `${wd[d.getDay()]} ${String(d.getDate()).padStart(2, "0")}`, date: d });
    }
    return arr;
  })();
  const ndays = days.length;
  const periodoSub = `por recurso · ${days[0].date.getDate()}–${days[ndays - 1].date.getDate()} ${days[0].date.toLocaleDateString("pt-BR", { month: "short" }).replace(".", "")}`;
  const colW = `repeat(${ndays}, 1fr)`;
  const toneFor = (o) => o.atrasada ? "crit" : o.status === "finalizado" ? "ok" : o.status === "producao" ? "accent" : "warn";

  // monta as barras a partir das OPs AO VIVO; OPs sem recurso vão p/ "Não alocado"
  const { resources, barsByRes } = useMemo(() => {
    const byRes = {};
    app.ops.forEach((o) => {
      const res = o.recurso && o.recurso !== "—" ? o.recurso : UNASSIGNED;
      const s = Math.max(0, Math.min(ndays - 1, o.inicio || 0));
      const l = Math.max(1, Math.min(ndays - s, o.dur || 1));
      (byRes[res] = byRes[res] || []).push({ s, l, tone: toneFor(o), op: o,
        t: o.op + " · " + o.produto.split(" ")[0], pct: Math.round((o.prod / Math.max(o.planej, 1)) * 100) });
    });
    const res = Object.keys(byRes).sort((a, b) => {
      if (a === UNASSIGNED) return 1; if (b === UNASSIGNED) return -1;
      const ia = RES_ORDER.indexOf(a), ib = RES_ORDER.indexOf(b);
      return (ia < 0 ? 99 : ia) - (ib < 0 ? 99 : ib);
    });
    return { resources: res, barsByRes: byRes };
  }, [app.ops]);

  return (
    <div className="card">
      <div className="card-head">
        <Icon name="gantt" size={15} />
        <h3>Programação da semana</h3>
        <span className="sub">{periodoSub}</span>
        <span className="spacer" />
        <div className="row gap12 small muted">
          <span className="row gap6"><span style={{ width: 9, height: 9, borderRadius: 3, background: "var(--accent)" }} />Em produção</span>
          <span className="row gap6"><span style={{ width: 9, height: 9, borderRadius: 3, background: "var(--warn)" }} />Planejada</span>
          <span className="row gap6"><span style={{ width: 9, height: 9, borderRadius: 3, background: "var(--crit)" }} />Atrasada</span>
        </div>
      </div>
      {resources.length === 0 ? (
        <Empty icon="gantt" title="Nenhuma OP programada">Crie uma ordem de produção para vê-la na agenda da semana.</Empty>
      ) : (
      <div className="gantt">
        <div className="gantt-grid">
          <div className="gantt-row head">
            <div className="gantt-res"><span className="r-sub">Recurso</span></div>
            <div className="gantt-days" style={{ gridTemplateColumns: colW }}>
              {days.map((d) => <div key={d.label}>{d.label}</div>)}
            </div>
          </div>
          {resources.map((r) => (
            <div key={r} className="gantt-row">
              <div className="gantt-res">
                <div className="r-name">{r}</div>
                <div className="r-sub">{RES_META[r] || (r === UNASSIGNED ? "aguardando recurso" : (barsByRes[r].length + " OP" + (barsByRes[r].length > 1 ? "s" : "")))}</div>
              </div>
              <div className="gantt-track">
                <div className="gantt-cols" style={{ gridTemplateColumns: colW }}>
                  {days.map((d) => <div key={d.label} />)}
                </div>
                {(barsByRes[r] || []).map((b, i) => (
                  <div key={i} className={"gbar b-" + b.tone}
                    style={{ left: `calc(${b.s / ndays * 100}% + 4px)`, width: `calc(${b.l / ndays * 100}% - 8px)` }}
                    title={b.op.op + " — " + b.op.produto + " · " + b.op.etapa + " · " + b.pct + "%"}
                    onClick={() => app.openModal("opDetail", { op: b.op })}>
                    {b.t}
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
      </div>
      )}
    </div>
  );
}

function PcpSugestoes({ app }) {
  // Calcula demanda por produto a partir de pedidos abertos/andamento
  const sugestoes = (() => {
    const map = {};
    (app.pedidos || []).filter((p) => p.status === "aberto" || p.status === "andamento").forEach((ped) => {
      const itens = app.normItens ? app.normItens(ped) : (ped.itens || []);
      itens.forEach((it) => {
        if (it.tipo !== "produto") return;
        const prod = (app.produtos || []).find((x) => x.nome === it.nome);
        if (!prod) return;
        if (!map[prod.sku]) map[prod.sku] = { sku: prod.sku, nome: prod.nome, demanda: 0 };
        map[prod.sku].demanda += +it.qtd || 0;
      });
    });
    // OPs em produção/planejado que cobrem essa demanda
    return Object.values(map).map((r) => {
      const cobertoOps = (app.ops || []).filter((o) => o.produto === r.nome && o.status !== "finalizado" && o.status !== "cancelado").reduce((s, o) => s + (+o.planej - +o.prod || 0), 0);
      const faltam = Math.max(0, r.demanda - cobertoOps);
      return { ...r, coberto: cobertoOps, faltam };
    }).filter((r) => r.faltam > 0);
  })();
  return (
    <div className="grid2" style={{ alignItems: "start" }}>
      <div className="card">
        <div className="card-head"><Icon name="package" size={15} /><h3>Produtos a produzir</h3><span className="spacer" /><span className="small muted">demanda dos pedidos abertos</span></div>
        <div className="tbl-wrap">
          <table className="tbl">
            <thead><tr><th>Produto</th><th className="num">Demanda</th><th className="num">Em OP</th><th className="num">Faltam</th><th></th></tr></thead>
            <tbody>
              {sugestoes.length === 0 ? (
                <tr><td colSpan="5"><div className="muted small" style={{ padding: "16px 4px" }}>Sem demanda pendente — todas as linhas de pedido já estão cobertas por OPs.</div></td></tr>
              ) : sugestoes.map((p) => (
                <tr key={p.sku}>
                  <td><span className="sku">{p.sku}</span> <span className="strong">{p.nome}</span></td>
                  <td className="num">{p.demanda}</td>
                  <td className="num muted">{p.coberto}</td>
                  <td className="num"><Badge tone="warn">{p.faltam}</Badge></td>
                  <td onClick={(e) => e.stopPropagation()}><Btn size="sm" icon="plus" onClick={() => app.openModal("novaOP", { fromPedido: { produto: p.nome, qtd: p.faltam, prio: 6 } })}>OP</Btn></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      <div className="card">
        <div className="card-head"><Icon name="cart" size={15} /><h3>Compras sugeridas</h3><span className="spacer" /><span className="badge accent">{app.counts.comprasSug} novas</span></div>
        <div className="tbl-wrap">
          <table className="tbl">
            <thead><tr><th>Insumo</th><th className="num">Qtd</th><th className="num">Valor</th><th>Status</th><th></th></tr></thead>
            <tbody>
              {app.compras.map((c) => (
                <tr key={c._id}>
                  <td>
                    <div><span className="sku">{c.sku}</span> <span className="strong">{c.item}</span></div>
                    <div className="small muted">{c.motivo}</div>
                  </td>
                  <td className="num">{c.qtd} <span className="muted small">{c.un}</span></td>
                  <td className="num strong">{DB.BRL(c.valor)}</td>
                  <td><Badge tone={c.status === "solicitada" ? "info" : undefined} dotted>{c.status === "solicitada" ? "Solicitada" : "Sugerida"}</Badge></td>
                  <td onClick={(e) => e.stopPropagation()}>{c.status === "sugerida" && <Btn size="sm" onClick={() => { app.comprasApi.update(c._id, { status: "solicitada" }); app.toast("Compra solicitada", "ok"); }}>Solicitar</Btn>}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------
// FINANCEIRO
// ---------------------------------------------------------------
function Financeiro({ app }) {
  const [tab, setTab] = useState("fluxo");
  const [tipo, setTipo] = useState("todos");
  const [canal, setCanal] = useState("todos");
  const L = app.lancamentos;
  const CANAL_META = {
    loja: { label: "Loja", icon: "building" },
    mercado_livre: { label: "Mercado Livre", icon: "tag" },
    shopee: { label: "Shopee", icon: "cart" },
  };
  const byCanal = canal === "todos" ? L : L.filter((l) => l.canal === canal);
  const entradas = byCanal.filter((l) => l.tipo === "entrada" && l.status === "pago").reduce((s, l) => s + l.valor, 0);
  const saidas = byCanal.filter((l) => l.tipo === "saida" && l.status === "pago").reduce((s, l) => s + l.valor, 0);
  const aReceber = byCanal.filter((l) => l.tipo === "entrada" && l.status === "pendente").reduce((s, l) => s + l.valor, 0);
  const aPagar = byCanal.filter((l) => l.tipo === "saida" && l.status === "pendente").reduce((s, l) => s + l.valor, 0);
  const rows = byCanal.filter((l) => tipo === "todos" || l.tipo === tipo);
  const fmt = (n) => DB.BRL(n).replace("R$\u00a0", "R$ ");
  const canalNome = canal === "todos" ? "todos os canais" : CANAL_META[canal].label;

  return (
    <div className="view-inner">
      <div className="page-head head-row">
        <div>
          <div className="crumb">Gestão</div>
          <h1 className="page-title">Financeiro</h1>
          <p className="page-sub">Fluxo de caixa e resultado · {new Date().toLocaleDateString("pt-BR", { month: "long", year: "numeric" })} · {canalNome}</p>
        </div>
        <div className="spacer" />
        <div className="row gap8">
          <Btn icon="download" onClick={() => app.openModal("exportar", { entity: "financeiro" })}>Exportar</Btn>
          {(() => {
            const importados = app.lancamentos.filter((l) => l.origem === "marketplace_import" || l.origem === "compra");
            return importados.length > 0 ? (
              <Btn icon="trash" onClick={() => app.openModal("confirm", {
                title: "Limpar lançamentos importados?",
                danger: true,
                message: <>Remove os <b>{importados.length} lançamentos</b> criados por importação (marketplace) ou recebimento de compra. Lançamentos manuais e os de pedidos concluídos ficam intactos.</>,
                confirmLabel: "Limpar importados",
                successMsg: importados.length + " lançamentos removidos",
                onConfirm: () => {
                  const ids = new Set(importados.map((l) => l._id));
                  app.lancamentosApi.replaceAll(app.lancamentos.filter((l) => !ids.has(l._id)));
                  if (app.logEvento) app.logEvento("limpar_lancamentos_importados", null, { quantidade: importados.length });
                },
              })}>Limpar importados</Btn>
            ) : null;
          })()}
          {app.lancamentos.length > 0 && (
            <Btn icon="trash" onClick={() => app.openModal("confirm", {
              title: "Limpar todos os lançamentos?",
              danger: true,
              message: <>Remove <b>todos os {app.lancamentos.length} lançamentos</b> do financeiro. Isso não estorna pedidos nem compras já registrados — só apaga o histórico de caixa.</>,
              confirmLabel: "Limpar tudo",
              successMsg: "Financeiro zerado",
              onConfirm: () => {
                const total = app.lancamentos.length;
                app.lancamentosApi.replaceAll([]);
                if (app.logEvento) app.logEvento("limpar_lancamentos", null, { quantidade: total });
              },
            })}>Limpar tudo</Btn>
          )}
          <Btn icon="plus" variant="primary" onClick={() => app.openModal("lancamento")}>Lançamento</Btn>
        </div>
      </div>

      <div className="metrics" style={{ gridTemplateColumns: "repeat(4, 1fr)", marginBottom: 18 }}>
        <MetricCard icon="trendUp" label="Entradas (pago)" value={fmt(entradas)} state="ok" />
        <MetricCard icon="trendDown" label="Saídas (pago)" value={fmt(saidas)} />
        <MetricCard icon="clock" label="A receber" value={fmt(aReceber)} foot="pendente" />
        <MetricCard icon="alert" label="A pagar (7 dias)" value={fmt(aPagar)} state="warn" />
      </div>

      <div className="toolbar" style={{ marginBottom: 14 }}>
        <div className="seg">
          <button className={tab === "fluxo" ? "on" : ""} onClick={() => setTab("fluxo")}><Icon name="list" size={14} />Fluxo de caixa</button>
          <button className={tab === "dre" ? "on" : ""} onClick={() => setTab("dre")}><Icon name="chart" size={14} />DRE</button>
        </div>
        <span className="spacer" />
        {tab === "fluxo" && (
          <div className="seg">
            {[["todos", "Tudo"], ["entrada", "Entradas"], ["saida", "Saídas"]].map(([k, l]) => (
              <button key={k} className={tipo === k ? "on" : ""} onClick={() => setTipo(k)}>{l}</button>
            ))}
          </div>
        )}
        {tab === "fluxo" && (
          <div className="seg">
            {[["todos", "Todos os canais"], ["loja", "Loja"], ["mercado_livre", "Mercado Livre"], ["shopee", "Shopee"]].map(([k, l]) => (
              <button key={k} className={canal === k ? "on" : ""} onClick={() => setCanal(k)}>{l}</button>
            ))}
          </div>
        )}
      </div>

      {tab === "fluxo" ? (
        <div className="card tbl-wrap">
          <table className="tbl">
            <thead><tr><th>Data</th><th>Descrição</th><th>Categoria</th><th>Canal</th><th>Origem</th><th className="num">Valor</th><th>Status</th><th></th></tr></thead>
            <tbody>
              {rows.map((l) => {
                const cm = CANAL_META[l.canal];
                return (
                <tr key={l._id} className="clickable">
                  <td className="mono muted">{l.data}</td>
                  <td className="strong" style={{ maxWidth: 320 }}>{l.desc}</td>
                  <td><Badge>{l.cat}</Badge></td>
                  <td>{cm ? <span className="mkt-chip" style={{ margin: 0 }}><Icon name={cm.icon} size={12} />{cm.label}</span> : <span className="muted small">—</span>}</td>
                  <td className="muted small">{l.origem === "manual" ? "Manual" : l.origem === "pedido" ? "Pedido" : l.origem === "marketplace" ? "Marketplace" : "Compra"}</td>
                  <td className="num strong" style={{ color: l.tipo === "entrada" ? "var(--ok)" : "var(--ink)" }}>
                    {l.tipo === "entrada" ? "+" : "−"} {DB.BRL(l.valor)}
                  </td>
                  <td><Badge tone={l.status === "pago" ? "ok" : "warn"} dotted>{l.status === "pago" ? "Pago" : "Pendente · " + (l.venc || "")}</Badge></td>
                  <td onClick={(e) => e.stopPropagation()}>
                    {l.origem === "manual" ? (
                      <RowMenu items={[
                        { icon: "edit", label: "Editar", onClick: () => app.openModal("lancamento", { edit: l }) },
                        { icon: l.status === "pago" ? "clock" : "check", label: l.status === "pago" ? "Marcar pendente" : "Marcar pago", onClick: () => { app.lancamentosApi.update(l._id, { status: l.status === "pago" ? "pendente" : "pago" }); app.toast("Status atualizado", "ok"); } },
                        { sep: true },
                        { icon: "trash", label: "Excluir", danger: true, onClick: () => app.openModal("confirm", { title: "Excluir lançamento?", message: <><b>{l.desc}</b> será removido do fluxo de caixa.</>, successMsg: "Lançamento excluído", onConfirm: () => app.lancamentosApi.remove(l._id) }) },
                      ]} />
                    ) : <span title="Lançamento automático — vinculado" style={{ display: "inline-flex" }}><Icon name="link" size={14} style={{ color: "var(--faint)" }} /></span>}
                  </td>
                </tr>
              ); })}
            </tbody>
          </table>
        </div>
      ) : <DRE app={app} fmt={fmt} />}
    </div>
  );
}

function DRE({ app, fmt }) {
  // Calcula DRE a partir dos lançamentos PAGOS (status="pago") do mês atual
  const hoje = new Date();
  const inicioMes = new Date(hoje.getFullYear(), hoje.getMonth(), 1);
  const fimMes = new Date(hoje.getFullYear(), hoje.getMonth() + 1, 0);
  const parseDataBR = (s) => {
    if (!s) return null;
    if (/^\d{4}-\d{2}-\d{2}/.test(s)) return new Date(s + "T00:00:00");
    // formato "DD MMM"
    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;
    return new Date(hoje.getFullYear(), mn, +m[1]);
  };
  const noMes = (l) => { const dt = parseDataBR(l.data); return dt && dt >= inicioMes && dt <= fimMes; };
  const pago = app.lancamentos.filter((l) => l.status === "pago" && noMes(l));
  const receita = pago.filter((l) => l.tipo === "entrada").reduce((s, l) => s + (+l.valor || 0), 0);
  const cmv = pago.filter((l) => l.tipo === "saida" && l.cat === "Matéria-prima").reduce((s, l) => s + (+l.valor || 0), 0);
  const despFixa = pago.filter((l) => l.tipo === "saida" && l.cat === "Despesa fixa").reduce((s, l) => s + (+l.valor || 0), 0);
  const pessoal = pago.filter((l) => l.tipo === "saida" && l.cat === "Pessoal").reduce((s, l) => s + (+l.valor || 0), 0);
  const outras = pago.filter((l) => l.tipo === "saida" && !["Matéria-prima","Despesa fixa","Pessoal"].includes(l.cat)).reduce((s, l) => s + (+l.valor || 0), 0);
  const lucroBruto = receita - cmv;
  const resultado = lucroBruto - despFixa - pessoal - outras;
  const margem = receita > 0 ? resultado / receita : 0;
  const d = { receita, cmv, despFixa, pessoal, outras, lucroBruto, resultado, margem };

  // série de receita por mês (últimos 6 meses) a partir dos lançamentos
  const fatSerie = (() => {
    const meses = [];
    for (let i = 5; i >= 0; i--) {
      const dt = new Date(hoje.getFullYear(), hoje.getMonth() - i, 1);
      meses.push({ m: dt.toLocaleDateString("pt-BR", { month: "short" }).replace(".", ""), y: dt.getFullYear(), mn: dt.getMonth(), v: 0 });
    }
    app.lancamentos.filter((l) => l.tipo === "entrada" && l.status === "pago").forEach((l) => {
      const dt = parseDataBR(l.data); if (!dt) return;
      const b = meses.find((x) => x.y === dt.getFullYear() && x.mn === dt.getMonth());
      if (b) b.v += (+l.valor || 0) / 1000;
    });
    return meses.map((m) => ({ m: m.m, v: Math.round(m.v) }));
  })();

  const lines = [
    { label: "Receita bruta", value: d.receita, tone: "ink", bold: true },
    { label: "(−) CMV — matéria-prima", value: -d.cmv, tone: "muted" },
    { label: "Lucro bruto", value: d.lucroBruto, tone: "ink", bold: true, rule: true },
    { label: "(−) Despesas fixas", value: -d.despFixa, tone: "muted" },
    { label: "(−) Pessoal", value: -d.pessoal, tone: "muted" },
    { label: "(−) Outras despesas", value: -d.outras, tone: "muted" },
    { label: "Resultado líquido", value: d.resultado, tone: "ok", bold: true, rule: true, big: true },
  ];
  const mesNome = hoje.toLocaleDateString("pt-BR", { month: "long" });
  return (
    <div className="grid2" style={{ gridTemplateColumns: "1.4fr 1fr", alignItems: "start" }}>
      <div className="card">
        <div className="card-head"><h3>Demonstração de resultado</h3><span className="sub">simplificado · {mesNome}</span></div>
        <div className="card-pad">
          {lines.map((l, i) => (
            <div key={i} style={{ borderTop: l.rule ? "1px solid var(--line)" : "none", marginTop: l.rule ? 8 : 0, paddingTop: l.rule ? 12 : 0 }}>
              <div className="row" style={{ justifyContent: "space-between", padding: "8px 0" }}>
                <span style={{ fontSize: l.big ? 15 : 13.5, fontWeight: l.bold ? 650 : 400, color: l.tone === "muted" ? "var(--muted)" : "var(--ink)" }}>{l.label}</span>
                <span className="mono" style={{ fontSize: l.big ? 17 : 13.5, fontWeight: l.bold ? 700 : 500,
                  color: l.tone === "ok" ? "var(--ok)" : l.value < 0 ? "var(--ink-soft)" : "var(--ink)" }}>
                  {l.value < 0 ? "−" : ""}{DB.BRL(Math.abs(l.value))}
                </span>
              </div>
            </div>
          ))}
        </div>
      </div>
      <div className="col gap16">
        <div className="card card-pad">
          <SectionLabel>Margem líquida</SectionLabel>
          <div style={{ fontSize: 40, fontWeight: 680, letterSpacing: "-0.03em", color: "var(--ok)" }}>{(d.margem * 100).toFixed(1)}%</div>
          <Bar value={d.margem * 100} tone="ok" style={{ marginTop: 12 }} />
          <p className="small muted mt12" style={{ margin: "12px 0 0" }}>Resultado líquido de {fmt(d.resultado)} sobre receita de {fmt(d.receita)}.</p>
        </div>
        <div className="card card-pad">
          <SectionLabel>Receita 6 meses</SectionLabel>
          <MiniBars data={fatSerie} height={92} accent="var(--ok)" />
        </div>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------
// Secondary screens (lightweight but real)
// ---------------------------------------------------------------
function Compras({ app }) {
  return (
    <div className="view-inner">
      <div className="page-head head-row">
        <div><div className="crumb">Operação</div><h1 className="page-title">Compras</h1><p className="page-sub">Insumos sugeridos e pedidos a fornecedores</p></div>
        <div className="spacer" />
        <div className="row gap8">
          {(() => {
            const sugeridas = app.compras.filter((c) => c.status === "sugerida");
            return sugeridas.length > 0 ? (
              <Btn icon="trash" onClick={() => app.openModal("confirm", {
                title: "Apagar todas as sugestões?",
                danger: true,
                message: <>Remove as <b>{sugeridas.length} compras sugeridas</b> automaticamente. As <b>solicitadas</b> ficam intactas. As sugestões podem voltar a aparecer enquanto houver itens abaixo do mínimo no estoque.</>,
                confirmLabel: "Apagar sugestões",
                successMsg: sugeridas.length + " sugestões removidas",
                onConfirm: () => {
                  const ids = new Set(sugeridas.map((c) => c._id));
                  app.comprasApi.replaceAll(app.compras.filter((c) => !ids.has(c._id)));
                  if (app.logEvento) app.logEvento("limpar_compras_sugeridas", null, { quantidade: sugeridas.length });
                },
              })}>Limpar sugestões</Btn>
            ) : null;
          })()}
          {app.compras.length > 0 && (
            <Btn icon="trash" onClick={() => app.openModal("confirm", {
              title: "Limpar todas as compras?",
              danger: true,
              message: <>Remove <b>todas as {app.compras.length} compras</b> (sugeridas + solicitadas). Compras já recebidas não estão aqui — elas viraram entrada no estoque.</>,
              confirmLabel: "Limpar tudo",
              successMsg: "Compras zeradas",
              onConfirm: () => {
                const total = app.compras.length;
                app.comprasApi.replaceAll([]);
                if (app.logEvento) app.logEvento("limpar_compras", null, { quantidade: total });
              },
            })}>Limpar tudo</Btn>
          )}
          <Btn icon="plus" variant="primary" onClick={() => app.openModal("novaCompra")}>Nova compra</Btn>
        </div>
      </div>
      <div className="metrics" style={{ gridTemplateColumns: "repeat(4,1fr)", marginBottom: 18 }}>
        <MetricCard icon="cart" label="Sugeridas" value={app.compras.filter((c) => c.status === "sugerida").length} state="warn" />
        <MetricCard icon="clock" label="Solicitadas" value={app.compras.filter((c) => c.status === "solicitada").length} />
        <MetricCard icon="truck" label="A receber" value={app.compras.filter((c) => c.status === "solicitada").length} />
        <MetricCard icon="dollar" label="Valor em aberto" value={DB.BRL(app.compras.reduce((s, c) => s + c.valor, 0)).replace("R$\u00a0", "R$ ")} />
      </div>
      <div className="card tbl-wrap">
        <table className="tbl">
          <thead><tr><th>Insumo</th><th>Fornecedor</th><th className="num">Qtd</th><th className="num">Valor</th><th>Motivo</th><th>Status</th><th></th></tr></thead>
          <tbody>
            {app.compras.map((c) => (
              <tr key={c._id} className="clickable">
                <td><span className="sku">{c.sku}</span> <span className="strong">{c.item}</span></td>
                <td>{c.forn}</td>
                <td className="num">{c.qtd} <span className="muted small">{c.un}</span></td>
                <td className="num strong">{DB.BRL(c.valor)}</td>
                <td className="muted small">{c.motivo}</td>
                <td><Badge tone={c.status === "solicitada" ? "info" : "warn"} dotted>{c.status === "solicitada" ? "Solicitada" : "Sugerida"}</Badge></td>
                <td onClick={(e) => e.stopPropagation()}>
                  <div className="row gap6" style={{ justifyContent: "flex-end" }}>
                    <Btn size="sm" icon={c.status === "solicitada" ? "truck" : "check"} onClick={() => c.status === "solicitada" ? app.openModal("receberCompra", { compra: c }) : (app.comprasApi.update(c._id, { status: "solicitada" }), app.toast("Compra solicitada", "ok"))}>{c.status === "solicitada" ? "Receber" : "Solicitar"}</Btn>
                    <RowMenu items={[
                      { icon: "truck", label: "Receber", onClick: () => app.openModal("receberCompra", { compra: c }) },
                      { icon: "check", label: "Marcar solicitada", onClick: () => { app.comprasApi.update(c._id, { status: "solicitada" }); app.toast("Compra solicitada", "ok"); } },
                      { sep: true },
                      { icon: "trash", label: "Cancelar", danger: true, onClick: () => app.openModal("confirm", { title: "Cancelar compra?", message: <>A compra de <b>{c.item}</b> será cancelada.</>, confirmLabel: "Cancelar compra", successMsg: "Compra cancelada", onConfirm: () => app.comprasApi.remove(c._id) }) },
                    ]} />
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function Produtos({ app }) {
  return (
    <div className="view-inner">
      <div className="page-head head-row">
        <div><div className="crumb">Cadastros</div><h1 className="page-title">Produtos</h1><p className="page-sub">{app.produtos.length} produtos acabados · com BOM e custo estimado</p></div>
        <div className="spacer" /><div className="row gap8"><Btn icon="download" onClick={() => app.openModal("exportar", { entity: "produtos" })}>Exportar</Btn><Btn icon="plus" variant="primary" onClick={() => app.openModal("novoProduto")}>Novo produto</Btn></div>
      </div>
      <div className="card tbl-wrap">
        <table className="tbl">
          <thead><tr><th>Produto</th><th>Modo</th><th className="num">Tempo</th><th className="num">Custo est.</th><th className="num">Preço</th><th className="num">Margem</th><th></th></tr></thead>
          <tbody>
            {app.produtos.map((p) => {
              const margem = (p.preco - p.custo) / p.preco;
              return (
                <tr key={p._id} className="clickable" onClick={() => app.openModal("produtoDetail", { produto: p })}>
                  <td>
                    <div className="row gap8" style={{ alignItems: "center" }}>
                      <span style={{ width: 36, height: 36, borderRadius: 8, overflow: "hidden", background: "var(--bg)", border: "1px solid var(--line)", display: "grid", placeItems: "center", flex: "none" }}>
                        {p.imgUrl ? <img src={p.imgUrl} alt="" style={{ width: "100%", height: "100%", objectFit: "cover" }} /> : <Icon name="package" size={16} className="muted" />}
                      </span>
                      <span className="sku">{p.sku}</span>
                      <span className="strong">{p.nome}</span>
                    </div>
                  </td>
                  <td><Badge tone={p.modo === "Para estoque" ? "info" : undefined}>{p.modo}</Badge></td>
                  <td className="num muted">{p.tempo}</td>
                  <td className="num">{DB.BRL(p.custo)}</td>
                  <td className="num strong">{DB.BRL(p.preco)}</td>
                  <td className="num"><span style={{ color: margem > 0.4 ? "var(--ok)" : "var(--warn)", fontWeight: 600 }}>{(margem * 100).toFixed(0)}%</span></td>
                  <td onClick={(e) => e.stopPropagation()}>
                    <RowMenu items={[
                      { icon: "eye", label: "Ver detalhes", onClick: () => app.openModal("produtoDetail", { produto: p }) },
                      { icon: "edit", label: "Editar produto", onClick: () => app.openModal("novoProduto", { edit: p }) },
                      { icon: "factory", label: "Criar OP", onClick: () => app.openModal("novaOP", { fromPedido: { produto: p.nome, qtd: 1, prio: 5 } }) },
                      { sep: true },
                      { icon: "trash", label: "Excluir", danger: true, onClick: () => app.openModal("confirm", { title: "Excluir " + p.sku + "?", message: <>O produto <b>{p.nome}</b> será removido.</>, successMsg: p.sku + " excluído", onConfirm: () => app.produtosApi.remove(p._id) }) },
                    ]} />
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function Placeholder({ route }) {
  const m = ROUTE_META[route] || {};
  return (
    <div className="view-inner">
      <div className="page-head"><div className="crumb">{m.crumb || "—"}</div><h1 className="page-title">{m.title || route}</h1><p className="page-sub">{m.sub || ""}</p></div>
      <div className="card" style={{ padding: "30px 0" }}>
        <Empty icon="layers" title="Tela não encontrada">A rota <b>{route}</b> não tem uma tela associada.</Empty>
      </div>
    </div>
  );
}

Object.assign(window, { PCP, Financeiro, Compras, Produtos, Placeholder });
