<script>
  import { onMount } from "svelte";
  import { Tabs } from "bits-ui";
  import { api } from "../lib/api.js";
  import AppearanceSettings from "../lib/components/AppearanceSettings.svelte";
  import HealthChecks from "../lib/components/HealthChecks.svelte";
  import SubAgentDefinitions from "../lib/components/SubAgentDefinitions.svelte";

  let { notify } = $props();
  let tab = $state("appearance");
  let content = $state("");
  let original = $state("");
  let path = $state("");
  let loading = $state(true);
  let saving = $state(false);
  let cleaning = $state(false);
  let reloadStatus = $state(null);
  let diagnostics = $state([]);
  let revision = $state("");
  let pollTimer = null;

  const isConfig = $derived(tab === "config");
  const isAppearance = $derived(tab === "appearance");
  const isHealth = $derived(tab === "health");
  const isSubagents = $derived(tab === "subagents");
  const title = $derived(tab === "config" ? "运行配置" : tab === "user" ? "用户档案" : tab === "agents" ? "Agent 行为准则" : "页面外观");
  const isDirty = $derived(content !== original);

  const jsonParse = $derived.by(() => {
    if (!isConfig || !content.trim()) return { value: null, error: null };
    try { return { value: JSON.parse(content), error: null }; } catch (e) { return { value: null, error: e.message }; }
  });
  const jsonError = $derived(jsonParse.error);
  const outlineKeys = $derived(jsonParse.value ? Object.keys(jsonParse.value) : []);

  const phaseBadge = $derived.by(() => {
    if (!reloadStatus) return "ok";
    const map = { steady: "ok", pending: "run", preparing: "run", activating: "run", failed: "fail" };
    return map[reloadStatus.phase] || "ok";
  });

  async function load() {
    loading = true;
    if (isAppearance || isHealth || isSubagents) { loading = false; return; }
    try {
      if (isConfig) {
        const result = await api("/api/config");
        content = JSON.stringify(result.config, null, 2);
        original = content;
        path = result.path;
        diagnostics = result.diagnostics || [];
        revision = result.revision || "";
      } else {
        const result = await api(`/api/profiles/${tab}`);
        content = result.content;
        original = content;
        path = result.path;
      }
    } catch (caught) { notify(caught.message, true); }
    finally { loading = false; }
  }

  async function save() {
    if (isConfig && jsonError) return;
    saving = true;
    try {
      if (isConfig) {
        const config = JSON.parse(content);
        const result = await api("/api/config", { method: "PUT", body: JSON.stringify({ config }) });
        content = JSON.stringify(result.config, null, 2);
        original = content;
        diagnostics = result.diagnostics || [];
        revision = result.revision || revision;
        notify("配置已保存");
      } else {
        await api(`/api/profiles/${tab}`, { method: "PUT", body: JSON.stringify({ content }) });
        original = content;
        notify("助手档案已保存");
      }
    } catch (caught) { notify(caught.message, true); }
    finally { saving = false; }
  }

  async function saveAndReload() {
    if (jsonError) return;
    saving = true;
    try {
      const config = JSON.parse(content);
      const result = await api("/api/config", { method: "PUT", body: JSON.stringify({ config }) });
      content = JSON.stringify(result.config, null, 2);
      original = content;
      diagnostics = result.diagnostics || [];
      revision = result.revision || revision;
      const reload = await api("/api/config/reload", { method: "POST" });
      notify(reload.message || "配置已保存并触发热重载");
      pollReloadStatus();
    } catch (caught) { notify(caught.message, true); }
    finally { saving = false; }
  }

  function discard() { content = original; }

  async function cleanupInvalid() {
    if (isDirty || !revision || !diagnostics.length) return;
    cleaning = true;
    const count = diagnostics.length;
    try {
      const result = await api("/api/config/cleanup-invalid", {
        method: "POST",
        body: JSON.stringify({ revision })
      });
      content = JSON.stringify(result.config, null, 2);
      original = content;
      diagnostics = result.diagnostics || [];
      revision = result.revision || revision;
      notify(`已清除 ${count} 个无效配置项；请热重载以同步磁盘配置`);
    } catch (caught) { notify(caught.message, true); }
    finally { cleaning = false; }
  }

  async function pollReloadStatus() {
    try { reloadStatus = await api("/api/config/reload/status"); } catch {}
  }

  function startPolling() {
    stopPolling();
    pollReloadStatus();
    pollTimer = setInterval(pollReloadStatus, 3000);
  }

  function stopPolling() {
    if (pollTimer) { clearInterval(pollTimer); pollTimer = null; }
  }

  function changeTab(value) {
    tab = value;
    stopPolling();
    load();
    if (value === "config") startPolling();
  }

  onMount(() => {
    load();
    if (tab === "config") startPolling();
    return stopPolling;
  });
