// Left column: agent picker + model params + system prompt.
//
// Skills / MCP toggles used to live here too, but they overlapped with the
// in-composer ChipPicker in chat-panel.jsx (which toggles session-only,
// while these toggled agent.enabledSkills / enabledMCPs as the agent
// default). The chat surface picker is enough for day-to-day toggling;
// editing the agent's persistent defaults is a Manage-page concern (same
// reason "New agent" was moved to Manage in PR pg-new-agent-to-manage).
// Removed here 2026-06-06 per user request.

function AgentPicker({ agents, activeId, onSelect, onAdd }) {
  return (
    <div className="section">
      <div className="section-title">
        <span>Agents</span>
      </div>
      <div>
        {agents.map((a) => (
          <div
            key={a.id}
            className={"agent-card" + (a.id === activeId ? " active" : "")}
            onClick={() => onSelect(a.id)}
          >
            <div className="avatar" style={{ background: a.color }}>{a.initials}</div>
            <div className="meta">
              <div className="name">{a.name}</div>
              <div className="desc">{a.desc}</div>
            </div>
            <div className="check"><Icon name="check" size={14} /></div>
          </div>
        ))}
      </div>
      <div className="add-agent-row">
        {/* PR pg-new-agent-to-manage: "+ New agent" now navigates to
            /manage?new=agent (Manage page picks up the hint to open the
            creation form). "Browse" removed — Manage is the single place
            for agent CRUD; having both inline-create and "browse" in
            Playground was redundant + the inline path skipped the proper
            naming/system-prompt fields. */}
        <button className="btn sm" onClick={onAdd}>
          <Icon name="plus" size={12} /> New agent
        </button>
      </div>
    </div>
  );
}

function ModelSection({ agent, onUpdate, overrideKeys, onReset }) {
  const provider = agent.modelProvider || "baizhi";
  const temporaryCount = overrideKeys.size;
  const scope = (key) => overrideKeys.has(key) ? "temporary" : "inherited";
  const modelOptions = modelOptionsForProvider(provider);
  const modelValue = agent.model || "";
  const displayModel = modelValue || defaultModelForProvider(provider);
  const setProvider = (provider) => {
    const knownProvider = modelProviderFor(agent.model);
    let nextModel = agent.model;
    if (!nextModel) {
      nextModel = defaultModelForProvider(provider);
    } else if (knownProvider && knownProvider !== provider) {
      nextModel = defaultModelForProvider(provider);
    }
    onUpdate({
      modelProvider: provider,
      model: nextModel,
    });
  };
  const setModel = (model) => {
    const nextProvider = modelProviderFor(model);
    const patch = { model };
    const modelBelongsToCurrentProvider = modelOptions.some((item) => item.id === model);
    if (nextProvider && nextProvider !== provider && !modelBelongsToCurrentProvider) {
      patch.modelProvider = nextProvider;
    }
    onUpdate(patch);
  };
  return (
    <div className="section">
      <div className="section-title">
        <span>Model Endpoint</span>
        {temporaryCount ? <span className="val">Temporary overrides · {temporaryCount}</span> : <span className="val">Agent default</span>}
        {temporaryCount ? (
          <button className="btn sm" type="button" onClick={onReset} title="Reset to Agent default">Reset</button>
        ) : null}
      </div>
      <div className="field">
        <label>
          <span>Provider</span>
          <span className="val">{agent.modelProvider || "minimax"} · {scope("provider")}</span>
        </label>
        <select
          className="select"
          value={provider}
          onChange={(e) => setProvider(e.target.value)}
        >
          {(window.MODEL_PROVIDERS || []).map((item) => (
            <option key={item.id} value={item.id}>{item.label}</option>
          ))}
        </select>
      </div>
      <div className="field">
        <label>
          <span>Model name</span>
          {/* 显示当前选中 model 的真实上下文窗口(per-model 记在 data.jsx MODELS) */}
          <span className="val">window {modelContextWindow(displayModel).toLocaleString()} · {scope("model_name")}</span>
        </label>
        <input
          className="input"
          value={modelValue}
          onChange={(e) => setModel(e.target.value)}
          list="model-options"
          placeholder={defaultModelForProvider(provider)}
        />
        <datalist id="model-options">
          {modelOptions.map((m) => (
            <option key={m.id} value={m.id}>{m.label}</option>
          ))}
        </datalist>
      </div>
      <div className="field">
        <label>
          <span>Endpoint</span>
          <span className="val">base URL</span>
        </label>
        <input
          className="input mono"
          value={modelEndpointForProvider(provider)}
          readOnly
          placeholder="Configured by server"
        />
      </div>
      <div className="field">
        <label>
          <span>Credential</span>
          <span className="val">Server managed</span>
        </label>
        <input
          className="input mono"
          value="Server managed"
          readOnly
          placeholder="Configured by server"
        />
      </div>
      <div className="field">
        <label>
          <span>Temperature</span>
          <span className="val">{agent.temperature.toFixed(2)} · {scope("temperature")}</span>
        </label>
        <input
          type="range" className="slider"
          min="0" max="2" step="0.05"
          value={agent.temperature}
          onChange={(e) => onUpdate({ temperature: parseFloat(e.target.value) })}
        />
      </div>
      <div className="field">
        <label>
          <span>Top P</span>
          <span className="val">{agent.top_p.toFixed(2)} · {scope("top_p")}</span>
        </label>
        <input
          type="range" className="slider"
          min="0" max="1" step="0.05"
          value={agent.top_p}
          onChange={(e) => onUpdate({ top_p: parseFloat(e.target.value) })}
        />
      </div>
      <div className="field">
        <label>
          {/* Max tokens = 单次输出上限(output cap)。 */}
          <span>Max output</span>
          <span className="val">{agent.max_tokens.toLocaleString()} / 409,600 · {scope("max_tokens")}</span>
        </label>
        <input
          type="range" className="slider"
          min="256" max="409600" step="128"
          value={Math.min(agent.max_tokens, 409600)}
          onChange={(e) => onUpdate({ max_tokens: parseInt(e.target.value, 10) })}
        />
      </div>
      <div className="field">
        <label style={{ display: "flex", alignItems: "center", justifyContent: "flex-start", gap: 8 }}>
          <input
            type="checkbox"
            checked={agent.reasoning_enabled !== false}
            onChange={(e) => onUpdate({ reasoning_enabled: e.target.checked })}
          />
          <span>Request thinking</span>
          <span className="val">{scope("reasoning_enabled")}</span>
        </label>
        <div className="hint">模型支持不一，勾选后也可能无思考输出，后续继续适配。</div>
      </div>
      <label className="field" style={{ display: "flex", alignItems: "center", justifyContent: "flex-start", gap: 8 }}>
        <input
          type="checkbox"
          checked={agent.reasoning_visible !== false}
          onChange={(e) => onUpdate({ reasoning_visible: e.target.checked })}
        />
        <span>Show thinking trace</span>
        <span className="val">{scope("reasoning_visible")}</span>
      </label>
    </div>
  );
}

