"use client";

import {
  ArrowClockwiseIcon,
  BrainIcon,
  CheckCircleIcon,
  DatabaseIcon,
  FloppyDiskIcon,
  ImageIcon,
  KeyIcon,
  PencilSimpleIcon,
  PlugIcon,
  PlusIcon,
  RobotIcon,
  TrashIcon,
  WarningCircleIcon,
  XIcon,
} from "@phosphor-icons/react";
import { useEffect, useMemo, useState } from "react";

import type {
  ModelCapability,
  ModelCategory,
  ModelPoolItem,
  SettingField,
  SettingsReadiness,
  SettingsResponse,
  TestResult,
} from "@/types/settings";

const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8000";

const testLabels: Record<string, string> = {
  infrastructure: "测试数据库与队列",
  storage: "测试 MinIO",
  baidu_ocr: "测试百度 OCR",
  gpu: "测试 GPU Worker",
  langfuse: "测试 Langfuse",
  sentry: "测试 Sentry",
};

const capabilityLabels: Record<ModelCapability, string> = {
  orchestration: "总调度",
  spatial_understanding: "空间理解",
  image_generation: "图像生成",
  image_editing: "局部编辑",
};

const providerLabels: Record<string, string> = {
  lingke: "聚合引擎 AIGC",
  openai: "OpenAI 官方",
  custom: "其他兼容接口",
};

type SettingsCenterProps = {
  open: boolean;
  onClose: () => void;
  onReadinessChange: (readiness: SettingsReadiness) => void;
};

function isVisible(field: SettingField, draft: Record<string, unknown>) {
  if (!field.visible_when) return true;
  return Object.entries(field.visible_when).every(([key, expected]) => {
    if (key.endsWith("__not")) return draft[key.slice(0, -5)] !== expected;
    return draft[key] === expected;
  });
}

function getErrorMessage(error: unknown) {
  return error instanceof Error ? error.message : "请求失败，请检查 API 服务是否启动。";
}

async function responseError(response: Response, fallback: string) {
  try {
    const payload = await response.json() as { detail?: string | { message?: string } };
    if (typeof payload.detail === "string") return payload.detail;
    if (payload.detail?.message) return payload.detail.message;
  } catch {
    // Use the readable fallback below when an upstream proxy returns non-JSON content.
  }
  return fallback;
}

function modelPoolFrom(draft: Record<string, unknown>): ModelPoolItem[] {
  return Array.isArray(draft.model_pool) ? draft.model_pool as ModelPoolItem[] : [];
}

function modelCategoryReady(data: SettingsResponse) {
  return ![...data.readiness.missing, ...data.readiness.untested]
    .some((message) => message.startsWith("AI 模型："));
}

