// Instance detail, API keys, metrics, skills, billing views

function InstanceDetail({ instance, onNav, allSkills, onReload }) {
  const [tab, setTab] = React.useState("overview");
  const [showOpenAI, setShowOpenAI] = React.useState(false);
  const [showAnthropic, setShowAnthropic] = React.useState(false);
  const inst = instance;
  if (!inst) return <div className="content full">Instance not found.</div>;

  const skillsBySparkSeed = inst.skills.map((_, i) => 10 + Math.floor(Math.random() * 40));

  const days = Array.from({ length: 30 }, (_, i) => i);
  const tokSeriesIn = days.map((d) => (inst.tokensIn / 30) + Math.sin(d / 3) * (inst.tokensIn / 100) + Math.random() * (inst.tokensIn / 120));
  const tokSeriesOut = days.map((d) => (inst.tokensOut / 30) + Math.cos(d / 4) * (inst.tokensOut / 100) + Math.random() * (inst.tokensOut / 130));
  const dayLabels = days.map((d) => {
    const dt = new Date(2026, 2, 22 + d);
    return `${dt.getDate()}.${dt.getMonth() + 1}`;
  });

  return (
    <div className="content full">
      <div className="page-head">
        <div className="row gap-14" style={{ alignItems: "center" }}>
          <button className="btn ghost" onClick={() => onNav("dashboard")} style={{ padding: 4 }}>
            <Icon name="arrow-left" size={16}/>
          </button>
          <InstanceLogo inst={inst} size={44}/>
          <div>
            <div className="row gap-6" style={{ alignItems: "center" }}>
              <h1 className="page-title" style={{ margin: 0 }}>{inst.name}</h1>
              <StatusPill status={inst.status}/>
            </div>
            <p className="page-sub mono" style={{ margin: "2px 0 0" }}>{inst.id}.oprt.chat · {inst.industry} · {inst.plan}</p>
          </div>
        </div>
        <div className="row gap-6">
          <button className="btn sm"><Icon name="refresh" size={13}/> Restart</button>
          <button className="btn sm"><Icon name="pause" size={13}/> Pause</button>
          <button className="btn sm"><Icon name="link" size={13}/> Open chat</button>
          <button className="btn sm danger"><Icon name="trash" size={13}/></button>
        </div>
      </div>

      <div className="tabs">
        {["overview", "messages", "skills", "files", "keys", "billing", "logs", "settings"].map((t) => (
          <div key={t} className={"tab " + (tab === t ? "active" : "")} onClick={() => setTab(t)}>
            {t[0].toUpperCase() + t.slice(1)}
          </div>
        ))}
      </div>

      {tab === "overview" && (
        <>
          <div className="grid-4 mb-22">
            <MetricCard label="Tokens in" value={fmtNum(inst.tokensIn)} delta={18.2} sparkColor="var(--brand)"
              spark={tokSeriesIn.map((v,i) => v / 10000)}/>
            <MetricCard label="Tokens out" value={fmtNum(inst.tokensOut)} delta={22.4} sparkColor="var(--violet)"
              spark={tokSeriesOut.map((v,i) => v / 5000)}/>
            <MetricCard label="Cost MTD" value={fmtEur(inst.cost)} delta={14.1} sparkColor="var(--amber)"
              spark={[5,8,12,18,22,28,32,38,42,45]}/>
            <MetricCard label="Messages" value={fmtNum(inst.messages)} delta={-4.3} sparkColor="var(--blue)"
              spark={[30,32,40,38,45,48,52,50,55,58]}/>
          </div>

          <div style={{ display: "grid", gridTemplateColumns: "1.5fr 1fr", gap: 14, marginBottom: 22 }}>
            <div className="panel">
              <div className="panel-head">
                <h3>Token usage</h3>
                <span className="sub">· 30d</span>
              </div>
              <div className="panel-body">
                <StackedArea seriesA={tokSeriesIn} seriesB={tokSeriesOut} labels={dayLabels} height={200}/>
              </div>
            </div>
            <div className="panel">
              <div className="panel-head"><h3>Customer info</h3></div>
              <div className="panel-body">
                <div className="kv">
                  <div className="k">Contact</div><div className="v">{inst.contact}</div>
                  <div className="k">Email</div><div className="v mono">{inst.email}</div>
                  <div className="k">Industry</div><div className="v">{inst.industry}</div>
                  <div className="k">Plan</div><div className="v">{inst.plan}</div>
                  <div className="k">Launched</div><div className="v mono">{inst.createdAt}</div>
                  <div className="k">Model</div><div className="v mono">{inst.model}</div>
                  <div className="k">Provider</div><div className="v" style={{ textTransform: "capitalize" }}>{inst.apiProvider}</div>
                  <div className="k">Telegram</div><div className="v mono" style={{ fontSize: 11.5 }}>{inst.telegram}</div>
                </div>
              </div>
            </div>
          </div>

          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
            <div className="panel">
              <div className="panel-head"><h3>Active skills</h3><span className="sub">· {inst.skills.length}</span></div>
              <div className="panel-body" style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
                {inst.skills.map((s) => <span key={s} className="skill-chip" style={{ padding: "4px 8px", fontSize: 11.5 }}>{s}</span>)}
              </div>
            </div>
            <div className="panel">
              <div className="panel-head"><h3>Recent activity</h3></div>
              <div className="panel-body col" style={{ gap: 8 }}>
                {[
                  { t: "2 min ago", m: "Received Telegram message from +49 176 •••• 412" },
                  { t: "8 min ago", m: "Skill oprt-calendar · booked meeting for Mo 15:00" },
                  { t: "14 min ago", m: "Skill oprt-gmail · drafted reply to invoice thread" },
                  { t: "41 min ago", m: "Model call claude-sonnet-4.5 · 4,218 tokens" },
                  { t: "1 h ago", m: "Handed conversation to human (Max Mustermann)" },
                ].map((r, i) => (
                  <div key={i} className="row" style={{ fontSize: 12.5, gap: 10, padding: "6px 0", borderBottom: i < 4 ? "1px solid var(--border)" : "0" }}>
                    <span className="mono dim" style={{ width: 72, flexShrink: 0, fontSize: 11 }}>{r.t}</span>
                    <span>{r.m}</span>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </>
      )}

      {tab === "keys" && (
        <KeyPanel inst={inst} showOpenAI={showOpenAI} setShowOpenAI={setShowOpenAI} showAnthropic={showAnthropic} setShowAnthropic={setShowAnthropic}/>
      )}

      {tab === "skills" && (
        <SkillsManager inst={inst} allSkills={allSkills || []} onReload={onReload}/>
      )}

      {tab === "files" && (
        <FilesBrowser inst={inst}/>
      )}

      {tab === "messages" && <MessagesStub/>}
      {tab === "billing" && <BillingInline inst={inst}/>}
      {tab === "logs" && <LogsStub inst={inst}/>}
      {tab === "settings" && <SettingsStub inst={inst}/>}
    </div>
  );
}

function SkillsManager({ inst, allSkills, onReload }) {
  const [saving, setSaving] = React.useState(false);
  const [showAdd, setShowAdd] = React.useState(false);
  const [localSkills, setLocalSkills] = React.useState(() => {
    if (inst.skillDetails && inst.skillDetails.length > 0) {
      return inst.skillDetails.map(s => ({ name: s.skill_name, enabled: s.enabled, category: s.category }));
    }
    return inst.skills.map(s => ({ name: s, enabled: true, category: "" }));
  });

  const assignedNames = new Set(localSkills.map(s => s.name));
  const availableSkills = (allSkills || []).filter(s => !assignedNames.has(s.name));

  const toggleSkill = async (name, enabled) => {
    const updated = localSkills.map(s => s.name === name ? { ...s, enabled } : s);
    setLocalSkills(updated);
    setSaving(true);
    try {
      await OprtAPI.updateInstanceSkills(inst.uuid, updated.map(s => ({ name: s.name, enabled: s.enabled })));
    } catch (e) {
      setLocalSkills(localSkills);
    } finally { setSaving(false); }
  };

  const addSkill = async (name) => {
    const skill = allSkills.find(s => s.name === name);
    const updated = [...localSkills, { name, enabled: true, category: skill ? skill.category : "" }];
    setLocalSkills(updated);
    setShowAdd(false);
    setSaving(true);
    try {
      await OprtAPI.updateInstanceSkills(inst.uuid, updated.map(s => ({ name: s.name, enabled: s.enabled })));
      if (onReload) onReload();
    } catch (e) {
      setLocalSkills(localSkills);
    } finally { setSaving(false); }
  };

  const removeSkill = async (name) => {
    const updated = localSkills.filter(s => s.name !== name);
    setLocalSkills(updated);
    setSaving(true);
    try {
      await OprtAPI.updateInstanceSkills(inst.uuid, updated.map(s => ({ name: s.name, enabled: s.enabled })));
      if (onReload) onReload();
    } catch (e) {
      setLocalSkills(localSkills);
    } finally { setSaving(false); }
  };

  return (
    <div className="col" style={{ gap: 14 }}>
      <div className="panel">
        <div className="panel-head">
          <h3>Skills</h3>
          <span className="sub">· {localSkills.filter(s => s.enabled).length} active / {localSkills.length} installed</span>
          <div className="right row gap-6">
            {saving && <span className="dim" style={{ fontSize: 12 }}>Saving…</span>}
            <button className="btn sm" onClick={() => setShowAdd(!showAdd)}>
              <Icon name="plus" size={12}/> Add skill
            </button>
          </div>
        </div>
        <div className="panel-body">
          <table className="table">
            <thead><tr><th>Skill</th><th>Category</th><th>Status</th><th style={{ textAlign: "right" }}>Actions</th></tr></thead>
            <tbody>
              {localSkills.map((s) => (
                <tr key={s.name}>
                  <td className="mono">{s.name}</td>
                  <td className="dim">{s.category}</td>
                  <td>
                    <label className="toggle-row" style={{ cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 8 }}>
                      <span className={"toggle-track " + (s.enabled ? "on" : "")} onClick={() => toggleSkill(s.name, !s.enabled)}
                        style={{
                          display: "inline-block", width: 36, height: 20, borderRadius: 10,
                          background: s.enabled ? "var(--brand)" : "var(--border)",
                          position: "relative", transition: "background 0.2s", cursor: "pointer",
                        }}>
                        <span style={{
                          position: "absolute", top: 2, left: s.enabled ? 18 : 2,
                          width: 16, height: 16, borderRadius: 8,
                          background: "var(--bg)", transition: "left 0.2s",
                        }}/>
                      </span>
                      <span className={s.enabled ? "" : "dim"}>{s.enabled ? "Enabled" : "Disabled"}</span>
                    </label>
                  </td>
                  <td style={{ textAlign: "right" }}>
                    <button className="btn sm ghost" onClick={() => removeSkill(s.name)} title="Remove skill">
                      <Icon name="trash" size={12}/>
                    </button>
                  </td>
                </tr>
              ))}
              {localSkills.length === 0 && (
                <tr><td colSpan={4} className="dim" style={{ textAlign: "center", padding: 20 }}>No skills installed. Click "Add skill" to get started.</td></tr>
              )}
            </tbody>
          </table>
        </div>
      </div>

      {showAdd && (
        <div className="panel">
          <div className="panel-head">
            <h3>Available skills</h3>
            <button className="btn sm ghost right" onClick={() => setShowAdd(false)}><Icon name="x" size={14}/></button>
          </div>
          <div className="panel-body">
            {availableSkills.length === 0 ? (
              <div className="dim" style={{ padding: 16, textAlign: "center" }}>All skills are already installed.</div>
            ) : (
              <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(240px, 1fr))", gap: 8 }}>
                {availableSkills.map((s) => (
                  <div key={s.name} className="col" style={{
                    padding: "10px 12px", border: "1px solid var(--border)", borderRadius: 8,
                    background: "var(--panel-2)", cursor: "pointer",
                  }} onClick={() => addSkill(s.name)}>
                    <div className="row" style={{ justifyContent: "space-between", alignItems: "center" }}>
                      <span className="mono" style={{ fontSize: 12.5 }}>{s.name}</span>
                      <button className="btn sm ghost"><Icon name="plus" size={12}/></button>
                    </div>
                    <div className="dim" style={{ fontSize: 11.5, marginTop: 4 }}>{s.category} · {s.description || ""}</div>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

function FilesBrowser({ inst }) {
  const [files, setFiles] = React.useState([]);
  const [selectedFile, setSelectedFile] = React.useState(null);
  const [fileContent, setFileContent] = React.useState("");
  const [originalContent, setOriginalContent] = React.useState("");
  const [loading, setLoading] = React.useState(true);
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState(null);
  const [saveMsg, setSaveMsg] = React.useState(null);

  const loadFiles = async () => {
    setLoading(true); setError(null);
    try {
      const r = await OprtAPI.listFiles(inst.uuid);
      setFiles(r.files || []);
    } catch (e) {
      setError(e.message);
      setFiles([]);
    } finally { setLoading(false); }
  };

  React.useEffect(() => { loadFiles(); }, [inst.uuid]);

  const openFile = async (path) => {
    setSelectedFile(path); setError(null); setSaveMsg(null);
    try {
      const r = await OprtAPI.readFile(inst.uuid, path);
      setFileContent(r.content);
      setOriginalContent(r.content);
    } catch (e) {
      setError("Failed to load " + path + ": " + e.message);
      setFileContent("");
      setOriginalContent("");
    }
  };

  const saveFile = async () => {
    if (!selectedFile) return;
    setSaving(true); setSaveMsg(null); setError(null);
    try {
      await OprtAPI.writeFile(inst.uuid, selectedFile, fileContent);
      setOriginalContent(fileContent);
      setSaveMsg("Saved");
      setTimeout(() => setSaveMsg(null), 2000);
    } catch (e) {
      setError("Failed to save: " + e.message);
    } finally { setSaving(false); }
  };

  const hasChanges = fileContent !== originalContent;

  const buildTree = (paths) => {
    const tree = {};
    for (const p of paths) {
      const parts = p.split("/");
      let node = tree;
      for (let i = 0; i < parts.length; i++) {
        const part = parts[i];
        if (i === parts.length - 1) {
          node[part] = p;
        } else {
          if (!node[part] || typeof node[part] === "string") node[part] = {};
          node = node[part];
        }
      }
    }
    return tree;
  };

  const renderTree = (node, depth = 0) => {
    return Object.keys(node).sort((a, b) => {
      const aIsDir = typeof node[a] === "object";
      const bIsDir = typeof node[b] === "object";
      if (aIsDir !== bIsDir) return aIsDir ? -1 : 1;
      return a.localeCompare(b);
    }).map((key) => {
      const val = node[key];
      if (typeof val === "object") {
        return (
          <div key={key}>
            <div className="file-entry dir" style={{ paddingLeft: 8 + depth * 14, padding: "5px 8px 5px " + (8 + depth * 14) + "px" }}>
              <Icon name="folder" size={13} color="var(--amber)"/> <span>{key}</span>
            </div>
            {renderTree(val, depth + 1)}
          </div>
        );
      }
      const isSelected = selectedFile === val;
      return (
        <div key={val}
          className={"file-entry" + (isSelected ? " active" : "")}
          style={{ paddingLeft: 8 + depth * 14, padding: "5px 8px 5px " + (8 + depth * 14) + "px", cursor: "pointer",
            background: isSelected ? "var(--brand-dim, oklch(from var(--brand) l c h / 0.12))" : "transparent",
          }}
          onClick={() => openFile(val)}>
          <Icon name="file" size={13}/> <span className="mono" style={{ fontSize: 12 }}>{key}</span>
        </div>
      );
    });
  };

  const tree = buildTree(files);

  return (
    <div style={{ display: "grid", gridTemplateColumns: "240px 1fr", gap: 14, minHeight: 400 }}>
      <div className="panel" style={{ overflow: "auto" }}>
        <div className="panel-head">
          <h3>Files</h3>
          <button className="btn sm ghost right" onClick={loadFiles} title="Refresh"><Icon name="refresh" size={12}/></button>
        </div>
        <div className="panel-body" style={{ padding: 0 }}>
          {loading ? (
            <div className="dim" style={{ padding: 16, textAlign: "center" }}>Loading…</div>
          ) : files.length === 0 ? (
            <div className="dim" style={{ padding: 16, textAlign: "center" }}>
              {error ? error : "No files found. Container may not be running."}
            </div>
          ) : (
            <div className="file-tree" style={{ fontSize: 12.5, lineHeight: 1.6 }}>
              {renderTree(tree)}
            </div>
          )}
        </div>
      </div>

      <div className="panel" style={{ display: "flex", flexDirection: "column" }}>
        <div className="panel-head">
          <h3>{selectedFile ? selectedFile : "Select a file"}</h3>
          <div className="right row gap-6">
            {saveMsg && <span style={{ color: "var(--brand)", fontSize: 12 }}>{saveMsg}</span>}
            {error && selectedFile && <span style={{ color: "var(--rose)", fontSize: 12 }}>{error}</span>}
            <button className="btn sm" disabled={!hasChanges || saving} onClick={saveFile}
              style={{ opacity: hasChanges && !saving ? 1 : 0.5 }}>
              <Icon name="check" size={12}/> {saving ? "Saving…" : "Save"}
            </button>
          </div>
        </div>
        <div className="panel-body" style={{ flex: 1, padding: 0 }}>
          {selectedFile ? (
            <textarea
              className="file-editor"
              value={fileContent}
              onChange={(e) => setFileContent(e.target.value)}
              spellCheck={false}
              style={{
                width: "100%", height: "100%", minHeight: 360,
                fontFamily: "var(--mono, 'SF Mono', 'Fira Code', monospace)",
                fontSize: 12.5, lineHeight: 1.6,
                background: "var(--panel-2)", color: "var(--text)",
                border: 0, outline: "none", resize: "vertical",
                padding: 14, boxSizing: "border-box",
              }}
            />
          ) : (
            <div className="dim" style={{ padding: 40, textAlign: "center" }}>
              Select a file from the tree to view and edit it.
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function KeyPanel({ inst, showOpenAI, setShowOpenAI, showAnthropic, setShowAnthropic }) {
  const openaiKey = "sk-proj-a49Nc8sY3hQ7kLmP2vXpZrB1Dw9eTgH5jRfM6uNiOaQxW8yE";
  const anthropicKey = "sk-ant-api03-xQ7mR2nP8vLkJhG5fD3sA9zWwB1cYtUeIoNaP6kM3xZvQ2bT";
  return (
    <div className="col" style={{ gap: 14 }}>
      <div className="banner">
        <Icon name="key" size={14} color="var(--blue)"/>
        <div style={{ flex: 1 }}>
          Each instance has its own dedicated API keys. Keys are stored encrypted per instance and never shared across customers.
        </div>
      </div>
      <div className="grid-2">
        <ProviderKey
          provider="OpenAI"
          color="var(--brand)"
          active={inst.apiProvider === "openai"}
          keyVal={openaiKey}
          show={showOpenAI}
          toggleShow={() => setShowOpenAI(!showOpenAI)}
          usage={{ month: "€28.40", quota: 64, limit: "€75.00/mo" }}
        />
        <ProviderKey
          provider="Anthropic"
          color="var(--amber)"
          active={inst.apiProvider === "anthropic"}
          keyVal={anthropicKey}
          show={showAnthropic}
          toggleShow={() => setShowAnthropic(!showAnthropic)}
          usage={{ month: "€20.32", quota: 41, limit: "€50.00/mo" }}
        />
      </div>
      <div className="panel">
        <div className="panel-head"><h3>Rotation history</h3></div>
        <table className="table">
          <thead><tr><th>Date</th><th>Provider</th><th>Action</th><th>By</th></tr></thead>
          <tbody>
            <tr><td className="mono">2026-04-03 14:22</td><td>OpenAI</td><td>Rotated</td><td>kai@oprt.ai</td></tr>
            <tr><td className="mono">2026-03-14 09:11</td><td>Anthropic</td><td>Created</td><td>kai@oprt.ai</td></tr>
            <tr><td className="mono">2026-03-14 09:10</td><td>OpenAI</td><td>Created</td><td>kai@oprt.ai</td></tr>
          </tbody>
        </table>
      </div>
    </div>
  );
}

function ProviderKey({ provider, color, active, keyVal, show, toggleShow, usage }) {
  return (
    <div className="panel">
      <div className="panel-head">
        <div className="row gap-6">
          <span style={{ width: 10, height: 10, borderRadius: 3, background: color }}/>
          <h3>{provider}</h3>
          {active && <span className="pill active"><span className="dot"/>Primary</span>}
        </div>
        <div className="right row gap-6">
          <button className="btn sm"><Icon name="refresh" size={12}/> Rotate</button>
        </div>
      </div>
      <div className="panel-body col" style={{ gap: 14 }}>
        <div className="col" style={{ gap: 6 }}>
          <div className="label">API key</div>
          <div className="secret">
            <span className="val">{show ? keyVal : keyVal.slice(0, 12) + "•".repeat(36)}</span>
            <button className="btn sm ghost" onClick={toggleShow}><Icon name={show ? "eye-off" : "eye"} size={13}/></button>
            <button className="btn sm ghost"><Icon name="copy" size={13}/></button>
          </div>
          <div className="hint">Scoped to this instance. Last used 2 min ago.</div>
        </div>
        <div>
          <div className="row" style={{ justifyContent: "space-between", marginBottom: 6 }}>
            <span className="dim" style={{ fontSize: 12 }}>Usage this month</span>
            <span className="mono" style={{ fontWeight: 600 }}>{usage.month} <span className="dim">/ {usage.limit}</span></span>
          </div>
          <div className="bar"><span style={{ width: usage.quota + "%", background: color }}/></div>
        </div>
      </div>
    </div>
  );
}

function MessagesStub() {
  return (
    <div className="panel">
      <div className="panel-head"><h3>Messages</h3><span className="sub">· live inbox</span></div>
      <div className="panel-body col" style={{ gap: 10 }}>
        {[
          { from: "+49 176 •••• 412", t: "2m", msg: "Kann ich morgen früher kommen?", bot: "Ja, verschoben auf 09:30.", tokens: 184 },
          { from: "info@heiztec.ch", t: "18m", msg: "Rechnung noch offen?", bot: "Rechnung #2941 wurde am 14.04. bezahlt.", tokens: 212 },
          { from: "@feldmann", t: "1h", msg: "Neue Hausverwaltung aufnehmen", bot: "Formular versendet an feldmann@…", tokens: 298 },
          { from: "+43 660 •••• 201", t: "3h", msg: "Öffnungszeiten?", bot: "Mo–Fr 08–17, Sa 09–12.", tokens: 84 },
        ].map((m, i) => (
          <div key={i} className="col" style={{ gap: 4, padding: "10px 12px", border: "1px solid var(--border)", borderRadius: 8, background: "var(--panel-2)" }}>
            <div className="row" style={{ justifyContent: "space-between" }}>
              <span className="mono" style={{ fontSize: 12 }}>{m.from}</span>
              <span className="dim mono" style={{ fontSize: 11 }}>{m.t} ago · {m.tokens} tokens</span>
            </div>
            <div style={{ fontSize: 13 }}>{m.msg}</div>
            <div style={{ fontSize: 12.5, color: "var(--text-dim)", paddingLeft: 12, borderLeft: "2px solid var(--brand)" }}>{m.bot}</div>
          </div>
        ))}
      </div>
    </div>
  );
}
function BillingInline({ inst }) {
  return (
    <div className="panel">
      <div className="panel-head"><h3>Billing</h3></div>
      <div className="panel-body col" style={{ gap: 10 }}>
        <div className="kv">
          <div className="k">Plan</div><div className="v">{inst.plan}</div>
          <div className="k">Billing cycle</div><div className="v">Monthly</div>
          <div className="k">Next invoice</div><div className="v mono">2026-05-01 · €{(inst.cost + 49).toFixed(2)}</div>
          <div className="k">Payment</div><div className="v mono">SEPA · DE** **** **** 2194</div>
        </div>
      </div>
    </div>
  );
}
function LogsStub({ inst }) {
  const lines = [
    "[2026-04-21 14:02:18] INFO  telegram.in  msg=412 tokens=184",
    "[2026-04-21 14:02:19] INFO  llm.call     provider=" + inst.apiProvider + " model=" + inst.model + " in=1,204 out=312",
    "[2026-04-21 14:02:20] INFO  skill.run    name=oprt-calendar ok dur=420ms",
    "[2026-04-21 14:02:21] INFO  telegram.out msg=413 reply_to=412",
    "[2026-04-21 13:58:04] WARN  llm.retry    attempt=2 reason=rate_limit",
    "[2026-04-21 13:58:06] INFO  llm.ok       attempt=2",
    "[2026-04-21 13:41:22] INFO  skill.run    name=oprt-gmail ok dur=812ms",
  ];
  return (
    <div className="panel">
      <div className="panel-head"><h3>Logs</h3><span className="sub">· tail -f</span></div>
      <div className="panel-body mono" style={{ fontSize: 12, lineHeight: 1.7, background: "var(--panel-2)", borderRadius: 8, padding: 14, color: "var(--text-dim)" }}>
        {lines.map((l, i) => <div key={i}>{l}</div>)}
      </div>
    </div>
  );
}
function SettingsStub({ inst }) {
  return (
    <div className="col" style={{ gap: 14 }}>
      <div className="panel">
        <div className="panel-head"><h3>Instance settings</h3></div>
        <div className="panel-body col" style={{ gap: 12 }}>
          <div className="form-row"><label className="label">Display name</label><input className="input" defaultValue={inst.name}/></div>
          <div className="form-row"><label className="label">Agent ID</label><input className="input mono" defaultValue={inst.id} disabled/></div>
          <div className="form-row"><label className="label">System prompt override</label><textarea className="input" rows={4} placeholder="Leave empty to use skill defaults"/></div>
        </div>
      </div>
      <div className="panel" style={{ borderColor: "oklch(from var(--rose) l c h / 0.35)" }}>
        <div className="panel-head"><h3 style={{ color: "var(--rose)" }}>Danger zone</h3></div>
        <div className="panel-body row" style={{ gap: 10 }}>
          <button className="btn">Pause instance</button>
          <button className="btn">Archive</button>
          <button className="btn danger">Delete permanently</button>
        </div>
      </div>
    </div>
  );
}

window.InstanceDetail = InstanceDetail;
