// ====== Add-to-dataset modal (shared between Traces + Evals) ======

const { useState: dUseState, useEffect: dUseEffect } = React;

// Toast manager — simple global queue
const _toasts = [];
const _toastListeners = new Set();
function pushToast(t) {
  const id = rid("toast");
  const obj = { id, ...t };
  _toasts.push(obj);
  _toastListeners.forEach((fn) => fn([..._toasts]));
  setTimeout(() => {
    const i = _toasts.findIndex((x) => x.id === id);
    if (i >= 0) _toasts.splice(i, 1);
    _toastListeners.forEach((fn) => fn([..._toasts]));
  }, t.duration || 5000);
}
function ToastContainer() {
  const [toasts, setToasts] = dUseState(_toasts);
  dUseEffect(() => {
    const fn = (t) => setToasts(t);
    _toastListeners.add(fn);
    return () => _toastListeners.delete(fn);
  }, []);
  return (
    <div className="toast-container">
      {toasts.map((t) => (
        <div key={t.id} className="toast">
          <span className="ic"><Icon name="check" size={12} /></span>
          <div className="body">{t.content}</div>
        </div>
      ))}
    </div>
  );
}

// ====== Add to dataset modal ======
function AddToDatasetModal({ trace, onClose }) {
  const [datasets, setDatasets] = dUseState([]);
  const [selectedDsId, setSelectedDsId] = dUseState(null);
  const [creatingNew, setCreatingNew] = dUseState(false);
  const [newDsName, setNewDsName] = dUseState("");
  const [loading, setLoading] = dUseState(true);
  const [loadError, setLoadError] = dUseState(null);

  // PR e2: fetch datasets from real backend on open. /v1/datasets list
  // doesn't include cases, so we lazy-fetch details when needed (the
  // sidebar shows `{cases.length} cases` — fetch detail to populate that
  // count). For brevity here we just show "—" if cases aren't loaded.
  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const items = await window.api.listDatasets();
        if (cancelled) return;
        const detailed = await Promise.all(items.map(
          (ds) => window.api.getDataset(ds.dataset_id).catch(() => ({ ...ds, cases: [] }))
        ));
        const decorated = detailed.map(window.decorateDataset);
        setDatasets(decorated);
        if (decorated.length && selectedDsId === null) {
          setSelectedDsId(decorated[0].id);
        }
      } catch (err) {
        if (!cancelled) setLoadError(err.message || String(err));
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => { cancelled = true; };
  }, []);

  // pre-extract tool names called in the trace
  const tracedTools = React.useMemo(() => {
    if (!trace) return [];
    const set = new Set();
    trace.spans.forEach((s) => {
      if (s.kind === "tool" || s.kind === "mcp") {
        // strip "github.list_prs" -> "github" for MCP namespace, keep skills as-is
        const base = s.name.split(".")[0];
        set.add(base);
      }
    });
    return [...set];
  }, [trace]);

  const [input, setInput] = dUseState(trace?.userInput || "");
  const [expected, setExpected] = dUseState(trace?.finalOutput || "");
  const [expectedTools, setExpectedTools] = dUseState(tracedTools);
  const [tags, setTags] = dUseState("");

  // All skills/MCPs (for tool picker)
  const allTools = React.useMemo(() => {
    const t = [];
    SKILLS.forEach((s) => t.push({ id: s.id, name: s.name, color: s.color, initials: s.initials, kind: "skill" }));
    MCPS.forEach((m) => t.push({ id: m.id, name: m.name, color: m.color, initials: m.initials, kind: "mcp" }));
    return t;
  }, []);

  const selectedDs = datasets.find((d) => d.id === selectedDsId);

  const toggleTool = (id) => {
    setExpectedTools((cur) => cur.includes(id) ? cur.filter((x) => x !== id) : [...cur, id]);
  };

  const handleCreateNew = async () => {
    if (!newDsName.trim()) return;
    try {
      const created = await window.api.createDataset({ name: newDsName.trim() });
      const decorated = window.decorateDataset({ ...created, cases: [] });
      setDatasets([decorated, ...datasets]);
      setSelectedDsId(decorated.id);
      setCreatingNew(false);
      setNewDsName("");
    } catch (err) {
      alert("Create dataset failed: " + (err.message || err));
    }
  };

  const handleSave = async () => {
    if (!selectedDs) return;
    try {
      const apiCase = await window.api.addDatasetCase(selectedDs.id, {
        input: input.trim(),
        expected: expected.trim() || null,
        tools: expectedTools,
        tags: tags.split(",").map((t) => t.trim()).filter(Boolean),
        source: trace ? { type: "trace", traceId: trace.id, runId: trace.runId } : { type: "manual" },
      });
      onClose();
      pushToast({
        content: (
          <span>
            Added to <strong>{selectedDs.name}</strong> · <a href="Evals.html">View in Evals →</a>
          </span>
        )
      });
    } catch (err) {
      alert("Save case failed: " + (err.message || err));
    }
  };

  return (
    <div className="modal-backdrop" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="modal" onMouseDown={(e) => e.stopPropagation()}>
        <div className="head">
          <div>
            <h2>Add to dataset</h2>
            <div className="sub">Save this trace as an eval case for regression testing.</div>
          </div>
          <button className="close" onClick={onClose} title="Close (Esc)"><Icon name="x" size={16} /></button>
        </div>
        <div className="body">
          <div className="mform-group">
            <div className="lbl">Dataset</div>
            <div className="ds-picker">
              {datasets.map((d) => (
                <div
                  key={d.id}
                  className={"opt" + (d.id === selectedDsId && !creatingNew ? " active" : "")}
                  onClick={() => { setSelectedDsId(d.id); setCreatingNew(false); }}
                >
                  <div className="av">
                    {d.id === selectedDsId && !creatingNew
                      ? <Icon name="check" size={14} />
                      : <Icon name="list" size={14} />}
                  </div>
                  <div className="meta">
                    <div className="nm">{d.name}</div>
                    <div className="ds">{d.description || <span className="dim">No description</span>}</div>
                  </div>
                  <span className="cnt">{d.cases.length} cases</span>
                </div>
              ))}
              <div
                className={"opt" + (creatingNew ? " active" : "")}
                onClick={() => setCreatingNew(true)}
                style={{ borderTop: "1px dashed var(--border)" }}
              >
                <div className="av"><Icon name="plus" size={14} /></div>
                <div className="meta">
                  <div className="nm">Create new dataset…</div>
                  <div className="ds">Start a fresh dataset for this case</div>
                </div>
              </div>
              {creatingNew && (
                <div className="new-ds-form">
                  <input
                    className="input-lg"
                    autoFocus
                    placeholder="Dataset name"
                    value={newDsName}
                    onChange={(e) => setNewDsName(e.target.value)}
                    onKeyDown={(e) => { if (e.key === "Enter") handleCreateNew(); }}
                  />
                  <div className="row">
                    <button className="btn primary sm" disabled={!newDsName.trim()} onClick={handleCreateNew}>Create</button>
                    <button className="btn sm" onClick={() => { setCreatingNew(false); setNewDsName(""); }}>Cancel</button>
                  </div>
                </div>
              )}
            </div>
          </div>

          <div className="mform-group">
            <div className="lbl">Input <span className="opt">— the user message</span></div>
            <textarea
              className="textarea-lg"
              style={{ minHeight: 64 }}
              value={input}
              onChange={(e) => setInput(e.target.value)}
            />
          </div>

          <div className="mform-group">
            <div className="lbl">Expected output <span className="opt">— optional reference answer</span></div>
            <textarea
              className="textarea-lg"
              style={{ minHeight: 90 }}
              value={expected}
              onChange={(e) => setExpected(e.target.value)}
              placeholder="Leave blank to use only LLM-as-judge / trajectory graders…"
            />
          </div>

          <div className="mform-group">
            <div className="lbl">Expected tool calls <span className="opt">— what the agent should call</span></div>
            <div className="tool-multi">
              {allTools.map((t) => (
                <span
                  key={t.id}
                  className={"opt" + (expectedTools.includes(t.id) ? " on" : "")}
                  onClick={() => toggleTool(t.id)}
                >
                  <span className="ic" style={{ background: t.color }}>{t.initials}</span>
                  {t.name}
                </span>
              ))}
            </div>
            <div className="hint">
              {tracedTools.length ? `Pre-selected from this trace: ${tracedTools.join(", ")}` : "No tools were called in this trace"}
            </div>
          </div>

          <div className="mform-group">
            <div className="lbl">Tags <span className="opt">— comma separated</span></div>
            <input
              className="input-lg"
              value={tags}
              placeholder="e.g. p0, regression, billing"
              onChange={(e) => setTags(e.target.value)}
            />
          </div>
        </div>
        <div className="foot">
          <span className="hint">Source: <span className="mono">trace {trace?.runId.slice(-8)}</span></span>
          <div className="spacer" />
          <button className="btn" onClick={onClose}>Cancel</button>
          <button
            className="btn primary"
            disabled={!selectedDs || !input.trim()}
            onClick={handleSave}
          >
            <Icon name="plus" size={11} /> Add to dataset
          </button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  AddToDatasetModal,
  ToastContainer,
  pushToast,
});