export function SettingsCenter({ open, onClose, onReadinessChange }: SettingsCenterProps) {
  const [data, setData] = useState<SettingsResponse | null>(null);
  const [draft, setDraft] = useState<Record<string, unknown>>({});
  const [activeCategoryId, setActiveCategoryId] = useState("deployment");
  const [showAdvanced, setShowAdvanced] = useState(false);
  const [busy, setBusy] = useState<string | null>(null);
  const [notice, setNotice] = useState<{ tone: "success" | "error"; text: string } | null>(null);
  const [testResults, setTestResults] = useState<Record<string, TestResult>>({});

  const activeCategory = useMemo(
    () => data?.categories.find((category) => category.id === activeCategoryId) ?? data?.categories[0],
    [activeCategoryId, data],
  );

  function applyResponse(response: SettingsResponse) {
    setData(response);
    setDraft(response.values);
    onReadinessChange(response.readiness);
  }

  async function loadSettings() {
    setBusy("load");
    try {
      const response = await fetch(`${API_BASE}/v1/settings`, { cache: "no-store" });
      if (!response.ok) throw new Error("系统设置读取失败，请确认后端 API 已启动。");
      applyResponse(await response.json() as SettingsResponse);
    } finally {
      setBusy(null);
    }
  }

  useEffect(() => {
    if (!open) return;
    let cancelled = false;
    fetch(`${API_BASE}/v1/settings`, { cache: "no-store" })
      .then((response) => {
        if (!response.ok) throw new Error("系统设置读取失败，请确认后端 API 已启动。");
        return response.json() as Promise<SettingsResponse>;
      })
      .then((response) => {
        if (cancelled) return;
        setData(response);
        setDraft(response.values);
        onReadinessChange(response.readiness);
      })
      .catch((error: unknown) => {
        if (!cancelled) setNotice({ tone: "error", text: getErrorMessage(error) });
      });
    return () => { cancelled = true; };
  }, [open, onReadinessChange]);

  function updateField(key: string, value: unknown) {
    setDraft((current) => ({ ...current, [key]: value }));
    setNotice(null);
  }

  async function saveSettings(showSuccess = true) {
    setBusy("save");
    setNotice(null);
    try {
      const response = await fetch(`${API_BASE}/v1/settings`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ values: draft }),
      });
      if (!response.ok) throw new Error(await responseError(response, "保存失败，请检查填写内容。"));
      const payload = await response.json() as SettingsResponse;
      applyResponse(payload);
      if (showSuccess) setNotice({ tone: "success", text: "设置已加密保存。" });
      return payload;
    } catch (error) {
      setNotice({ tone: "error", text: getErrorMessage(error) });
      throw error;
    } finally {
      setBusy(null);
    }
  }

  async function testTarget(target: string) {
    setBusy(target);
    setNotice(null);
    try {
      await saveSettings(false);
      setBusy(target);
      const response = await fetch(`${API_BASE}/v1/settings/test`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ target, values: {} }),
      });
      const result = await response.json() as TestResult;
      setTestResults((current) => ({ ...current, [target]: result }));
      await loadSettings();
      setNotice({ tone: result.ok ? "success" : "error", text: result.message });
    } catch (error) {
      setNotice({ tone: "error", text: getErrorMessage(error) });
    } finally {
      setBusy(null);
    }
  }

  async function testModel(modelId: string) {
    const target = `model:${modelId}`;
    setBusy(target);
    setNotice(null);
    try {
      await saveSettings(false);
      setBusy(target);
      const response = await fetch(`${API_BASE}/v1/settings/models/${encodeURIComponent(modelId)}/test`, {
        method: "POST",
      });
      const result = await response.json() as TestResult;
      setTestResults((current) => ({ ...current, [target]: result }));
      await loadSettings();
      setNotice({ tone: result.ok ? "success" : "error", text: result.message });
    } catch (error) {
      setNotice({ tone: "error", text: getErrorMessage(error) });
    } finally {
      setBusy(null);
    }
  }

  async function generateFor(field: SettingField) {
    if (!field.generator) return;
    setBusy(field.key);
    try {
      const response = await fetch(`${API_BASE}/v1/settings/generate-secret`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ kind: field.generator }),
      });
      if (!response.ok) throw new Error("密钥生成失败。");
      const payload = await response.json() as { value: string };
      updateField(field.key, payload.value);
      setNotice({ tone: "success", text: `${field.label}已生成，点击保存后会加密存储。` });
    } catch (error) {
      setNotice({ tone: "error", text: getErrorMessage(error) });
    } finally {
      setBusy(null);
    }
  }

  function closeSafely() {
    if (data) {
      const secretKeys = new Set(data.categories.flatMap((category) => category.fields)
        .filter((field) => field.secret)
        .map((field) => field.key));
      setDraft((current) => Object.fromEntries(
        Object.entries(current).filter(([key]) => !secretKeys.has(key)),
      ));
    }
    onClose();
  }

  if (!open) return null;

  return (
    <div className="settings-backdrop" role="presentation">
      <section className="settings-dialog" role="dialog" aria-modal="true" aria-label="系统设置">
        <header className="settings-header">
          <div>
            <p className="settings-kicker">首次使用向导</p>
            <h1>系统设置</h1>
            <p>按服务分类配置并逐项测试。所有 API Key 都由后端加密保存。</p>
          </div>
          <button className="icon-button" type="button" onClick={closeSafely} aria-label="关闭系统设置">
            <XIcon size={18} />
          </button>
        </header>

        {data ? (
          <div className="settings-readiness">
            <div className={`readiness-orb ${data.readiness.ready ? "ready" : ""}`}>
              {data.readiness.ready ? <CheckCircleIcon size={22} weight="fill" /> : <DatabaseIcon size={22} />}
            </div>
            <div>
              <strong>{data.readiness.ready ? "工作流已就绪" : "完成必备配置后才能开始设计"}</strong>
              <p>{data.readiness.completed_required} / {data.readiness.total_required} 个必备分类已配置并测试</p>
            </div>
            <div className="readiness-meter" aria-label="配置完成度">
              <span style={{ width: `${(data.readiness.completed_required / data.readiness.total_required) * 100}%` }} />
            </div>
          </div>
        ) : null}

        <div className="settings-layout">
          <nav className="settings-nav" aria-label="设置分类">
            {data?.categories.map((category) => {
              const categoryTested = category.id === "models"
                ? modelCategoryReady(data)
                : category.test_targets.length === 0 || category.test_targets.every((target) => data.tests[target]?.ok);
              return (
                <button
                  key={category.id}
                  type="button"
                  className={category.id === activeCategory?.id ? "active" : ""}
                  onClick={() => setActiveCategoryId(category.id)}
                >
                  <span>{category.label}</span>
                  {category.required_for_workflow ? (
                    <small className={categoryTested ? "done" : "required"}>
                      {categoryTested ? "已就绪" : "必备"}
                    </small>
                  ) : <small>可选</small>}
                </button>
              );
            })}
          </nav>

          <div className="settings-content">
            {busy === "load" && !data ? (
              <div className="settings-loading"><ArrowClockwiseIcon size={24} /> 正在读取设置</div>
            ) : activeCategory && data ? (
              <>
                <div className="settings-section-heading">
                  <div>
                    <h2>{activeCategory.label}</h2>
                    <p>{activeCategory.description}</p>
                  </div>
                  {activeCategory.id !== "models" && activeCategory.fields.some((field) => field.advanced) ? (
                    <label className="advanced-toggle">
                      <input
                        type="checkbox"
                        checked={showAdvanced}
                        onChange={(event) => setShowAdvanced(event.target.checked)}
                      />
                      高级设置
                    </label>
                  ) : null}
                </div>

                {activeCategory.id === "models" ? (
                  <ModelPoolPanel
                    draft={draft}
                    tests={{ ...data.tests, ...testResults }}
                    busy={busy}
                    onChange={updateField}
                    onTest={(modelId) => void testModel(modelId)}
                  />
                ) : (
                  <div className="settings-fields">
                    {activeCategory.fields.map((field) => {
                      if (!isVisible(field, draft) || (field.advanced && !showAdvanced)) return null;
                      return (
                        <SettingControl
                          key={field.key}
                          field={field}
                          value={draft[field.key]}
                          configured={Boolean(data.configured[field.key])}
                          onChange={(value) => updateField(field.key, value)}
                          onGenerate={() => void generateFor(field)}
                          busy={busy === field.key}
                        />
                      );
                    })}
                  </div>
                )}

                {activeCategory.id === "deployment" ? (
                  <div className="deployment-note">
                    <KeyIcon size={18} />
                    <p>数据库和 Redis 密码必须在服务启动前存在，因此不在这里修改。运行 <code>scripts/bootstrap.ps1</code> 时会自动安全生成。</p>
                  </div>
                ) : null}

                {activeCategory.id !== "models" ? (
                  <div className="settings-test-actions">
                    {activeCategory.test_targets.map((target) => {
                      const recorded = testResults[target] ?? (data.tests[target] as TestResult | undefined);
                      return (
                        <button
                          className="button button-secondary"
                          type="button"
                          key={target}
                          onClick={() => void testTarget(target)}
                          disabled={Boolean(busy)}
                        >
                          {busy === target ? <ArrowClockwiseIcon className="spin" size={16} /> : <PlugIcon size={16} />}
                          {testLabels[target] ?? "测试连接"}
                          {recorded?.ok ? <CheckCircleIcon size={15} weight="fill" /> : null}
                        </button>
                      );
                    })}
                  </div>
                ) : null}
              </>
            ) : null}
          </div>
        </div>

        <footer className="settings-footer">
          <div className={`settings-notice ${notice?.tone ?? ""}`}>
            {notice?.tone === "error" ? <WarningCircleIcon size={17} /> : null}
            {notice?.tone === "success" ? <CheckCircleIcon size={17} weight="fill" /> : null}
            <span>{notice?.text ?? "必备项完成并测试通过后，设计工作流会自动解锁。"}</span>
          </div>
          <div className="settings-footer-actions">
            <button className="button button-secondary" type="button" onClick={closeSafely}>稍后设置</button>
            <button
              className="button button-primary"
              type="button"
              onClick={() => void saveSettings()}
              disabled={Boolean(busy) || !data}
            >
              <FloppyDiskIcon size={16} /> 保存设置
            </button>
          </div>
        </footer>
      </section>
    </div>
  );
}

