/* global React, Icon, UI, DATA */
const { useState: useEState } = React;

function ExecutionsList({ navigate }) {
  const { StatusBadge } = UI;
  const D = DATA;
  const [status, setStatus] = useEState("all");
  const [proj, setProj] = useEState("all");
  const [q, setQ] = useEState("");

  let list = D.executions.filter((e) =>
    (status === "all" || e.status === status) &&
    (proj === "all" || e.project === proj) &&
    (e.id.includes(q) || e.projectName.toLowerCase().includes(q.toLowerCase())));

  return (
    <div className="app-scroll"><div className="page fade-in">
      <UI.PageHeader title="Executions" subtitle="Every workflow run creates an immutable record with files, logs, outputs, and errors." />

      <div style={{ display: "flex", gap: 10, alignItems: "center", marginBottom: 18, flexWrap: "wrap" }}>
        <div style={{ position: "relative", flex: 1, minWidth: 200, maxWidth: 300 }}>
          <span style={{ position: "absolute", left: 12, top: "50%", transform: "translateY(-50%)" }}><Icon name="search" size={16} color="var(--ef-fg-4)" /></span>
          <input className="input" placeholder="Search by ID or project" value={q} onChange={(e) => setQ(e.target.value)} style={{ paddingLeft: 36 }} />
        </div>
        <select className="select" value={proj} onChange={(e) => setProj(e.target.value)} style={{ width: 200 }}>
          <option value="all">All projects</option>{D.projects.map((p) => <option key={p.id} value={p.id}>{p.name}</option>)}
        </select>
        <select className="select" value={status} onChange={(e) => setStatus(e.target.value)} style={{ width: 200 }}>
          <option value="all">All statuses</option>{["completed", "completed_with_warnings", "partially_completed", "failed", "waiting_for_human_review", "cancelled"].map((s) => <option key={s} value={s}>{UI.statusMeta(s).label}</option>)}
        </select>
        <div style={{ flex: 1 }} />
        <span className="muted" style={{ fontSize: 13 }}>{list.length} of {D.executions.length}</span>
      </div>

      <div className="card" style={{ overflow: "hidden" }}>
        <table className="tbl">
          <thead><tr><th>Execution</th><th>Project</th><th>Trigger</th><th>Status</th><th style={{ textAlign: "right" }}>Files</th><th style={{ textAlign: "right" }}>Outputs</th><th style={{ textAlign: "right" }}>Duration</th><th>Triggered by</th><th style={{ textAlign: "right" }}>Started</th><th></th></tr></thead>
          <tbody>
            {list.map((e) => (
              <tr key={e.id} className="tbl-row" onClick={() => navigate("execution", { id: e.id })}>
                <td className="mono" style={{ fontWeight: 600, color: "var(--ef-fg-1)", fontSize: 12.5 }}>{e.id}</td>
                <td style={{ maxWidth: 180, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{e.projectName}</td>
                <td className="muted" style={{ fontSize: 12.5 }}>{e.trigger.replace(/_/g, " ")}</td>
                <td><StatusBadge status={e.status} /></td>
                <td style={{ textAlign: "right" }} className="tabular">{e.files}{e.failed ? <span style={{ color: "var(--ef-danger)" }}> · {e.failed}✕</span> : ""}</td>
                <td style={{ textAlign: "right" }} className="tabular">{e.outputs}</td>
                <td style={{ textAlign: "right", fontSize: 12 }} className="muted mono">{e.duration}</td>
                <td className="muted" style={{ fontSize: 12.5 }}>{e.by}</td>
                <td style={{ textAlign: "right", fontSize: 12 }} className="muted mono">{D.fmtAgo(e.started)}</td>
                <td><Icon name="chevron-right" size={16} color="var(--ef-fg-4)" /></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div></div>
  );
}

function ExecutionDetail({ navigate, toast, params }) {
  const { StatusBadge, Button } = UI;
  const D = DATA;
  const e = D.executions.find((x) => x.id === params?.id) || D.executions[0];
  const [tab, setTab] = useEState("timeline");
  const isHero = e.id === "exec_8841";
  const steps = isHero ? D.heroSteps : synthSteps(e);

  // statuses for replay
  const statuses = {};
  if (isHero) D.heroNodes.forEach((n) => (statuses[n.id] = "completed"));
  else D.heroNodes.forEach((n, i) => {
    if (e.status === "failed") statuses[n.id] = i < 4 ? "completed" : i === 4 ? "failed" : "skipped";
    else if (e.status === "waiting_for_human_review") statuses[n.id] = i < 4 ? "completed" : i === 4 ? "waiting" : "skipped";
    else statuses[n.id] = "completed";
  });

  return (
    <div className="app-scroll"><div className="page fade-in">
      {/* header */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 20, marginBottom: 20, flexWrap: "wrap" }}>
        <div>
          <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 10 }}>
            <StatusBadge status={e.status} />
            <span className="mono" style={{ fontSize: 13, color: "var(--ef-fg-3)", fontWeight: 600 }}>{e.id}</span>
          </div>
          <h2 style={{ fontSize: 28 }}>{e.workflow}</h2>
          <p className="muted" style={{ fontSize: 14, marginTop: 6 }}>{e.projectName} · triggered {e.trigger.replace(/_/g, " ")} by {e.by}</p>
        </div>
        <div style={{ display: "flex", gap: 10 }}>
          {(e.status === "failed" || e.status === "partially_completed") && <Button variant="secondary" icon="refresh-cw" onClick={() => toast("Retrying failed steps", "info")}>Retry failed</Button>}
          {e.outputs > 0 && <Button variant="secondary" icon="download" onClick={() => toast("Download started", "success")}>Download outputs</Button>}
          <Button variant="secondary" icon="git-branch" onClick={() => navigate("project", { id: e.project })}>Open project</Button>
        </div>
      </div>

      {/* summary stats */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(5, 1fr)", gap: 14, marginBottom: 24 }}>
        <MiniStat label="Files processed" value={e.files} sub={e.failed ? `${e.failed} failed` : "all succeeded"} bad={!!e.failed} />
        <MiniStat label="Outputs" value={e.outputs} />
        <MiniStat label="Duration" value={e.duration} />
        <MiniStat label="Pages" value={e.pages} />
        <MiniStat label="AI tokens" value={e.tokens ? (e.tokens / 1000).toFixed(1) + "K" : "0"} />
      </div>

      {/* error banner */}
      {e.error && (
        <div className="card" style={{ padding: "14px 18px", marginBottom: 22, borderColor: "var(--ef-danger)", background: "#FCF0F0", display: "flex", gap: 12, alignItems: "center" }}>
          <Icon name="alert-circle" size={20} color="var(--ef-danger)" />
          <div style={{ flex: 1 }}><div style={{ fontWeight: 700, color: "var(--ef-fg-1)", fontSize: 14 }}>{e.error}</div><div className="muted" style={{ fontSize: 12.5, marginTop: 2 }}>Reconnect Google Drive, then retry this execution.</div></div>
          <Button variant="secondary" size="sm" onClick={() => navigate("connectors")}>Reconnect</Button>
        </div>
      )}
      {e.status === "waiting_for_human_review" && (
        <div className="card" style={{ padding: "14px 18px", marginBottom: 22, borderColor: "var(--ef-violet)", background: "#F3F0FE", display: "flex", gap: 12, alignItems: "center" }}>
          <Icon name="user-plus" size={20} color="var(--ef-violet)" />
          <div style={{ flex: 1 }}><div style={{ fontWeight: 700, color: "var(--ef-fg-1)", fontSize: 14 }}>Waiting for your review</div><div className="muted" style={{ fontSize: 12.5, marginTop: 2 }}>A high-value claim exceeded the auto-process threshold and is paused for approval.</div></div>
          <Button variant="secondary" size="sm" onClick={() => toast("Opening review", "info")}>Review now</Button>
          <Button variant="primary" size="sm" onClick={() => toast("Approved", "success")}>Approve</Button>
        </div>
      )}

      {/* replay graph */}
      <div className="card card-pad" style={{ marginBottom: 22 }}>
        <div className="eyebrow" style={{ marginBottom: 16 }}>Workflow replay</div>
        <ReplayGraph statuses={statuses} />
        <div style={{ display: "flex", gap: 16, marginTop: 16, flexWrap: "wrap" }}>
          {[["completed", "Completed"], ["running", "Running"], ["failed", "Failed"], ["waiting", "Waiting"], ["skipped", "Skipped"]].map(([s, l]) => (
            <div key={s} style={{ display: "flex", alignItems: "center", gap: 6 }}><span className="dot" style={{ background: UI.statusMeta(s).c, width: 8, height: 8 }} /><span className="muted" style={{ fontSize: 12 }}>{l}</span></div>
          ))}
        </div>
      </div>

      <div style={{ marginBottom: 18 }}><UI.Tabs tabs={[{ id: "timeline", label: "Step timeline" }, { id: "files", label: "Files", count: e.files }, { id: "outputs", label: "Outputs", count: e.outputs }, { id: "logs", label: "Logs" }, { id: "errors", label: "Errors", count: e.failed || (e.error ? 1 : 0) }]} active={tab} onChange={setTab} /></div>

      {tab === "timeline" && (
        <div className="card" style={{ overflow: "hidden" }}>
          {steps.map((s, i) => (
            <div key={i} style={{ display: "flex", gap: 14, padding: "14px 18px", borderTop: i ? "1px solid var(--ef-border)" : 0, alignItems: "center" }}>
              <StepIcon status={s.status} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 700, color: "var(--ef-fg-1)", fontSize: 13.5 }}>{s.name}</div>
                <div className="muted" style={{ fontSize: 12, marginTop: 2 }}>{s.agent ? s.agent + " · " : ""}{(s.in || []).join(", ")}{s.out && s.out.length ? " → " + s.out.join(", ") : ""}{s.external ? " → " + s.external : ""}</div>
              </div>
              {s.conf != null && <span className="badge" style={{ fontSize: 10.5 }}>conf {Math.round(s.conf * 100)}%{s.lowConf ? ` · ${s.lowConf} low` : ""}</span>}
              <StatusBadge status={s.status} size="sm" />
              <span className="mono muted" style={{ fontSize: 12, width: 44, textAlign: "right" }}>{s.duration}</span>
            </div>
          ))}
        </div>
      )}

      {tab === "files" && (
        <div className="card" style={{ overflow: "hidden" }}>
          <table className="tbl"><thead><tr><th>File</th><th>Template matched</th><th style={{ textAlign: "right" }}>Match conf.</th><th>Status</th><th>Output</th></tr></thead>
            <tbody>{filesFor(e).map((f, i) => (
              <tr key={i}><td><div style={{ display: "flex", gap: 9, alignItems: "center" }}><Icon name="file-text" size={16} color="var(--ef-fg-3)" /><span className="mono" style={{ fontSize: 12.5, fontWeight: 600, color: "var(--ef-fg-1)" }}>{f.name}</span></div></td>
                <td className="muted">{f.template}</td><td style={{ textAlign: "right" }}><span className="mono" style={{ color: f.match >= 0.85 ? "var(--ef-success)" : "var(--ef-warning)", fontWeight: 700, fontSize: 12 }}>{f.match ? Math.round(f.match * 100) + "%" : "—"}</span></td>
                <td><StatusBadge status={f.status} size="sm" /></td><td className="muted mono" style={{ fontSize: 12 }}>{f.output || "—"}</td></tr>
            ))}</tbody>
          </table>
        </div>
      )}

      {tab === "outputs" && (e.outputs > 0 ? (
        <div className="card" style={{ overflow: "hidden" }}>
          <table className="tbl"><thead><tr><th>File</th><th>Type</th><th>Destination</th><th>Delivery</th><th></th></tr></thead>
            <tbody>{outputsFor(e).map((o, i) => (
              <tr key={i}><td className="mono" style={{ fontWeight: 600, color: "var(--ef-fg-1)", fontSize: 12.5 }}>{o.name}</td><td><span className="badge">{o.type}</span></td>
                <td className="muted" style={{ fontSize: 12.5 }}>{o.dest}</td><td><StatusBadge status="completed" size="sm" /></td>
                <td><button className="btn btn-ghost btn-icon btn-sm" onClick={() => toast("Download started", "success")}><Icon name={o.dest.includes("Drive") ? "external-link" : "download"} size={15} /></button></td></tr>
            ))}</tbody>
          </table>
        </div>
      ) : <div className="card"><UI.EmptyState icon="send" title="No outputs generated" body="This execution did not reach an output node." compact /></div>)}

      {tab === "logs" && (
        <div className="card" style={{ background: "var(--ef-ink-950)", padding: 18, overflow: "auto" }}>
          <pre className="mono" style={{ margin: 0, fontSize: 12, lineHeight: 1.85, color: "var(--ef-ink-200)" }}>{logLines(e, steps)}</pre>
        </div>
      )}

      {tab === "errors" && ((e.failed || e.error) ? (
        <div className="card card-pad">
          <div style={{ display: "flex", gap: 12, alignItems: "flex-start" }}>
            <Icon name="alert-circle" size={20} color="var(--ef-danger)" />
            <div style={{ flex: 1 }}>
              <div style={{ fontWeight: 700, color: "var(--ef-fg-1)" }}>{e.error || "3 files failed due to unreadable scans"}</div>
              <div className="muted" style={{ fontSize: 13, marginTop: 6, lineHeight: 1.5 }}>{e.error ? "The output step could not upload because the Google Drive connector authorization expired. No partial files were written." : "OCR confidence fell below threshold on 3 documents. The remaining files completed and were consolidated."}</div>
              <div style={{ display: "flex", gap: 10, marginTop: 14 }}>
                <Button variant="secondary" size="sm" icon="refresh-cw">Retry failed</Button>
                <Button variant="ghost" size="sm">View affected files</Button>
              </div>
              <div className="mono muted" style={{ fontSize: 11.5, marginTop: 14 }}>support_id: err_{e.id.replace("exec_", "")}_{e.status === "failed" ? "auth" : "ocr"}</div>
            </div>
          </div>
        </div>
      ) : <div className="card"><UI.EmptyState icon="check-circle" title="No errors" body="Every file processed cleanly." compact /></div>)}
    </div></div>
  );
}

function ReplayGraph({ statuses }) {
  const nodes = DATA.heroNodes, edges = DATA.heroEdges;
  const minX = Math.min(...nodes.map((n) => n.x)), maxX = Math.max(...nodes.map((n) => n.x)) + 196;
  const minY = Math.min(...nodes.map((n) => n.y)), maxY = Math.max(...nodes.map((n) => n.y)) + 64;
  const W = maxX - minX, H = maxY - minY;
  return (
    <div style={{ overflowX: "auto", paddingBottom: 8 }}>
      <div style={{ position: "relative", width: W, height: H, minWidth: "100%" }}>
        <svg style={{ position: "absolute", inset: 0, overflow: "visible", pointerEvents: "none" }} width={W} height={H}>
          {edges.map((e, i) => { const a = nodes.find((n) => n.id === e.from), b = nodes.find((n) => n.id === e.to); if (!a || !b) return null;
            const x1 = a.x - minX + 196, y1 = a.y - minY + 32, x2 = b.x - minX, y2 = b.y - minY + 32; const dx = Math.max(30, Math.abs(x2 - x1) * 0.5);
            const done = statuses[e.from] === "completed" && statuses[e.to] === "completed";
            return <path key={i} d={`M ${x1} ${y1} C ${x1 + dx} ${y1}, ${x2 - dx} ${y2}, ${x2} ${y2}`} fill="none" stroke={done ? "var(--ef-success)" : "var(--ef-ink-200)"} strokeWidth="2" />; })}
        </svg>
        {nodes.map((n) => { const m = UI.NODE_TYPES[n.type]; const st = statuses[n.id]; const sm = UI.statusMeta(st === "waiting" ? "waiting_for_human_review" : st);
          return (
            <div key={n.id} style={{ position: "absolute", left: n.x - minX, top: n.y - minY, width: 196, background: "var(--ef-bg-raised)", border: `1.5px solid ${st === "skipped" ? "var(--ef-border)" : sm.c}`, borderRadius: 9, padding: "8px 10px", opacity: st === "skipped" ? 0.5 : 1, display: "flex", gap: 9, alignItems: "center" }}>
              <div style={{ width: 24, height: 24, borderRadius: 6, background: "var(--ef-bone-2)", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}><Icon name={m.icon} size={14} color={m.color} /></div>
              <div style={{ flex: 1, minWidth: 0 }}><div style={{ fontSize: 11.5, fontWeight: 700, color: "var(--ef-fg-1)", lineHeight: 1.2, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{n.label}</div></div>
              <StepIcon status={st} small />
            </div>
          ); })}
      </div>
    </div>
  );
}

function StepIcon({ status, small }) {
  const sz = small ? 16 : 22;
  const map = { completed: ["check", "var(--ef-success)"], failed: ["x", "var(--ef-danger)"], running: ["loader", "var(--ef-info)"], waiting: ["clock", "var(--ef-warning)"], skipped: ["minus", "var(--ef-fg-4)"] };
  const [ic, c] = map[status] || map.completed;
  return <div style={{ width: sz, height: sz, borderRadius: 999, background: status === "skipped" ? "var(--ef-bone-3)" : c + "22", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}><Icon name={ic} size={small ? 11 : 14} color={c} className={status === "running" ? "spin" : ""} /></div>;
}
function MiniStat({ label, value, sub, bad }) {
  return <div className="card card-pad" style={{ padding: 16 }}><div className="eyebrow">{label}</div><div style={{ fontSize: 24, fontWeight: 800, color: "var(--ef-fg-1)", letterSpacing: "-0.02em", marginTop: 6 }} className="tabular">{value}</div>{sub && <div style={{ fontSize: 11.5, color: bad ? "var(--ef-danger)" : "var(--ef-fg-3)", marginTop: 2, fontWeight: 600 }}>{sub}</div>}</div>;
}

function synthSteps(e) {
  const base = [
    { name: "Receive document", type: "input", status: "completed", duration: "0.4s", in: ["input"], out: [] },
    { name: "OCR document", type: "processing", status: "completed", duration: "9s", agent: "OCR Agent", conf: 0.95 },
    { name: "Extract fields", type: "processing", status: "completed", duration: "32s", agent: "Extraction Agent", conf: 0.92 },
  ];
  if (e.status === "failed") base.push({ name: "Upload output", type: "output", status: "failed", duration: "—", agent: "Output Agent" });
  else if (e.status === "waiting_for_human_review") base.push({ name: "Decision: high-value", type: "decision", status: "waiting", duration: "—" });
  else base.push({ name: "Generate output", type: "processing", status: "completed", duration: "1s" }, { name: "Deliver output", type: "output", status: "completed", duration: "2s", agent: "Output Agent" });
  return base;
}
function filesFor(e) {
  if (e.id === "exec_8841") return [{ name: "zara_po_4417.pdf", template: "Zara purchase order v2", match: 0.96, status: "completed", output: "po_4417.csv" }];
  if (e.status === "partially_completed") return [...Array(4)].map((_, i) => ({ name: `invoice_${1001 + i}.pdf`, template: "Supplier invoice v3", match: i < 1 ? 0.62 : 0.9, status: i < 1 ? "failed" : "completed", output: i < 1 ? "—" : "row added" }));
  return [...Array(Math.min(e.files, 4))].map((_, i) => ({ name: `document_${i + 1}.pdf`, template: "Standard", match: 0.9, status: "completed", output: "processed" }));
}
function outputsFor(e) {
  if (e.id === "exec_8841") return [{ name: "po_4417.csv", type: "CSV", dest: "Google Drive · /Purchase Orders/2026" }, { name: "notification", type: "Email", dest: "ops@fakirfashion.com" }];
  if (e.id === "exec_8838") return [{ name: "split_documents.zip", type: "Archive", dest: "Download · 20 files" }, { name: "page_01.pdf … page_20.pdf", type: "PDF", dest: "Google Drive" }];
  return [...Array(e.outputs)].map((_, i) => ({ name: i === 0 ? "output.xlsx" : "report", type: i === 0 ? "Excel" : "Email", dest: i === 0 ? "Download" : "Email" }));
}
function logLines(e, steps) {
  const t = e.started ? "10:00" : "—";
  let out = `[${t}:00] execution ${e.id} started · trigger=${e.trigger}\n[${t}:00] workflow_version=1 template_versions=[tmpl_po_v2]\n`;
  steps.forEach((s, i) => { out += `[${t}:${String(i * 11 + 2).padStart(2, "0")}] ${s.status === "failed" ? "ERROR" : "INFO"}  ${s.name}${s.agent ? ` · agent=${s.agent}` : ""}${s.conf ? ` · conf=${s.conf}` : ""} · ${s.duration}\n`; });
  out += e.error ? `[${t}:22] ERROR  ${e.error}\n[${t}:22] execution finalized · status=failed` : `[${t}:${String(steps.length * 11).padStart(2, "0")}] INFO  execution finalized · status=${e.status}`;
  return out;
}

window.ExecutionsList = ExecutionsList;
window.ExecutionDetail = ExecutionDetail;