function SystemSection({ agent, onUpdate }) {
  const [open, setOpen] = React.useState(false);
  const [popoverStyle, setPopoverStyle] = React.useState({});
  const triggerRef = React.useRef(null);
  const popRef = React.useRef(null);
  const placePopover = React.useCallback(() => {
    const trigger = triggerRef.current;
    if (!trigger) return;
    const rect = trigger.getBoundingClientRect();
    const gap = 12;
    const viewportPad = 16;
    const left = Math.min(
      rect.right + gap,
      window.innerWidth - viewportPad - 360
    );
    const width = Math.max(
      360,
      Math.min(560, window.innerWidth - left - viewportPad)
    );
    const top = Math.max(56, Math.min(rect.top - 8, window.innerHeight - 520));
    const maxHeight = Math.max(320, window.innerHeight - top - viewportPad);
    setPopoverStyle({ left, top, width, maxHeight });
  }, []);
  React.useEffect(() => {
    if (!open) return;
    placePopover();
    const onMove = () => placePopover();
    window.addEventListener("resize", onMove);
    window.addEventListener("scroll", onMove, true);
    return () => {
      window.removeEventListener("resize", onMove);
      window.removeEventListener("scroll", onMove, true);
    };
  }, [open, placePopover]);
  React.useEffect(() => {
    if (!open) return;
    const onDown = (e) => {
      if (popRef.current?.contains(e.target) || triggerRef.current?.contains(e.target)) return;
      setOpen(false);
    };
    const onKey = (e) => {
      if (e.key === "Escape") setOpen(false);
    };
    document.addEventListener("mousedown", onDown);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("mousedown", onDown);
      document.removeEventListener("keydown", onKey);
    };
  }, [open]);
  const detected = scanPromptVariables(agent.system || "");
  const summary = (agent.system || "").trim().replace(/\s+/g, " ");
  return (
    <div className={"section system-pop-section" + (open ? " open" : "")} ref={popRef}>
      <div className="section-title">
        <span>System</span>
        <button
          ref={triggerRef}
          className="btn sm"
          type="button"
          onClick={() => setOpen((v) => !v)}
        >
          <Icon name="settings" size={12} /> Edit
        </button>
      </div>
      <button
        type="button"
        className="system-pop-trigger"
        onClick={() => setOpen(true)}
        title={summary || "No system prompt"}
      >
        <span>{summary || "No system prompt"}</span>
        {detected.length ? <b>{detected.length} vars</b> : null}
      </button>
      {open ? (
        <div className="system-popover" ref={popRef} style={popoverStyle}>
          <div className="system-popover-head">
            <div>
              <div className="ttl">System prompt</div>
              <div className="sub">Variables are rendered by the runtime before each run.</div>
            </div>
            <button className="btn ghost icon sm" type="button" onClick={() => setOpen(false)} title="Close">
              <Icon name="x" size={12} />
            </button>
          </div>
          <PromptTemplateEditor
            className="textarea"
            rows={7}
            value={agent.system}
            agent={agent}
            onChange={(system, promptVariables) => onUpdate({ system, promptVariables })}
            style={{ minHeight: 132, maxHeight: 260, resize: "vertical" }}
          />
        </div>
      ) : null}
    </div>
  );
}

function LeftPanel({ agents, activeId, onSelect, onAdd, onUpdateAgent, modelAgent, modelOverride, onUpdateModel, onResetModel }) {
  const agent = agents.find((a) => a.id === activeId);
  return (
    <div className="col left">
      <div className="scroll">
        <AgentPicker
          agents={agents}
          activeId={activeId}
          onSelect={onSelect}
          onAdd={onAdd}
        />
        <ModelSection
          agent={modelAgent || agent}
          onUpdate={onUpdateModel}
          overrideKeys={new Set(Object.keys(modelOverride || {}))}
          onReset={onResetModel}
        />
        <SystemSection agent={agent} onUpdate={onUpdateAgent} />
      </div>
    </div>
  );
}

window.LeftPanel = LeftPanel;