type ModelPoolPanelProps = {
  draft: Record<string, unknown>;
  tests: Record<string, { ok: boolean; message: string }>;
  busy: string | null;
  onChange: (key: string, value: unknown) => void;
  onTest: (modelId: string) => void;
};

function newModel(category: ModelCategory): ModelPoolItem {
  return {
    id: crypto.randomUUID(),
    name: "",
    model_id: "",
    category,
    provider: "lingke",
    base_url: "",
    api_key: "",
    capabilities: category === "language" ? ["orchestration"] : ["spatial_understanding"],
    models_path: "/models",
    chat_path: "/chat/completions",
    image_generation_path: "/images/generations",
    image_edit_path: "/images/edits",
    enabled: true,
    api_key_configured: false,
  };
}

function ModelPoolPanel({ draft, tests, busy, onChange, onTest }: ModelPoolPanelProps) {
  const pool = modelPoolFrom(draft);
  const [editor, setEditor] = useState<ModelPoolItem | null>(null);
  const [editorError, setEditorError] = useState("");
  const [showAdvanced, setShowAdvanced] = useState(false);

  const languageModels = pool.filter((item) => item.category === "language");
  const multimodalModels = pool.filter((item) => item.category === "multimodal");
  const spatialModels = multimodalModels.filter((item) => item.capabilities.includes("spatial_understanding"));
  const imageModels = multimodalModels.filter((item) => item.capabilities.includes("image_generation"));

  function replacePool(nextPool: ModelPoolItem[]) {
    onChange("model_pool", nextPool);
  }

  function saveEditor() {
    if (!editor) return;
    if (!editor.name.trim() || !editor.model_id.trim() || !editor.base_url.trim()) {
      setEditorError("请填写显示名称、模型 ID 和 API Base URL。");
      return;
    }
    if (!editor.api_key?.trim() && !editor.api_key_configured) {
      setEditorError("请填写 API Key。");
      return;
    }
    if (editor.category === "multimodal" && editor.capabilities.length === 0) {
      setEditorError("请至少选择一种多模态能力。");
      return;
    }
    const normalized = {
      ...editor,
      name: editor.name.trim(),
      model_id: editor.model_id.trim(),
      base_url: editor.base_url.trim(),
      capabilities: editor.category === "language" ? ["orchestration" as const] : editor.capabilities,
    };
    const exists = pool.some((item) => item.id === editor.id);
    replacePool(exists
      ? pool.map((item) => item.id === editor.id ? normalized : item)
      : [...pool, normalized]);
    setEditor(null);
    setEditorError("");
  }

  function removeModel(model: ModelPoolItem) {
    if (!window.confirm(`确定从模型池删除“${model.name}”吗？保存前仍可刷新页面撤销。`)) return;
    replacePool(pool.filter((item) => item.id !== model.id));
    if (draft.orchestrator_model_id === model.id) onChange("orchestrator_model_id", "");
    if (draft.spatial_model_id === model.id) onChange("spatial_model_id", "");
    if (draft.image_model_id === model.id) onChange("image_model_id", "");
  }

  function updateCapability(capability: ModelCapability, checked: boolean) {
    if (!editor) return;
    const next = checked
      ? [...new Set([...editor.capabilities, capability])]
      : editor.capabilities.filter((item) => item !== capability);
    setEditor({ ...editor, capabilities: next });
  }

  return (
    <div className="model-pool">
      <div className="model-pool-intro">
        <div>
          <strong>模型逐个验证，错误逐个定位</strong>
          <p>同一聚合平台可以添加多个模型，也可以为不同模型配置不同平台和密钥。</p>
        </div>
        <div className="model-pool-summary">
          <span>{languageModels.length} 个大语言模型</span>
          <span>{multimodalModels.length} 个多模态模型</span>
        </div>
      </div>

      {editor ? (
        <section className="model-editor" aria-label="模型配置编辑器">
          <div className="model-editor-heading">
            <div>
              <h3>{pool.some((item) => item.id === editor.id) ? "编辑模型" : "添加模型"}</h3>
              <p>测试会核对当前账号的模型列表，并准确指出哪个模型 ID 不可用。</p>
            </div>
            <button className="icon-button small" type="button" onClick={() => setEditor(null)} aria-label="关闭模型编辑器">
              <XIcon size={16} />
            </button>
          </div>

          <div className="model-editor-grid">
            <label className="model-input">
              <span>模型分类</span>
              <select
                value={editor.category}
                onChange={(event) => {
                  const category = event.target.value as ModelCategory;
                  setEditor({
                    ...editor,
                    category,
                    capabilities: category === "language" ? ["orchestration"] : ["spatial_understanding"],
                  });
                }}
              >
                <option value="language">大语言模型</option>
                <option value="multimodal">多模态模型</option>
              </select>
            </label>
            <label className="model-input">
              <span>显示名称</span>
              <input value={editor.name} placeholder="例如：主调度 GPT" onChange={(event) => setEditor({ ...editor, name: event.target.value })} />
            </label>
            <label className="model-input">
              <span>平台模型 ID</span>
              <input value={editor.model_id} placeholder="例如：gpt-image-2" onChange={(event) => setEditor({ ...editor, model_id: event.target.value })} />
            </label>
            <label className="model-input">
              <span>API 来源</span>
              <select value={editor.provider} onChange={(event) => setEditor({ ...editor, provider: event.target.value })}>
                <option value="lingke">聚合引擎 AIGC</option>
                <option value="openai">OpenAI 官方</option>
                <option value="custom">其他兼容接口</option>
              </select>
            </label>
            <label className="model-input model-input-wide">
              <span>API Base URL</span>
              <input value={editor.base_url} placeholder="https://example.com/v1" onChange={(event) => setEditor({ ...editor, base_url: event.target.value })} />
            </label>
            <label className="model-input model-input-wide">
              <span>API Key</span>
              <input
                type="password"
                value={editor.api_key ?? ""}
                placeholder={editor.api_key_configured ? "已安全保存，留空不修改" : "请输入该模型使用的 API Key"}
                autoComplete="off"
                onChange={(event) => setEditor({ ...editor, api_key: event.target.value })}
              />
            </label>
          </div>

          {editor.category === "multimodal" ? (
            <fieldset className="model-capabilities">
              <legend>模型能力</legend>
              {(["spatial_understanding", "image_generation", "image_editing"] as ModelCapability[]).map((capability) => (
                <label key={capability}>
                  <input
                    type="checkbox"
                    checked={editor.capabilities.includes(capability)}
                    onChange={(event) => updateCapability(capability, event.target.checked)}
                  />
                  {capabilityLabels[capability]}
                </label>
              ))}
            </fieldset>
          ) : null}

          <label className="model-enabled-row">
            <span><strong>启用模型</strong><small>停用后不会参与自动路由，也不能作为手动模型使用。</small></span>
            <input type="checkbox" checked={editor.enabled} onChange={(event) => setEditor({ ...editor, enabled: event.target.checked })} />
          </label>

          <button className="model-advanced-trigger" type="button" onClick={() => setShowAdvanced((current) => !current)}>
            {showAdvanced ? "收起接口路径" : "高级：接口路径"}
          </button>
          {showAdvanced ? (
            <div className="model-editor-grid model-path-grid">
              {([
                ["models_path", "模型列表路径"],
                ["chat_path", "对话路径"],
                ["image_generation_path", "生图路径"],
                ["image_edit_path", "图片编辑路径"],
              ] as const).map(([key, label]) => (
                <label className="model-input" key={key}>
                  <span>{label}</span>
                  <input value={editor[key]} onChange={(event) => setEditor({ ...editor, [key]: event.target.value })} />
                </label>
              ))}
            </div>
          ) : null}

          {editorError ? <p className="model-editor-error"><WarningCircleIcon size={15} /> {editorError}</p> : null}
          <div className="model-editor-actions">
            <button className="button button-secondary" type="button" onClick={() => setEditor(null)}>取消</button>
            <button className="button button-primary" type="button" onClick={saveEditor}>加入模型池</button>
          </div>
        </section>
      ) : null}

      <ModelGroup
        title="大语言模型"
        description="负责多轮追问、任务拆解、状态维护和模型调度。"
        category="language"
        models={languageModels}
        tests={tests}
        busy={busy}
        onAdd={() => { setEditor(newModel("language")); setShowAdvanced(false); }}
        onEdit={(model) => { setEditor({ ...model, api_key: "" }); setShowAdvanced(false); }}
        onRemove={removeModel}
        onTest={onTest}
      />
      <ModelGroup
        title="多模态模型"
        description="承担空间理解、风格评审、图像生成或局部编辑，可以同时具备多种能力。"
        category="multimodal"
        models={multimodalModels}
        tests={tests}
        busy={busy}
        onAdd={() => { setEditor(newModel("multimodal")); setShowAdvanced(false); }}
        onEdit={(model) => { setEditor({ ...model, api_key: "" }); setShowAdvanced(false); }}
        onRemove={removeModel}
        onTest={onTest}
      />

      <section className="model-routing">
        <div className="model-routing-heading">
          <RobotIcon size={19} />
          <div>
            <h3>工作流模型路由</h3>
            <p>总调度必须手动指定。空间理解和生图可以交给总调度自动选择，也可以固定模型。</p>
          </div>
        </div>

        <div className="routing-row">
          <div><strong>总调度模型</strong><p>只显示模型池中的大语言模型。</p></div>
          <select value={String(draft.orchestrator_model_id ?? "")} onChange={(event) => onChange("orchestrator_model_id", event.target.value)}>
            <option value="">请选择大语言模型</option>
            {languageModels.filter((item) => item.enabled).map((model) => (
              <option key={model.id} value={model.id}>{model.name} · {model.model_id}</option>
            ))}
          </select>
        </div>

        <RouteControl
          label="空间理解模型"
          description="分析户型、参考图、空间关系和审美一致性。"
          mode={String(draft.spatial_routing_mode ?? "auto")}
          selectedId={String(draft.spatial_model_id ?? "")}
          models={spatialModels}
          onModeChange={(value) => onChange("spatial_routing_mode", value)}
          onModelChange={(value) => onChange("spatial_model_id", value)}
        />
        <RouteControl
          label="生图模型"
          description="生成风格方向图、完整效果图和后续局部修改。"
          mode={String(draft.image_routing_mode ?? "auto")}
          selectedId={String(draft.image_model_id ?? "")}
          models={imageModels}
          onModeChange={(value) => onChange("image_routing_mode", value)}
          onModelChange={(value) => onChange("image_model_id", value)}
        />
      </section>
    </div>
  );
}

