"use client";

import {
  Boxes,
  Brain,
  Check,
  Copy,
  MessageSquareText,
  MoreHorizontal,
  Pencil,
  Plus,
  Rocket,
  Sparkles,
  Trash2,
  Workflow,
  ChevronLeft,
  ChevronUp,
  ChevronDown,
  Save,
  Terminal,
  Loader2,
} from "lucide-react";

import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { TurnConfigEditor } from "@/components/turn-config-editor";
import { Input } from "@/components/ui/input";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { DataList } from "@/components/ui/data-list";
import { PageHeader } from "@/components/ui/page-header";
import { FilterPills } from "@/components/ui/filter-pills";
import { SearchInput } from "@/components/ui/search-input";
import { ListToolbar } from "@/components/ui/list-toolbar";
import { useCallback, useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import {
  assistantsApi,
  knowledgeBasesApi,
  modelResourcesApi,
  toolsApi,
  type Assistant,
  type AssistantType as ApiAssistantType,
  type AssistantUpsert,
  type KnowledgeBase,
  type KnowledgeRetrievalConfig,
  type ModelResource,
  type Tool,
  type TurnConfig,
} from "@/lib/api";
import type { WorkflowSettings } from "@/components/workflow/types";
import { SectionCard } from "@/components/editor/section-card";
import {
  defaultGraph,
  workflowUsesVision,
  type WorkflowGraph,
} from "@/components/workflow/specs";
import {
  defaultTurnConfig,
  normalizeTurnConfig,
} from "@/lib/turn-config";
import {
  activeDynamicVariableDefinitions,
  activeWorkflowDynamicVariableDefinitions,
} from "@/components/assistant-editor/dynamic-variables";
import { useWorkflowEditorState } from "@/components/assistant-editor/use-workflow-editor-state";
import { DebugDrawer } from "@/components/assistant-editor/debug-preview";
import {
  AssistantIdentity,
  EditableTitle,
  EditorBackButton,
  ResourceSelectField,
  TextAreaField,
  ToggleRow,
} from "@/components/assistant-editor/editor-controls";
import type { AssistantForm } from "@/components/assistant-editor/types";
import { PromptEditor } from "@/components/assistant-editor/prompt-editor";
import { WorkflowPage } from "@/components/assistant-editor/workflow-page";

type AgentPlatform = "dify" | "fastgpt";

type AgentPlatformForm = {
  name: string;
  platform: AgentPlatform;
  agent: string;
  asr: string;
  voice: string;
  enableInterrupt: boolean;
  turnConfig: TurnConfig;
};

type OpenCodeForm = {
  name: string;
  prompt: string;
  agent: string;
  model: string;
  asr: string;
  voice: string;
  enableInterrupt: boolean;
  turnConfig: TurnConfig;
  visionEnabled: boolean;
  visionModelResourceId: string;
};

type AssistantType = "提示词" | "工作流" | "Dify" | "FastGPT" | "OpenCode";
type BuildMethod = "提示词" | "工作流" | "智能体平台" | "OpenCode";

const assistantTypes: AssistantType[] = [
  "提示词",
  "工作流",
  "Dify",
  "FastGPT",
  "OpenCode",
];

function defaultKnowledgeRetrievalConfig(): KnowledgeRetrievalConfig {
  return {
    mode: "automatic",
    topN: 5,
    scoreThreshold: 0,
  };
}

// 后端 type(英文) ↔ 列表展示标签(中文)
const typeToLabel: Record<ApiAssistantType, AssistantType> = {
  prompt: "提示词",
  workflow: "工作流",
  dify: "Dify",
  fastgpt: "FastGPT",
  opencode: "OpenCode",
};
const typeFromBuildMethod: Record<
  Exclude<BuildMethod, "智能体平台">,
  ApiAssistantType
> = {
  提示词: "prompt",
  工作流: "workflow",
  OpenCode: "opencode",
};

// 后端 type → 编辑器视图(工作流暂为占位页)
const typeToView = {
  prompt: "create",
  dify: "create-agent-platform",
  fastgpt: "create-agent-platform",
  opencode: "create-opencode",
  workflow: "workflow",
} as const;

type View = "list" | "choose" | "loading" | (typeof typeToView)[ApiAssistantType];

// 路由驱动的页面模式:
// /assistants → list | /assistants/new → choose(引导,确认即建库) | /assistants/[id] → edit
export type AssistantPageProps =
  | { mode: "list" }
  | { mode: "choose" }
  | { mode: "edit"; assistantId: string };

// 各类型的空白表单模板(新建用)
function blankPromptForm(name: string): AssistantForm {
  return {
    name,
    greeting: "",
    prompt: "",
    dynamicVariableDefinitions: {},
    runtimeMode: "pipeline",
    realtimeModel: "",
    model: "",
    asr: "",
    voice: "",
    knowledgeBase: "",
    knowledgeRetrievalConfig: defaultKnowledgeRetrievalConfig(),
    enableInterrupt: true,
    turnConfig: defaultTurnConfig(),
    visionEnabled: false,
    visionModelResourceId: "",
    toolIds: [],
  };
}

function blankAgentPlatformForm(name: string): AgentPlatformForm {
  return {
    name,
    platform: "dify",
    agent: "",
    asr: "",
    voice: "",
    enableInterrupt: true,
    turnConfig: defaultTurnConfig(),
  };
}

function blankOpenCodeForm(name: string): OpenCodeForm {
  return {
    name,
    prompt: "",
    agent: "",
    model: "",
    asr: "",
    voice: "",
    enableInterrupt: true,
    turnConfig: defaultTurnConfig(),
    visionEnabled: false,
    visionModelResourceId: "",
  };
}
function formatTimestamp(iso?: string | null): string {
  if (!iso) return "";
  const d = new Date(iso);
  if (Number.isNaN(d.getTime())) return "";
  const pad = (n: number) => String(n).padStart(2, "0");
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(
    d.getHours(),
  )}:${pad(d.getMinutes())}`;
}

type AssistantTypeOption = {
  type: BuildMethod;
  label: string;
  description: string;
  icon: React.ReactNode;
  /** 提示词、工作流、智能体平台已落地；OpenCode 暂时显示即将上线 */
  available: boolean;
};

const assistantTypeOptions: AssistantTypeOption[] = [
  {
    type: "提示词",
    label: "使用提示词构建",
    description: "通过提示词、模型与语音快速搭建对话助手，适合大多数场景。",
    icon: <MessageSquareText size={20} />,
    available: true,
  },
  {
    type: "工作流",
    label: "使用工作流构建",
    description: "用可视化编排串联多个节点，适合多步骤、带分支的复杂流程。",
    icon: <Workflow size={20} />,
    available: true,
  },
  {
    type: "智能体平台",
    label: "从智能体平台创建",
    description:
      "接入 Dify、FastGPT 等智能体平台，复用平台中的提示词、知识库和工作流配置。",
    icon: <Boxes size={20} />,
    available: true,
  },
  {
    type: "OpenCode",
    label: "使用 OpenCode 构建",
    description: "对接 OpenCode 服务，通过提示词驱动代码助手并支持实时语音对话。",
    icon: <Terminal size={20} />,
    available: false,
  },
];

type AssistantListItem = {
  id: string;
  name: string;
  type: AssistantType;
  updatedAt: string;
  /** 原始 ISO 时间戳,用于按时间排序(updatedAt 为展示用整形字符串) */
  updatedAtRaw: string | null | undefined;
};

type TypeFilter = "全部" | AssistantType;

const typeFilters: TypeFilter[] = ["全部", ...assistantTypes];

// 列表按更新时间排序:newest=最近更新在前(倒叙,默认) / oldest=最早更新在前
type SortOrder = "newest" | "oldest";

export function AssistantPage(props: AssistantPageProps) {
  const router = useRouter();
  // 编辑中的助手 id(来自路由)
  const editingId = props.mode === "edit" ? props.assistantId : null;

  const [form, setForm] = useState<AssistantForm>(() => blankPromptForm(""));
  const [agentPlatformForm, setAgentPlatformForm] =
    useState<AgentPlatformForm>(() =>
      blankAgentPlatformForm(""),
  );
  const [openCodeForm, setOpenCodeForm] = useState<OpenCodeForm>(() =>
    blankOpenCodeForm(""),
  );
  const [assistants, setAssistants] = useState<Assistant[]>([]);
  const [listLoading, setListLoading] = useState(true);
  const [listError, setListError] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);
  const [saveError, setSaveError] = useState<string | null>(null);
  // 编辑模式:加载指定 id 助手失败时的错误
  const [loadError, setLoadError] = useState<string | null>(null);
  // 编辑模式:后端返回的打码 API Key(用于编辑页展示"当前密钥")
  // 下拉数据源:模型资源 + 知识库
  const [modelResources, setModelResources] = useState<ModelResource[]>([]);
  const [knowledgeBases, setKnowledgeBases] = useState<KnowledgeBase[]>([]);
  const [tools, setTools] = useState<Tool[]>([]);
  // 视图由路由模式决定;仅编辑模式需要先 loading,等拿到助手类型后切换
  const [view, setView] = useState<View>(() => {
    if (props.mode === "choose") return "choose";
    if (props.mode === "edit") return "loading";
    return "list";
  });
  const [searchQuery, setSearchQuery] = useState("");
  const [typeFilter, setTypeFilter] = useState<TypeFilter>("全部");
  const [sortOrder, setSortOrder] = useState<SortOrder>("newest");
  const [currentPage, setCurrentPage] = useState(1);
  // choose 步骤的草稿：名称与已选类型，确认后直接建库并进入编辑页
  // (工作流占位页也用它展示名称与类型)
  const [draftName, setDraftName] = useState("");
  const [draftType, setDraftType] = useState<BuildMethod | null>(null);
  const [draftAgentPlatform, setDraftAgentPlatform] =
    useState<AgentPlatform | null>(null);
  // 引导页:创建请求进行中 / 创建失败
  const [creating, setCreating] = useState(false);
  const [createError, setCreateError] = useState<string | null>(null);
  // 已保存基线(当前类型表单的 JSON);与表单不一致时保存按钮才可点击
  const [savedSnapshot, setSavedSnapshot] = useState<string | null>(null);

  const {
    workflowName,
    setWorkflowName,
    workflowGraph,
    setWorkflowGraph,
    workflowSettings,
    setWorkflowSettings,
    workflowDynamicVariableDefinitions,
    setWorkflowDynamicVariableDefinitions,
    workflowDebugOpen,
    setWorkflowDebugOpen,
    workflowSettingsOpen,
    setWorkflowSettingsOpen,
    workflowEditingNodeId,
    setWorkflowEditingNodeId,
    workflowEditingEdgeId,
    setWorkflowEditingEdgeId,
    activeNodeId,
    setActiveNodeId,
    dynamicVariablesOpen,
    setDynamicVariablesOpen,
  } = useWorkflowEditorState();

  const effectiveDynamicVariableDefinitions = activeDynamicVariableDefinitions(
    [form.prompt, form.greeting],
    form.dynamicVariableDefinitions,
  );
  const effectiveWorkflowDynamicVariableDefinitions =
    activeWorkflowDynamicVariableDefinitions(
      workflowGraph,
      workflowDynamicVariableDefinitions,
    );

  const loadAssistants = useCallback(async () => {
    setListLoading(true);
    setListError(null);
    try {
      setAssistants(await assistantsApi.list());
    } catch (error) {
      setListError(error instanceof Error ? error.message : "加载失败");
    } finally {
      setListLoading(false);
    }
  }, []);

  useEffect(() => {
    // 列表页挂载时拉取助手列表(与后端同步)
    if (props.mode !== "list") return;
    // eslint-disable-next-line react-hooks/set-state-in-effect
    void loadAssistants();
  }, [props.mode, loadAssistants]);

  // 进入创建/编辑前加载下拉数据源(模型资源 + 知识库)
  const loadResources = useCallback(async () => {
    try {
      const [creds, kbs, toolRows] = await Promise.all([
        modelResourcesApi.list(),
        knowledgeBasesApi.list(),
        toolsApi.list(),
      ]);
      setModelResources(creds);
      setKnowledgeBases(kbs);
      setTools(toolRows);
    } catch {
      // 拉取失败时下拉为空,不阻塞表单
    }
  }, []);

  // 编辑页挂载时加载下拉数据源
  useEffect(() => {
    if (props.mode !== "edit") return;
    // eslint-disable-next-line react-hooks/set-state-in-effect
    void loadResources();
  }, [props.mode, loadResources]);

  // 按资源类型生成 {value:id, label:name} 选项
  const credOptions = (type: ModelResource["capability"]) =>
    modelResources
      .filter((c) => c.capability === type)
      .map((c) => ({ value: c.id, label: c.name }));
  const agentOptions = (interfaceType: "dify" | "fastgpt" | "opencode") =>
    modelResources
      .filter(
        (resource) =>
          resource.capability === "Agent" &&
          resource.interfaceType === interfaceType,
      )
      .map((resource) => ({ value: resource.id, label: resource.name }));
  const visionModelOptionsFor = (currentModelId: string) => modelResources
    .filter(
      (c) =>
        c.capability === "LLM" &&
        c.supportImageInput &&
        c.id !== currentModelId,
    )
    .map((c) => ({ value: c.id, label: c.name }));
  const kbOptions = knowledgeBases.map((k) => ({ value: k.id, label: k.name }));

  function handlePromptVisionEnabledChange(enabled: boolean) {
    updateForm("visionEnabled", enabled);
    if (!enabled) updateForm("visionModelResourceId", "");
  }

  function handlePromptModelChange(value: string) {
    updateForm("model", value);
    if (form.visionModelResourceId === value) {
      updateForm("visionModelResourceId", "");
    }
  }

  function handleOpenCodeVisionEnabledChange(enabled: boolean) {
    updateOpenCodeForm("visionEnabled", enabled);
    if (!enabled) updateOpenCodeForm("visionModelResourceId", "");
  }

  function handleOpenCodeModelChange(value: string) {
    updateOpenCodeForm("model", value);
    if (openCodeForm.visionModelResourceId === value) {
      updateOpenCodeForm("visionModelResourceId", "");
    }
  }

  function startCreate() {
    router.push("/assistants/new");
  }

  // 把后端 Assistant 回填进提示词表单(model/asr/voice 等存模型资源 id)
  // 返回回填后的表单,供调用方记录"已保存基线"
  function fillPromptForm(a: Assistant): AssistantForm {
    const next: AssistantForm = {
      name: a.name,
      greeting: a.greeting,
      prompt: a.prompt,
      dynamicVariableDefinitions: a.dynamicVariableDefinitions ?? {},
      runtimeMode: a.runtimeMode,
      realtimeModel: a.modelResourceIds.Realtime ?? "",
      model: a.modelResourceIds.LLM ?? "",
      asr: a.modelResourceIds.ASR ?? "",
      voice: a.modelResourceIds.TTS ?? "",
      knowledgeBase: a.knowledgeBaseId ?? "",
      knowledgeRetrievalConfig:
        a.knowledgeRetrievalConfig ?? defaultKnowledgeRetrievalConfig(),
      enableInterrupt: a.enableInterrupt,
      turnConfig: normalizeTurnConfig(a.turnConfig),
      visionEnabled: a.visionEnabled,
      visionModelResourceId: a.visionModelResourceId ?? "",
      toolIds: a.toolIds ?? [],
    };
    setForm(next);
    return next;
  }

  // 编辑：跳转到 /assistants/[id],由编辑页按助手类型回填表单
  function handleEdit(assistant: AssistantListItem) {
    router.push(`/assistants/${assistant.id}`);
  }

  // 引导页确认：直接创建到数据库拿到 id，再进入该助手的编辑页
  async function confirmType() {
    if (
      !draftName.trim() ||
      !draftType ||
      (draftType === "智能体平台" && !draftAgentPlatform) ||
      creating
    ) {
      return;
    }

    setCreating(true);
    setCreateError(null);
    try {
      let assistantType: ApiAssistantType;
      if (draftType === "智能体平台") {
        if (!draftAgentPlatform) return;
        assistantType = draftAgentPlatform;
      } else {
        assistantType = typeFromBuildMethod[draftType];
      }
      const created = await assistantsApi.create(
        baseUpsert({
          name: draftName.trim(),
          type: assistantType,
        }),
      );
      router.push(`/assistants/${created.id}`);
    } catch (error) {
      setCreateError(error instanceof Error ? error.message : "创建失败");
      setCreating(false);
    }
  }

  // 复制助手：服务端整行复制(含真 key,密钥不经浏览器)
  async function handleDuplicate(assistant: AssistantListItem) {
    try {
      await assistantsApi.duplicate(assistant.id);
      await loadAssistants();
    } catch (error) {
      setListError(error instanceof Error ? error.message : "复制失败");
    }
  }

  // 删除助手
  async function handleDelete(id: string) {
    try {
      await assistantsApi.remove(id);
      await loadAssistants();
    } catch (error) {
      setListError(error instanceof Error ? error.message : "删除失败");
    }
  }

  // 平铺字段的空白 upsert,各类型按需覆盖(后端会按 type 清掉无关字段)
  function baseUpsert(over: Partial<AssistantUpsert>): AssistantUpsert {
    return {
      name: "",
      type: "prompt",
      runtimeMode: "pipeline",
      greeting: "",
      enableInterrupt: true,
      turnConfig: defaultTurnConfig(),
      visionEnabled: false,
      visionModelResourceId: null,
      modelResourceIds: {},
      knowledgeBaseId: null,
      knowledgeRetrievalConfig: defaultKnowledgeRetrievalConfig(),
      toolIds: [],
      prompt: "",
      dynamicVariableDefinitions: {},
      apiUrl: "",
      apiKey: "",
      appId: "",
      graph: {},
      ...over,
    };
  }

  // 保存后停留在编辑页，并把当前表单记为已保存基线（按钮随之置灰）。
  async function save(payload: AssistantUpsert) {
    if (!editingId) return;
    setSaving(true);
    setSaveError(null);
    try {
      await assistantsApi.update(editingId, payload);
      if (view === "create") {
        setSavedSnapshot(JSON.stringify(form));
      } else if (view === "create-agent-platform") {
        const next = { ...agentPlatformForm };
        setAgentPlatformForm(next);
        setSavedSnapshot(JSON.stringify(next));
      } else if (view === "create-opencode") {
        const next = { ...openCodeForm };
        setOpenCodeForm(next);
        setSavedSnapshot(JSON.stringify(next));
      } else if (view === "workflow") {
        setSavedSnapshot(
          JSON.stringify({
            name: workflowName,
            graph: workflowGraph,
            settings: workflowSettings,
            dynamicVariableDefinitions: effectiveWorkflowDynamicVariableDefinitions,
          }),
        );
      }
    } catch (error) {
      setSaveError(error instanceof Error ? error.message : "保存失败");
    } finally {
      setSaving(false);
    }
  }

  function handleSavePrompt() {
    void save(
      baseUpsert({
        name: form.name.trim(),
        type: "prompt",
        runtimeMode: form.runtimeMode,
        greeting: form.greeting,
        enableInterrupt: form.enableInterrupt,
        turnConfig: form.turnConfig,
        visionEnabled: form.visionEnabled,
        visionModelResourceId: form.visionModelResourceId || null,
        modelResourceIds: {
          ...(form.model ? { LLM: form.model } : {}),
          ...(form.asr ? { ASR: form.asr } : {}),
          ...(form.voice ? { TTS: form.voice } : {}),
          ...(form.realtimeModel ? { Realtime: form.realtimeModel } : {}),
        },
        knowledgeBaseId: form.runtimeMode === "pipeline" ? form.knowledgeBase || null : null,
        knowledgeRetrievalConfig: form.knowledgeRetrievalConfig,
        toolIds: form.toolIds,
        prompt: form.prompt,
        dynamicVariableDefinitions: effectiveDynamicVariableDefinitions,
      }),
    );
  }

  // ---- 外部智能体平台（Dify / FastGPT）----
  function fillAgentPlatformForm(a: Assistant): AgentPlatformForm {
    const next: AgentPlatformForm = {
      name: a.name,
      platform: a.type === "fastgpt" ? "fastgpt" : "dify",
      agent: a.modelResourceIds.Agent ?? "",
      asr: a.modelResourceIds.ASR ?? "",
      voice: a.modelResourceIds.TTS ?? "",
      enableInterrupt: a.enableInterrupt,
      turnConfig: normalizeTurnConfig(a.turnConfig),
    };
    setAgentPlatformForm(next);
    return next;
  }

  function handleSaveAgentPlatform() {
    void save(
      baseUpsert({
        name: agentPlatformForm.name.trim(),
        type: agentPlatformForm.platform,
        enableInterrupt: agentPlatformForm.enableInterrupt,
        turnConfig: agentPlatformForm.turnConfig,
        modelResourceIds: {
          ...(agentPlatformForm.agent
            ? { Agent: agentPlatformForm.agent }
            : {}),
          ...(agentPlatformForm.asr ? { ASR: agentPlatformForm.asr } : {}),
          ...(agentPlatformForm.voice
            ? { TTS: agentPlatformForm.voice }
            : {}),
        },
      }),
    );
  }

  // ---- OpenCode ----
  function fillOpenCodeForm(a: Assistant): OpenCodeForm {
    const next: OpenCodeForm = {
      name: a.name,
      prompt: a.prompt,
      agent: a.modelResourceIds.Agent ?? "",
      model: a.modelResourceIds.LLM ?? "",
      asr: a.modelResourceIds.ASR ?? "",
      voice: a.modelResourceIds.TTS ?? "",
      enableInterrupt: a.enableInterrupt,
      turnConfig: normalizeTurnConfig(a.turnConfig),
      visionEnabled: a.visionEnabled,
      visionModelResourceId: a.visionModelResourceId ?? "",
    };
    setOpenCodeForm(next);
    return next;
  }

  // 编辑模式:按路由中的 id 拉取助手,回填对应类型的表单后再切换视图
  useEffect(() => {
    if (props.mode !== "edit" || !editingId) return;
    let cancelled = false;

    void (async () => {
      try {
        const assistant = await assistantsApi.get(editingId);
        if (cancelled) return;
        if (assistant.type === "prompt") {
          setSavedSnapshot(JSON.stringify(fillPromptForm(assistant)));
        } else if (
          assistant.type === "fastgpt" ||
          assistant.type === "dify"
        ) {
          setSavedSnapshot(JSON.stringify(fillAgentPlatformForm(assistant)));
        } else if (assistant.type === "opencode") {
          setSavedSnapshot(JSON.stringify(fillOpenCodeForm(assistant)));
        } else {
          // 工作流：回填名称与图(空图回落到默认 开始→智能体→结束)
          const graph =
            assistant.graph &&
            Array.isArray((assistant.graph as WorkflowGraph).nodes) &&
            (assistant.graph as WorkflowGraph).nodes.length > 0
              ? (assistant.graph as WorkflowGraph)
              : defaultGraph();
          const wfSettings: WorkflowSettings = {
            llm:
              graph.settings?.defaultLlmResourceId ||
              assistant.modelResourceIds.LLM,
            asr: graph.settings?.defaultAsrResourceId || assistant.modelResourceIds.ASR,
            tts: graph.settings?.defaultTtsResourceId || assistant.modelResourceIds.TTS,
            visionEnabled:
              graph.settings?.visionEnabled ?? assistant.visionEnabled,
            visionModelResourceId:
              graph.settings?.visionModelResourceId ??
              assistant.visionModelResourceId ??
              "",
            toolIds: graph.settings?.toolIds ?? [],
            knowledgeBaseId:
              graph.settings?.knowledgeBaseId || assistant.knowledgeBaseId || "",
            knowledgeRetrievalConfig: {
              mode:
                graph.settings?.knowledgeMode ||
                assistant.knowledgeRetrievalConfig.mode,
              topN:
                graph.settings?.knowledgeTopN ??
                assistant.knowledgeRetrievalConfig.topN,
              scoreThreshold:
                graph.settings?.knowledgeScoreThreshold ??
                assistant.knowledgeRetrievalConfig.scoreThreshold,
            },
            globalPrompt: graph.settings?.globalPrompt ?? "",
            allowInterrupt:
              graph.settings?.enableInterrupt ?? assistant.enableInterrupt,
            turnConfig: normalizeTurnConfig(
              graph.settings?.turnConfig ?? assistant.turnConfig,
            ),
          };
          setWorkflowName(assistant.name);
          setWorkflowGraph(graph);
          setWorkflowSettings(wfSettings);
          const dynamicVariableDefinitions =
            activeWorkflowDynamicVariableDefinitions(
              graph,
              assistant.dynamicVariableDefinitions ?? {},
            );
          setWorkflowDynamicVariableDefinitions(
            dynamicVariableDefinitions,
          );
          setSavedSnapshot(
            JSON.stringify({
              name: assistant.name,
              graph,
              settings: wfSettings,
              dynamicVariableDefinitions,
            }),
          );
        }
        setView(typeToView[assistant.type]);
      } catch (error) {
        if (!cancelled) {
          setLoadError(
            error instanceof Error ? error.message : "加载助手失败",
          );
        }
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [
    props.mode,
    editingId,
    setWorkflowDynamicVariableDefinitions,
    setWorkflowGraph,
    setWorkflowName,
    setWorkflowSettings,
  ]);

  function handleSaveOpenCode() {
    void save(
      baseUpsert({
        name: openCodeForm.name.trim(),
        type: "opencode",
        enableInterrupt: openCodeForm.enableInterrupt,
        turnConfig: openCodeForm.turnConfig,
        visionEnabled: openCodeForm.visionEnabled,
        visionModelResourceId: openCodeForm.visionModelResourceId || null,
        modelResourceIds: {
          ...(openCodeForm.agent ? { Agent: openCodeForm.agent } : {}),
          ...(openCodeForm.model ? { LLM: openCodeForm.model } : {}),
          ...(openCodeForm.asr ? { ASR: openCodeForm.asr } : {}),
          ...(openCodeForm.voice ? { TTS: openCodeForm.voice } : {}),
        },
        prompt: openCodeForm.prompt,
      }),
    );
  }

  function handleSaveWorkflow() {
    void save(
      baseUpsert({
        name: workflowName.trim(),
        type: "workflow",
        enableInterrupt: workflowSettings.allowInterrupt,
        turnConfig: workflowSettings.turnConfig,
        visionEnabled: workflowUsesVision(workflowGraph),
        visionModelResourceId: null,
        modelResourceIds: {
          ...(workflowSettings.llm ? { LLM: workflowSettings.llm } : {}),
          ...(workflowSettings.asr ? { ASR: workflowSettings.asr } : {}),
          ...(workflowSettings.tts ? { TTS: workflowSettings.tts } : {}),
        },
        knowledgeBaseId: workflowSettings.knowledgeBaseId || null,
        knowledgeRetrievalConfig: workflowSettings.knowledgeRetrievalConfig,
        toolIds: workflowSettings.toolIds,
        graph: workflowGraph as unknown as Record<string, unknown>,
        dynamicVariableDefinitions: effectiveWorkflowDynamicVariableDefinitions,
      }),
    );
  }

  // 当前编辑器表单相对已保存基线是否有改动(决定保存按钮是否可点)
  const activeFormJson =
    view === "create"
      ? JSON.stringify(form)
      : view === "create-agent-platform"
        ? JSON.stringify(agentPlatformForm)
        : view === "create-opencode"
          ? JSON.stringify(openCodeForm)
          : view === "workflow"
            ? JSON.stringify({
                name: workflowName,
                graph: workflowGraph,
                settings: workflowSettings,
                dynamicVariableDefinitions:
                  effectiveWorkflowDynamicVariableDefinitions,
              })
            : null;
  const dirty =
    activeFormJson !== null &&
    savedSnapshot !== null &&
    activeFormJson !== savedSnapshot;

  const listItems: AssistantListItem[] = assistants.map((a) => ({
    id: a.id,
    name: a.name,
    type: typeToLabel[a.type],
    updatedAt: formatTimestamp(a.updatedAt),
    updatedAtRaw: a.updatedAt,
  }));
  const filteredAssistants = listItems.filter((assistant) => {
    if (typeFilter !== "全部" && assistant.type !== typeFilter) {
      return false;
    }

    const keyword = searchQuery.trim().toLowerCase();

    if (!keyword) {
      return true;
    }

    return [assistant.name, assistant.id, assistant.type, assistant.updatedAt]
      .join(" ")
      .toLowerCase()
      .includes(keyword);
  });

  // 按更新时间排序(以原始 ISO 时间戳为准);缺失时间戳视为最早,id 作为稳定的次级排序键
  const timeValue = (iso: string | null | undefined) => {
    const t = iso ? new Date(iso).getTime() : NaN;
    return Number.isNaN(t) ? 0 : t;
  };
  const sortedAssistants = [...filteredAssistants].sort((a, b) => {
    const diff = timeValue(b.updatedAtRaw) - timeValue(a.updatedAtRaw);
    if (diff !== 0) return sortOrder === "newest" ? diff : -diff;
    return a.id.localeCompare(b.id);
  });

  const pageSize = 5;
  const totalPages = Math.max(1, Math.ceil(sortedAssistants.length / pageSize));
  const safeCurrentPage = Math.min(currentPage, totalPages);
  const pageStart = (safeCurrentPage - 1) * pageSize;
  const pageEnd = pageStart + pageSize;
  const paginatedAssistants = sortedAssistants.slice(pageStart, pageEnd);

  function handleSearchChange(value: string) {
    setSearchQuery(value);
    setCurrentPage(1);
  }

  function handleFilterChange(filter: TypeFilter) {
    setTypeFilter(filter);
    setCurrentPage(1);
  }

  function handleSortChange(order: SortOrder) {
    setSortOrder(order);
    setCurrentPage(1);
  }

  function toggleSortOrder() {
    handleSortChange(sortOrder === "newest" ? "oldest" : "newest");
  }

  function updateForm<K extends keyof AssistantForm>(
    key: K,
    value: AssistantForm[K],
  ) {
    setForm((prev) => ({
      ...prev,
      [key]: value,
    }));
  }

  function updateAgentPlatformForm<K extends keyof AgentPlatformForm>(
    key: K,
    value: AgentPlatformForm[K],
  ) {
    setAgentPlatformForm((prev) => ({
      ...prev,
      [key]: value,
    }));
  }

  function handleAgentPlatformChange(platform: AgentPlatform) {
    setAgentPlatformForm((prev) => ({
      ...prev,
      platform,
      agent: prev.platform === platform ? prev.agent : "",
    }));
  }

  function updateOpenCodeForm<K extends keyof OpenCodeForm>(
    key: K,
    value: OpenCodeForm[K],
  ) {
    setOpenCodeForm((prev) => ({
      ...prev,
      [key]: value,
    }));
  }
  if (view === "loading") {
    return (
      <div className="flex h-full items-center justify-center">
        {loadError ? (
          <div className="text-center">
            <div className="font-medium text-destructive">加载助手失败</div>
            <div className="mt-2 text-sm text-muted-foreground">
              {loadError}
            </div>
            <Button
              variant="outline"
              size="sm"
              className="mt-4 border-hairline-strong text-muted-foreground hover:text-foreground"
              onClick={() => router.push("/assistants")}
            >
              返回列表
            </Button>
          </div>
        ) : (
          <div className="flex items-center gap-2 text-sm text-muted-foreground">
            <Loader2 size={16} className="animate-spin" />
            正在加载助手…
          </div>
        )}
      </div>
    );
  }

  if (view === "list") {
    return (
      <div className="mx-auto flex w-full max-w-[1440px] flex-col gap-8">
        <PageHeader
          title="助手列表"
          description="管理已有的视频助手，支持提示词、工作流、Dify 和 FastGPT 类型。"
          action={
            <Button
              size="lg"
              className="w-full gap-2 sm:w-auto"
              onClick={startCreate}
            >
              <Plus size={16} />
              创建助手
            </Button>
          }
        />

        <section className="rounded-2xl border border-hairline bg-card p-6 shadow-sm">
          <ListToolbar
            filters={
              <FilterPills
                options={typeFilters}
                value={typeFilter}
                onChange={handleFilterChange}
              />
            }
            search={
              <SearchInput
                value={searchQuery}
                onChange={handleSearchChange}
                placeholder="搜索助手名称、类型或 ID..."
                className="lg:w-[320px]"
              />
            }
          />

          <DataList<AssistantListItem>
            rows={paginatedAssistants}
            rowKey={(assistant) => assistant.id}
            loading={listLoading}
            loadingText="正在加载助手列表…"
            error={listError}
            onRetry={() => void loadAssistants()}
            empty={{
              title: listItems.length === 0 ? "暂无助手" : "未找到匹配的助手",
              description:
                listItems.length === 0
                  ? "点击右上角「创建助手」开始。"
                  : "请调整关键词或筛选条件后再试。",
            }}
            pagination={{
              page: safeCurrentPage,
              totalPages,
              onPageChange: setCurrentPage,
              summary:
                filteredAssistants.length === 0
                  ? "没有数据"
                  : `显示 ${pageStart + 1}-${Math.min(pageEnd, filteredAssistants.length)} / 共 ${filteredAssistants.length} 个助手`,
            }}
            columns={[
              {
                key: "name",
                header: "助手名称",
                width: "md:w-[360px]",
                cell: (assistant) => (
                  <>
                    <div className="truncate font-medium text-foreground">
                      {assistant.name}
                    </div>
                    <div className="mt-1 text-xs text-muted-soft">
                      {assistant.id}
                    </div>
                  </>
                ),
              },
              {
                key: "type",
                header: "助手类型",
                width: "md:w-[128px]",
                cell: (assistant) => (
                  <Badge
                    variant="secondary"
                    className="h-6 bg-surface-strong px-3 text-muted-foreground"
                  >
                    {assistant.type}
                  </Badge>
                ),
              },
              {
                key: "updatedAt",
                width: "md:w-[176px]",
                header: (
                  <button
                    type="button"
                    onClick={toggleSortOrder}
                    className="caption-label -mx-2 inline-flex items-center gap-1 rounded-md px-2 py-1 text-muted-soft transition-colors hover:bg-surface-strong hover:text-foreground"
                    aria-label={
                      sortOrder === "newest"
                        ? "当前按最近更新排序,点击切换为最早更新"
                        : "当前按最早更新排序,点击切换为最近更新"
                    }
                  >
                    更新时间
                    {sortOrder === "newest" ? (
                      <ChevronDown size={13} />
                    ) : (
                      <ChevronUp size={13} />
                    )}
                  </button>
                ),
                cellClassName:
                  "whitespace-nowrap tabular-nums text-muted-foreground",
                cell: (assistant) => assistant.updatedAt,
              },
              {
                key: "actions",
                header: "操作",
                align: "right",
                cellClassName: "flex justify-end gap-2",
                cell: (assistant) => (
                  <>
                    <Button
                      variant="outline"
                      size="sm"
                      className="gap-1.5 border-hairline-strong text-xs text-muted-foreground hover:text-foreground"
                      onClick={() => handleEdit(assistant)}
                    >
                      <Pencil size={14} />
                      编辑
                    </Button>

                    <DropdownMenu>
                      <DropdownMenuTrigger asChild>
                        <Button
                          variant="outline"
                          size="icon-sm"
                          className="border-hairline-strong text-muted-foreground hover:text-foreground"
                          aria-label={`${assistant.name} 更多操作`}
                        >
                          <MoreHorizontal size={15} />
                        </Button>
                      </DropdownMenuTrigger>
                      <DropdownMenuContent
                        align="end"
                        className="w-32 min-w-32 rounded-xl border border-hairline bg-popover p-1"
                      >
                        <DropdownMenuItem
                          className="rounded-lg"
                          onSelect={() => handleDuplicate(assistant)}
                        >
                          <Copy size={14} />
                          复制
                        </DropdownMenuItem>
                        <DropdownMenuItem
                          variant="destructive"
                          className="rounded-lg"
                          onSelect={(event) => {
                            event.preventDefault();
                            void handleDelete(assistant.id);
                          }}
                        >
                          <Trash2 size={14} />
                          删除
                        </DropdownMenuItem>
                      </DropdownMenuContent>
                    </DropdownMenu>
                  </>
                ),
              },
            ]}
          />
        </section>
      </div>
    );
  }

  if (view === "choose") {
    return (
      <div className="mx-auto flex w-full max-w-[1180px] flex-col gap-8">
        <div className="flex items-start justify-between gap-6">
          <div>
            <h1 className="font-display display-lg text-ink">创建助手</h1>
            <p className="mt-3 max-w-2xl text-[15px] leading-7 text-muted-foreground">
              先为助手取个名字，再选择构建方式。确认后将立即创建助手并进入编辑页。
            </p>
          </div>

          <Button
            variant="outline"
            size="lg"
            className="shrink-0 gap-2 border-hairline-strong text-muted-foreground hover:text-foreground"
            onClick={() => router.push("/assistants")}
          >
            <ChevronLeft size={16} />
            返回列表
          </Button>
        </div>

        <section className="rounded-2xl border border-hairline bg-card p-6 shadow-sm">
          <label className="block">
            <div className="mb-2 text-sm font-medium text-foreground">
              助手名称
            </div>
            <Input
              value={draftName}
              autoFocus
              onChange={(event) => setDraftName(event.target.value)}
              placeholder="请输入助手名称"
              className="border-hairline-strong bg-background text-foreground placeholder:text-muted-soft"
            />
          </label>
        </section>

        <section className="flex flex-col gap-4">
          <div className="text-sm font-medium text-foreground">构建方式</div>

          <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
            {assistantTypeOptions.map((option) => {
              const selected = draftType === option.type;

              return (
                <button
                  key={option.type}
                  type="button"
                  onClick={() => setDraftType(option.type)}
                  className={`group relative flex flex-col gap-4 rounded-2xl border bg-card p-5 text-left transition-colors ${
                    selected
                      ? "border-primary ring-1 ring-primary"
                      : "border-hairline hover:border-hairline-strong"
                  }`}
                >
                  <div className="flex items-center justify-between">
                    <div className="flex h-11 w-11 items-center justify-center rounded-full bg-surface-strong text-foreground">
                      {option.icon}
                    </div>

                    {selected ? (
                      <span className="flex h-6 w-6 items-center justify-center rounded-full bg-primary text-primary-foreground">
                        <Check size={14} />
                      </span>
                    ) : (
                      !option.available && (
                        <Badge
                          variant="secondary"
                          className="h-6 bg-surface-strong px-3 text-xs text-muted-foreground"
                        >
                          即将上线
                        </Badge>
                      )
                    )}
                  </div>

                  <div>
                    <div className="text-base font-medium text-foreground">
                      {option.label}
                    </div>
                    <p className="mt-1.5 text-sm leading-6 text-muted-foreground">
                      {option.description}
                    </p>
                  </div>
                </button>
              );
            })}
          </div>

          {draftType === "智能体平台" && (
            <div className="rounded-2xl border border-hairline bg-card p-5">
              <div className="text-sm font-medium text-foreground">
                选择智能体平台
              </div>
              <p className="mt-1.5 text-sm leading-6 text-muted-foreground">
                平台类型用于匹配对应的应用资源和运行方式。
              </p>
              <div className="mt-4 flex flex-wrap gap-3">
                {(["dify", "fastgpt"] as const).map((platform) => {
                  const selected = draftAgentPlatform === platform;
                  const label = platform === "dify" ? "Dify" : "FastGPT";

                  return (
                    <Button
                      key={platform}
                      type="button"
                      variant={selected ? "default" : "outline"}
                      className={
                        selected
                          ? "gap-2"
                          : "gap-2 border-hairline-strong text-muted-foreground hover:text-foreground"
                      }
                      onClick={() => setDraftAgentPlatform(platform)}
                    >
                      {selected && <Check size={14} />}
                      {label}
                    </Button>
                  );
                })}
              </div>
            </div>
          )}
        </section>

        <div className="flex items-center justify-end gap-3">
          {createError && (
            <span className="text-xs text-destructive">{createError}</span>
          )}
          <Button
            variant="outline"
            size="lg"
            className="border-hairline-strong text-muted-foreground hover:text-foreground"
            disabled={creating}
            onClick={() => router.push("/assistants")}
          >
            取消
          </Button>
          <Button
            size="lg"
            className="gap-2"
            disabled={
              !draftName.trim() ||
              !draftType ||
              (draftType === "智能体平台" && !draftAgentPlatform) ||
              creating
            }
            onClick={() => void confirmType()}
          >
            {creating ? (
              <Loader2 size={16} className="animate-spin" />
            ) : (
              <Rocket size={16} />
            )}
            创建助手
          </Button>
        </div>
      </div>
    );
  }

  if (view === "workflow") {
    return (
      <WorkflowPage
        assistantId={editingId}
        workflowName={workflowName}
        workflowGraph={workflowGraph}
        workflowSettings={workflowSettings}
        dynamicVariableDefinitions={
          effectiveWorkflowDynamicVariableDefinitions
        }
        workflowDebugOpen={workflowDebugOpen}
        workflowSettingsOpen={workflowSettingsOpen}
        workflowEditingNodeId={workflowEditingNodeId}
        workflowEditingEdgeId={workflowEditingEdgeId}
        activeNodeId={activeNodeId}
        dynamicVariablesOpen={dynamicVariablesOpen}
        saving={saving}
        dirty={dirty}
        saveError={saveError}
        modelOptions={{
          llm: credOptions("LLM"),
          asr: credOptions("ASR"),
          tts: credOptions("TTS"),
          vision: visionModelOptionsFor(""),
        }}
        toolOptions={tools
          .filter((tool) => tool.status === "active")
          .map((tool) => ({ value: tool.id, label: tool.name }))}
        knowledgeOptions={kbOptions}
        onBack={() => router.push("/assistants")}
        onSave={() => void handleSaveWorkflow()}
        setWorkflowName={setWorkflowName}
        setWorkflowGraph={setWorkflowGraph}
        setWorkflowSettings={setWorkflowSettings}
        setWorkflowDynamicVariableDefinitions={
          setWorkflowDynamicVariableDefinitions
        }
        setWorkflowDebugOpen={setWorkflowDebugOpen}
        setWorkflowSettingsOpen={setWorkflowSettingsOpen}
        setWorkflowEditingNodeId={setWorkflowEditingNodeId}
        setWorkflowEditingEdgeId={setWorkflowEditingEdgeId}
        setActiveNodeId={setActiveNodeId}
        setDynamicVariablesOpen={setDynamicVariablesOpen}
      />
    );
  }
  if (view === "create-agent-platform") {
    const platformLabel =
      agentPlatformForm.platform === "dify" ? "Dify" : "FastGPT";

    return (
      <div className="-mt-6 flex h-full flex-col gap-4">
        <div className="flex shrink-0 items-center justify-between gap-6 border-b border-hairline pb-3 pt-1">
          <div className="flex min-w-0 items-center gap-2">
            <EditorBackButton onClick={() => router.push("/assistants")} />
            <EditableTitle
              value={agentPlatformForm.name}
              onChange={(value) => updateAgentPlatformForm("name", value)}
            />
            <AssistantIdentity assistantId={editingId} />
          </div>

          <div className="flex shrink-0 gap-2">
            {saveError && (
              <span className="self-center text-xs text-destructive">
                {saveError}
              </span>
            )}
            <Button
              className="gap-2"
              disabled={
                saving ||
                !dirty ||
                !agentPlatformForm.name.trim() ||
                !agentPlatformForm.agent
              }
              onClick={() => void handleSaveAgentPlatform()}
            >
              {saving ? (
                <Loader2 size={16} className="animate-spin" />
              ) : (
                <Save size={16} />
              )}
              保存
            </Button>
          </div>
        </div>

        <div className="flex min-h-0 flex-1 gap-4">
          <div className="scrollbar-subtle min-w-0 flex-1 space-y-3 overflow-y-auto pr-1">
            <SectionCard
              icon={<Boxes size={15} />}
              title="智能体平台配置"
              description={`选择智能体平台及对应应用。开场白、知识库、提示词等对话编排请在 ${platformLabel} 平台配置，本页不重复设置。`}
            >
              <div>
                <div className="mb-2 text-sm font-medium text-foreground">
                  智能体平台
                </div>
                <div className="flex flex-wrap gap-2">
                  {(["dify", "fastgpt"] as const).map((platform) => {
                    const selected = agentPlatformForm.platform === platform;
                    const label = platform === "dify" ? "Dify" : "FastGPT";

                    return (
                      <Button
                        key={platform}
                        type="button"
                        size="sm"
                        variant={selected ? "default" : "outline"}
                        className={
                          selected
                            ? "gap-2"
                            : "gap-2 border-hairline-strong text-muted-foreground hover:text-foreground"
                        }
                        onClick={() => handleAgentPlatformChange(platform)}
                      >
                        {selected && <Check size={14} />}
                        {label}
                      </Button>
                    );
                  })}
                </div>
              </div>
              <ResourceSelectField
                label={`${platformLabel} 应用`}
                value={agentPlatformForm.agent}
                onChange={(value) => updateAgentPlatformForm("agent", value)}
                options={agentOptions(agentPlatformForm.platform)}
                noneLabel="请选择"
              />
            </SectionCard>

            <SectionCard
              icon={<Brain size={15} />}
              title="语音配置"
              description={`从「模型资源」中选择语音识别与语音合成。大模型、知识库与开场白由 ${platformLabel} 应用提供，请前往 ${platformLabel} 平台配置。`}
            >
              <ResourceSelectField
                label="语音识别"
                value={agentPlatformForm.asr}
                onChange={(value) => updateAgentPlatformForm("asr", value)}
                options={credOptions("ASR")}
                noneLabel="无"
              />
              <ResourceSelectField
                label="语音合成"
                value={agentPlatformForm.voice}
                onChange={(value) => updateAgentPlatformForm("voice", value)}
                options={credOptions("TTS")}
                noneLabel="无"
              />
            </SectionCard>

            <SectionCard
              icon={<Sparkles size={15} />}
              title="交互策略"
              description="设置实时视频对话时的交互体验"
            >
              <TurnConfigEditor
                enabled={agentPlatformForm.enableInterrupt}
                config={agentPlatformForm.turnConfig}
                onEnabledChange={(checked) =>
                  updateAgentPlatformForm("enableInterrupt", checked)
                }
                onConfigChange={(config) =>
                  updateAgentPlatformForm("turnConfig", config)
                }
              />
            </SectionCard>
          </div>

          <DebugDrawer assistantId={editingId} hasUnsavedChanges={dirty} />
        </div>
      </div>
    );
  }

  if (view === "create-opencode") {
    return (
      <div className="-mt-6 flex h-full flex-col gap-4">
        <div className="flex shrink-0 items-center justify-between gap-6 border-b border-hairline pb-3 pt-1">
          <div className="flex min-w-0 items-center gap-2">
            <EditorBackButton onClick={() => router.push("/assistants")} />
            <EditableTitle
              value={openCodeForm.name}
              onChange={(value) => updateOpenCodeForm("name", value)}
            />
            <AssistantIdentity assistantId={editingId} />
          </div>

          <div className="flex shrink-0 gap-2">
            {saveError && (
              <span className="self-center text-xs text-destructive">
                {saveError}
              </span>
            )}
            <Button
              className="gap-2"
              disabled={
                saving ||
                !dirty ||
                !openCodeForm.name.trim() ||
                !openCodeForm.agent
              }
              onClick={() => void handleSaveOpenCode()}
            >
              {saving ? (
                <Loader2 size={16} className="animate-spin" />
              ) : (
                <Save size={16} />
              )}
              保存
            </Button>
          </div>
        </div>

        <div className="flex min-h-0 flex-1 gap-4">
          <div className="scrollbar-subtle min-w-0 flex-1 space-y-3 overflow-y-auto pr-1">
            <SectionCard
              icon={<Terminal size={15} />}
              title="OpenCode 服务配置"
              description="从「模型资源」中选择 OpenCode 服务资源。"
            >
              <ResourceSelectField
                label="OpenCode 服务"
                value={openCodeForm.agent}
                onChange={(value) => updateOpenCodeForm("agent", value)}
                options={agentOptions("opencode")}
                noneLabel="请选择"
              />
            </SectionCard>

            <SectionCard
              icon={<MessageSquareText size={15} />}
              title="提示词"
              description="描述助手的角色、能力和回答要求"
            >
              <TextAreaField
                value={openCodeForm.prompt}
                onChange={(value) => updateOpenCodeForm("prompt", value)}
                placeholder="请输入提示词，描述助手的角色、能力和回答要求"
                rows={8}
              />
            </SectionCard>

            <SectionCard
              icon={<Brain size={15} />}
              title="模型与语音配置"
              description="配置 OpenCode 使用的大语言模型、语音识别与语音合成资源。"
            >
              <ToggleRow
                title="视觉理解"
                hint="开启后，开始对话时会允许助手按需理解当前视频画面。视觉模型选「模型自己」时，大语言模型本身必须支持图片输入。"
                checked={openCodeForm.visionEnabled}
                onChange={handleOpenCodeVisionEnabledChange}
              />
              {openCodeForm.visionEnabled && (
                <ResourceSelectField
                  label="视觉模型"
                  value={openCodeForm.visionModelResourceId}
                  onChange={(value) =>
                    updateOpenCodeForm("visionModelResourceId", value)
                  }
                  options={visionModelOptionsFor(openCodeForm.model)}
                  noneLabel="模型自己"
                />
              )}
              <ResourceSelectField
                label="大语言模型"
                value={openCodeForm.model}
                onChange={handleOpenCodeModelChange}
                options={credOptions("LLM")}
                noneLabel="无"
              />
              <ResourceSelectField
                label="语音识别"
                value={openCodeForm.asr}
                onChange={(value) => updateOpenCodeForm("asr", value)}
                options={credOptions("ASR")}
                noneLabel="无"
              />
              <ResourceSelectField
                label="语音合成"
                value={openCodeForm.voice}
                onChange={(value) => updateOpenCodeForm("voice", value)}
                options={credOptions("TTS")}
                noneLabel="无"
              />
            </SectionCard>

            <SectionCard
              icon={<Sparkles size={15} />}
              title="交互策略"
              description="设置实时视频对话时的交互体验"
            >
              <TurnConfigEditor
                enabled={openCodeForm.enableInterrupt}
                config={openCodeForm.turnConfig}
                onEnabledChange={(checked) => updateOpenCodeForm("enableInterrupt", checked)}
                onConfigChange={(config) => updateOpenCodeForm("turnConfig", config)}
              />
            </SectionCard>
          </div>

          <DebugDrawer assistantId={editingId} hasUnsavedChanges={dirty} />
        </div>
      </div>
    );
  }

  return (
    <PromptEditor
      assistantId={editingId}
      form={form}
      dynamicVariablesOpen={dynamicVariablesOpen}
      dynamicVariableDefinitions={effectiveDynamicVariableDefinitions}
      saving={saving}
      dirty={dirty}
      saveError={saveError}
      llmOptions={credOptions("LLM")}
      asrOptions={credOptions("ASR")}
      ttsOptions={credOptions("TTS")}
      realtimeOptions={credOptions("Realtime")}
      visionModelOptions={visionModelOptionsFor(form.model)}
      knowledgeOptions={kbOptions}
      tools={tools}
      onBack={() => router.push("/assistants")}
      onSave={() => void handleSavePrompt()}
      setDynamicVariablesOpen={setDynamicVariablesOpen}
      updateForm={updateForm}
      handlePromptVisionEnabledChange={handlePromptVisionEnabledChange}
      handlePromptModelChange={handlePromptModelChange}
    />
  );
}