</script>

<section class="page active content-page">
  <div class="settings-grid">
    <Tabs.Root value={tab} onValueChange={changeTab} orientation="vertical">
      <Tabs.List class="settings-nav" aria-label="设置分类">
        <Tabs.Trigger value="appearance">外观</Tabs.Trigger><Tabs.Trigger value="config">config.json</Tabs.Trigger><Tabs.Trigger value="health">健康检查</Tabs.Trigger><Tabs.Trigger value="user">USER.md</Tabs.Trigger><Tabs.Trigger value="agents">AGENTS.md</Tabs.Trigger><Tabs.Trigger value="subagents">子代理</Tabs.Trigger>
      </Tabs.List>
    </Tabs.Root>

    {#if isAppearance}
      <AppearanceSettings />
    {:else if isHealth}
      <HealthChecks />
    {:else if isSubagents}
      <div class="subagents-pane">
        <SubAgentDefinitions {notify} />
      </div>
    {:else if isConfig}
      <div class="config-layout">
        <div class="editor-card">
          <div class="editor-head">
            <div><strong>{title}</strong><small>{path}</small></div>
            <div class="editor-actions">
              {#if isDirty}<span class="dirty-badge">未保存</span>{/if}
              <button class="secondary" onclick={discard} disabled={!isDirty || loading || saving}>放弃修改</button>
              <button class="secondary" onclick={saveAndReload} disabled={loading || saving || cleaning || !!jsonError}>保存并热重载</button>
              <button class="primary" onclick={save} disabled={loading || saving || cleaning || !!jsonError}>保存</button>
            </div>
          </div>
          <textarea bind:value={content} spellcheck="false" disabled={loading}></textarea>
          {#if jsonError}<div class="json-error">JSON 格式错误：{jsonError}</div>{/if}
          <div class="notice">API Key 等敏感字段显示为 <code>********</code>，保持不变即可保留原值。</div>
        </div>

        <aside class="config-sidebar">
          <div class="panel sidebar-panel">
            <span class="label-caps">配置大纲</span>
            {#if outlineKeys.length}
              <ul class="outline-list">
                {#each outlineKeys as key}
                  <li>
                    <span class="mono">{key}</span>
                    {#if key === "gateway"}<span class="outline-note">⚠ 含重启字段</span>{:else if key === "providers"}<span class="outline-note">🔑 含密钥</span>{/if}
                  </li>
                {/each}
              </ul>
            {:else}
              <p class="sidebar-empty">{jsonError ? "JSON 无效" : "暂无内容"}</p>
            {/if}
          </div>

          <div class="panel sidebar-panel">
            <div class="diagnostic-head">
              <span class="label-caps">无效配置项</span>
              {#if diagnostics.length}<span class="badge fail">{diagnostics.length}</span>{/if}
            </div>
            {#if diagnostics.length}
              <ul class="diagnostic-list">
                {#each diagnostics as diagnostic}
                  <li>
                    <code>{diagnostic.path}</code>
                    <span>{diagnostic.reason}</span>
                  </li>
                {/each}
              </ul>
              <button
                class="secondary cleanup-button"
                onclick={cleanupInvalid}
                disabled={isDirty || loading || saving || cleaning}
                title={isDirty ? "请先保存或放弃编辑器中的修改" : "从 config.json 删除所有已被运行时忽略的配置项"}
              >{cleaning ? "清理中…" : "一键清除"}</button>
              {#if isDirty}<p class="cleanup-hint">存在未保存修改，暂不能清理。</p>{/if}
            {:else}
              <p class="sidebar-empty">未发现被忽略的配置项</p>
            {/if}
          </div>

          <div class="panel sidebar-panel">
            <span class="label-caps">热重载状态</span>
            {#if reloadStatus}
              <div class="reload-row"><span>Generation</span><span class="mono">{reloadStatus.generation}</span></div>
              <div class="reload-row"><span>Phase</span><span class="badge {phaseBadge}">{reloadStatus.phase}</span></div>
              {#if reloadStatus.last_error}<div class="reload-error">{reloadStatus.last_error}</div>{/if}
            {:else}
              <p class="sidebar-empty">加载中…</p>
            {/if}
          </div>
        </aside>
      </div>
    {:else}
      <div class="editor-card">
        <div class="editor-head">
          <div><strong>{title}</strong><small>{path}</small></div>
          <div class="editor-actions">
            {#if isDirty}<span class="dirty-badge">未保存</span>{/if}
            <button class="primary" onclick={save} disabled={loading || saving}>保存更改</button>
          </div>
        </div>
        <textarea bind:value={content} spellcheck="false" disabled={loading}></textarea>
        <div class="notice">Markdown 内容会在后续新会话和上下文构建中供 PicoBot 使用。</div>
      </div>
    {/if}
  </div>
</section>

<style>
  .subagents-pane { min-width: 0; }
  .config-layout { display: grid; grid-template-columns: minmax(0, 1fr) 230px; gap: 18px; align-items: start; }
  .config-sidebar { display: grid; gap: 14px; }
  .sidebar-panel { padding: 14px; }
  .sidebar-empty { margin: 10px 0 0; color: var(--muted); font-size: 12px; }
  .outline-list { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 7px; }
  .outline-list li { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13px; color: var(--text-soft); }
  .outline-note { font-size: 11px; color: var(--muted); white-space: nowrap; }
  .diagnostic-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
  .diagnostic-list { list-style: none; margin: 10px 0 12px; padding: 0; display: grid; gap: 9px; max-height: 280px; overflow: auto; }
  .diagnostic-list li { display: grid; gap: 3px; padding-bottom: 9px; border-bottom: 1px solid var(--line); }
  .diagnostic-list code { overflow-wrap: anywhere; color: var(--danger); font-size: 11px; }
  .diagnostic-list span { color: var(--text-soft); font-size: 12px; line-height: 1.45; }
  .cleanup-button { width: 100%; justify-content: center; }
  .cleanup-hint { margin: 7px 0 0; color: var(--muted); font-size: 11px; }
  .reload-row { display: flex; justify-content: space-between; align-items: center; padding: 7px 0; font-size: 13px; color: var(--text-soft); }
  .reload-row + .reload-row { border-top: 1px solid var(--line); }
  .reload-error { margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: var(--danger-soft); color: var(--danger); font-size: 12px; line-height: 1.5; }
  .json-error { padding: 9px 15px; color: var(--danger); font-size: 12px; background: var(--danger-soft); border-top: 1px solid var(--danger-border); }
  .dirty-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 600; color: var(--accent); background: var(--accent-soft); border: 1px solid var(--accent-border); border-radius: 4px; padding: 3px 8px; white-space: nowrap; }
  .dirty-badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
  .editor-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
  .editor-head { min-height: 62px; height: auto; padding: 10px 15px; flex-wrap: wrap; gap: 8px; }
  @media (max-width: 800px) { .config-layout { grid-template-columns: 1fr; } }
</style>