type ModelGroupProps = {
  title: string;
  description: string;
  category: ModelCategory;
  models: ModelPoolItem[];
  tests: Record<string, { ok: boolean; message: string }>;
  busy: string | null;
  onAdd: () => void;
  onEdit: (model: ModelPoolItem) => void;
  onRemove: (model: ModelPoolItem) => void;
  onTest: (modelId: string) => void;
};

function ModelGroup({ title, description, category, models, tests, busy, onAdd, onEdit, onRemove, onTest }: ModelGroupProps) {
  return (
    <section className="model-group">
      <div className="model-group-heading">
        <div className="model-group-icon">{category === "language" ? <BrainIcon size={18} /> : <ImageIcon size={18} />}</div>
        <div><h3>{title}</h3><p>{description}</p></div>
        <button className="button button-secondary compact" type="button" onClick={onAdd} disabled={Boolean(busy)}>
          <PlusIcon size={15} /> 添加模型
        </button>
      </div>

      {models.length === 0 ? (
        <button className="model-empty" type="button" onClick={onAdd}>
          <PlusIcon size={19} />
          <span><strong>还没有{title}</strong><small>点击添加第一个模型，并单独验证连通性。</small></span>
        </button>
      ) : (
        <div className="model-list">
          {models.map((model) => {
            const target = `model:${model.id}`;
            const result = tests[target];
            return (
              <article className={`model-row ${!model.enabled ? "disabled" : ""}`} key={model.id}>
                <div className={`model-state ${result?.ok ? "ok" : result ? "failed" : "untested"}`}>
                  {result?.ok ? <CheckCircleIcon size={18} weight="fill" /> : result ? <WarningCircleIcon size={18} /> : <PlugIcon size={17} />}
                </div>
                <div className="model-identity">
                  <div><strong>{model.name}</strong>{!model.enabled ? <small>已停用</small> : null}</div>
                  <code>{model.model_id}</code>
                  <span>{providerLabels[model.provider] ?? model.provider}</span>
                </div>
                <div className="model-capability-list">
                  {model.capabilities.map((capability) => <span key={capability}>{capabilityLabels[capability]}</span>)}
                </div>
                <div className="model-row-actions">
                  <button className="button button-secondary compact" type="button" onClick={() => onTest(model.id)} disabled={Boolean(busy) || !model.enabled}>
                    {busy === target ? <ArrowClockwiseIcon className="spin" size={14} /> : <PlugIcon size={14} />}
                    测试
                  </button>
                  <button className="icon-button small" type="button" onClick={() => onEdit(model)} disabled={Boolean(busy)} aria-label={`编辑${model.name}`}>
                    <PencilSimpleIcon size={15} />
                  </button>
                  <button className="icon-button small danger" type="button" onClick={() => onRemove(model)} disabled={Boolean(busy)} aria-label={`删除${model.name}`}>
                    <TrashIcon size={15} />
                  </button>
                </div>
                {result ? <p className={`model-test-message ${result.ok ? "ok" : "failed"}`}>{result.message}</p> : <p className="model-test-message">尚未测试这个模型。</p>}
              </article>
            );
          })}
        </div>
      )}
    </section>
  );
}

type RouteControlProps = {
  label: string;
  description: string;
  mode: string;
  selectedId: string;
  models: ModelPoolItem[];
  onModeChange: (value: string) => void;
  onModelChange: (value: string) => void;
};

function RouteControl({ label, description, mode, selectedId, models, onModeChange, onModelChange }: RouteControlProps) {
  return (
    <div className="routing-row routing-row-adaptive">
      <div><strong>{label}</strong><p>{description}</p></div>
      <select value={mode} onChange={(event) => onModeChange(event.target.value)} aria-label={`${label}路由方式`}>
        <option value="auto">总调度自动选择</option>
        <option value="manual">用户手动指定</option>
      </select>
      {mode === "manual" ? (
        <select value={selectedId} onChange={(event) => onModelChange(event.target.value)} aria-label={`选择${label}`}>
          <option value="">请选择模型</option>
          {models.filter((item) => item.enabled).map((model) => (
            <option key={model.id} value={model.id}>{model.name} · {model.model_id}</option>
          ))}
        </select>
      ) : <p className="routing-auto-note">仅从已启用且测试通过的候选模型中选择。</p>}
    </div>
  );
}

type SettingControlProps = {
  field: SettingField;
  value: unknown;
  configured: boolean;
  onChange: (value: unknown) => void;
  onGenerate: () => void;
  busy: boolean;
};

function SettingControl({ field, value, configured, onChange, onGenerate, busy }: SettingControlProps) {
  const selectedOption = field.options.find((option) => option.value === String(value ?? ""));

  if (field.kind === "status") {
    return (
      <div className="setting-status-row">
        <span className={configured ? "configured" : "missing"}>
          {configured ? <CheckCircleIcon size={18} weight="fill" /> : <WarningCircleIcon size={18} />}
        </span>
        <div><strong>{field.label}</strong><p>{field.description}</p></div>
        <small>{configured ? "已配置" : "缺失"}</small>
      </div>
    );
  }

  if (field.kind === "toggle") {
    return (
      <label className="setting-toggle-row">
        <div><strong>{field.label}</strong><p>{field.description}</p></div>
        <input type="checkbox" checked={Boolean(value)} onChange={(event) => onChange(event.target.checked)} />
      </label>
    );
  }

  return (
    <label className="setting-field">
      <span className="setting-field-label"><strong>{field.label}</strong>{field.required ? <small>必填</small> : null}</span>
      <span className="setting-description">{field.description}</span>
      <span className="setting-control-wrap">
        {field.kind === "select" ? (
          <select value={String(value ?? "")} onChange={(event) => onChange(event.target.value)}>
            <option value="" disabled>请选择</option>
            {field.options.map((option) => <option key={option.value} value={option.value}>{option.label}</option>)}
          </select>
        ) : (
          <>
            <input
              type={field.kind === "password" ? "password" : field.kind === "number" ? "number" : "text"}
              list={field.kind === "combobox" ? `options-${field.key}` : undefined}
              value={String(value ?? "")}
              placeholder={field.secret && configured ? "已安全保存，留空不修改" : field.placeholder}
              onChange={(event) => onChange(event.target.value)}
              autoComplete="off"
            />
            {field.kind === "combobox" ? (
              <datalist id={`options-${field.key}`}>
                {field.options.map((option) => <option key={option.value} value={option.value}>{option.label}</option>)}
              </datalist>
            ) : null}
          </>
        )}
        {field.generator ? (
          <button className="generate-button" type="button" onClick={onGenerate} disabled={busy}>
            <KeyIcon size={14} /> 一键生成
          </button>
        ) : null}
      </span>
      {selectedOption ? <span className="option-help">{selectedOption.help}</span> : null}
    </label>
  );
}
