/**
 * AI 相关 API - AI 对话、LLM 服务、Agent、Embedding
 */
import { ipcRenderer } from 'electron'
import type { ExportProgress } from '../../../src/types/base'

// ==================== 类型定义 ====================

// AI API 类型
export interface SearchMessageResult {
  id: number
  senderName: string
  senderPlatformId: string
  senderAliases: string[]
  senderAvatar: string | null
  content: string
  timestamp: number
  type: number
}

export interface AIConversation {
  id: string
  sessionId: string
  title: string | null
  assistantId: string
  createdAt: number
  updatedAt: number
}

// 内容块类型（用于 AI 消息的混合渲染）
export type ContentBlock =
  | { type: 'text'; text: string }
  | {
      type: 'tool'
      tool: {
        name: string
        displayName: string
        status: 'running' | 'done' | 'error'
        params?: Record<string, unknown>
      }
    }
  | { type: 'skill'; skillId: string; skillName: string }

export type AIMessageRole = 'user' | 'assistant' | 'summary'

export interface TokenUsageData {
  promptTokens: number
  completionTokens: number
  totalTokens: number
}

export interface AIMessage {
  id: string
  conversationId: string
  role: AIMessageRole
  content: string
  timestamp: number
  dataKeywords?: string[]
  dataMessageCount?: number
  contentBlocks?: ContentBlock[]
  tokenUsage?: TokenUsageData
}

// LLM API 类型
export interface LLMProvider {
  id: string
  name: string
  description: string
  defaultBaseUrl: string
  models: Array<{ id: string; name: string; description?: string }>
}

export interface ChatMessage {
  role: 'system' | 'user' | 'assistant'
  content: string
}

export interface ChatOptions {
  temperature?: number
  maxTokens?: number
}

export interface ChatStreamChunk {
  content: string
  isFinished: boolean
  finishReason?: 'stop' | 'length' | 'error'
}

// Agent API 类型 — 从 shared/types 统一导入
export type { TokenUsage, AgentRuntimeStatus } from '../../shared/types'
import type { TokenUsage, AgentRuntimeStatus, SerializedErrorInfo } from '../../shared/types'

export type { SerializedErrorInfo } from '../../shared/types'

export interface AgentStreamChunk {
  type: 'content' | 'think' | 'tool_start' | 'tool_result' | 'status' | 'compression_done' | 'done' | 'error'
  content?: string
  thinkTag?: string
  thinkDurationMs?: number
  toolName?: string
  toolParams?: Record<string, unknown>
  toolResult?: unknown
  status?: AgentRuntimeStatus
  error?: SerializedErrorInfo
  isFinished?: boolean
  compressionResult?: {
    summaryContent: string
    tokensBefore: number
    tokensAfter: number
    timestamp: number
  }
  /** Token 使用量（type=done 时返回累计值） */
  usage?: TokenUsage
}

export interface AgentResult {
  content: string
  toolsUsed: string[]
  toolRounds: number
  error?: SerializedErrorInfo
}

/** 单条脱敏规则 */
export interface DesensitizeRule {
  id: string
  label: string
  pattern: string
  replacement: string
  enabled: boolean
  builtin: boolean
  locales: string[]
}

/** 工具目录条目（实验室 - 基础工具） */
export interface ToolCatalogEntry {
  name: string
  category: 'core' | 'analysis'
  description: string
  parameters: Record<string, unknown>
}

/** 工具执行结果 */
export interface ToolExecuteResult {
  success: boolean
  elapsed?: number
  content?: Array<{ type: string; text: string }>
  details?: Record<string, unknown>
  error?: string
  truncated?: boolean
}

/** 聊天记录预处理配置 */
export interface PreprocessConfig {
  dataCleaning: boolean
  mergeConsecutive: boolean
  mergeWindowSeconds?: number
  blacklistKeywords: string[]
  denoise: boolean
  desensitize: boolean
  desensitizeRules: DesensitizeRule[]
  anonymizeNames: boolean
}

export interface ToolContext {
  sessionId: string
  conversationId?: string
  timeFilter?: { startTs: number; endTs: number }
  maxMessagesLimit?: number
  ownerInfo?: { platformId: string; displayName: string }
  mentionedMembers?: Array<{
    memberId: number
    platformId: string
    displayName: string
    aliases: string[]
    mentionText: string
  }>
  locale?: string
  preprocessConfig?: PreprocessConfig
}

// AI 服务配置类型（前端用）
export interface AIServiceConfigDisplay {
  id: string
  name: string
  provider: string
  apiKey: string // 脱敏后的 API Key
  apiKeySet: boolean
  model?: string
  baseUrl?: string
  maxTokens?: number
  apiFormat?: string
  disableThinking?: boolean
  isReasoningModel?: boolean
  customModels?: Array<{ id: string; name: string }>
  createdAt: number
  updatedAt: number
}

// ==================== AI API ====================

export const aiApi = {
  /**
   * 搜索消息（关键词搜索）
   * @param senderId 可选的发送者成员 ID，用于筛选特定成员的消息
   */
  searchMessages: (
    sessionId: string,
    keywords: string[],
    filter?: { startTs?: number; endTs?: number },
    limit?: number,
    offset?: number,
    senderId?: number
  ): Promise<{ messages: SearchMessageResult[]; total: number }> => {
    return ipcRenderer.invoke('ai:searchMessages', sessionId, keywords, filter, limit, offset, senderId)
  },

  /**
   * 获取消息上下文
   * @param messageIds 支持单个或批量消息 ID
   */
  getMessageContext: (
    sessionId: string,
    messageIds: number | number[],
    contextSize?: number
  ): Promise<SearchMessageResult[]> => {
    return ipcRenderer.invoke('ai:getMessageContext', sessionId, messageIds, contextSize)
  },

  /**
   * 获取最近消息（AI Agent 专用）
   */
  getRecentMessages: (
    sessionId: string,
    filter?: { startTs?: number; endTs?: number },
    limit?: number
  ): Promise<{ messages: SearchMessageResult[]; total: number }> => {
    return ipcRenderer.invoke('ai:getRecentMessages', sessionId, filter, limit)
  },

  /**
   * 获取所有最近消息（消息查看器专用）
   */
  getAllRecentMessages: (
    sessionId: string,
    filter?: { startTs?: number; endTs?: number },
    limit?: number
  ): Promise<{ messages: SearchMessageResult[]; total: number }> => {
    return ipcRenderer.invoke('ai:getAllRecentMessages', sessionId, filter, limit)
  },

  /**
   * 获取两人之间的对话
   */
  getConversationBetween: (
    sessionId: string,
    memberId1: number,
    memberId2: number,
    filter?: { startTs?: number; endTs?: number },
    limit?: number
  ): Promise<{ messages: SearchMessageResult[]; total: number; member1Name: string; member2Name: string }> => {
    return ipcRenderer.invoke('ai:getConversationBetween', sessionId, memberId1, memberId2, filter, limit)
  },

  /**
   * 获取指定消息之前的 N 条（用于向上无限滚动）
   */
  getMessagesBefore: (
    sessionId: string,
    beforeId: number,
    limit?: number,
    filter?: { startTs?: number; endTs?: number },
    senderId?: number,
    keywords?: string[]
  ): Promise<{ messages: SearchMessageResult[]; hasMore: boolean }> => {
    return ipcRenderer.invoke('ai:getMessagesBefore', sessionId, beforeId, limit, filter, senderId, keywords)
  },

  /**
   * 获取指定消息之后的 N 条（用于向下无限滚动）
   */
  getMessagesAfter: (
    sessionId: string,
    afterId: number,
    limit?: number,
    filter?: { startTs?: number; endTs?: number },
    senderId?: number,
    keywords?: string[]
  ): Promise<{ messages: SearchMessageResult[]; hasMore: boolean }> => {
    return ipcRenderer.invoke('ai:getMessagesAfter', sessionId, afterId, limit, filter, senderId, keywords)
  },

  // ==================== 自定义筛选（支持分页） ====================

  /**
   * 筛选结果消息类型
   */
  // FilterMessage 和 FilterResult 类型定义在下方

  /**
   * 按条件筛选消息并扩充上下文（支持分页）
   * @param page 页码（从 1 开始，默认 1）
   * @param pageSize 每页块数（默认 50）
   */
  filterMessagesWithContext: (
    sessionId: string,
    keywords?: string[],
    timeFilter?: { startTs: number; endTs: number },
    senderIds?: number[],
    contextSize?: number,
    page?: number,
    pageSize?: number
  ): Promise<{
    blocks: Array<{
      startTs: number
      endTs: number
      messages: Array<{
        id: number
        senderName: string
        senderPlatformId: string
        senderAliases: string[]
        senderAvatar: string | null
        content: string
        timestamp: number
        type: number
        replyToMessageId: string | null
        replyToContent: string | null
        replyToSenderName: string | null
        isHit: boolean
      }>
      hitCount: number
    }>
    stats: {
      totalMessages: number
      hitMessages: number
      totalChars: number
    }
    pagination: {
      page: number
      pageSize: number
      totalBlocks: number
      totalHits: number
      hasMore: boolean
    }
  }> => {
    return ipcRenderer.invoke(
      'ai:filterMessagesWithContext',
      sessionId,
      keywords,
      timeFilter,
      senderIds,
      contextSize,
      page,
      pageSize
    )
  },

  /**
   * 获取多个会话的完整消息（支持分页）
   * @param page 页码（从 1 开始，默认 1）
   * @param pageSize 每页块数（默认 50）
   */
  getMultipleSessionsMessages: (
    sessionId: string,
    chatSessionIds: number[],
    page?: number,
    pageSize?: number
  ): Promise<{
    blocks: Array<{
      startTs: number
      endTs: number
      messages: Array<{
        id: number
        senderName: string
        senderPlatformId: string
        senderAliases: string[]
        senderAvatar: string | null
        content: string
        timestamp: number
        type: number
        replyToMessageId: string | null
        replyToContent: string | null
        replyToSenderName: string | null
        isHit: boolean
      }>
      hitCount: number
    }>
    stats: {
      totalMessages: number
      hitMessages: number
      totalChars: number
    }
    pagination: {
      page: number
      pageSize: number
      totalBlocks: number
      totalHits: number
      hasMore: boolean
    }
  }> => {
    return ipcRenderer.invoke('ai:getMultipleSessionsMessages', sessionId, chatSessionIds, page, pageSize)
  },

  /**
   * 导出筛选结果到文件（后端生成，支持大数据量）
   */
  exportFilterResultToFile: (params: {
    sessionId: string
    sessionName: string
    outputDir: string
    filterMode: 'condition' | 'session'
    keywords?: string[]
    timeFilter?: { startTs: number; endTs: number }
    senderIds?: number[]
    contextSize?: number
    chatSessionIds?: number[]
  }): Promise<{ success: boolean; filePath?: string; error?: string }> => {
    return ipcRenderer.invoke('ai:exportFilterResultToFile', params)
  },

  /**
   * 监听导出进度
   */
  onExportProgress: (callback: (progress: ExportProgress) => void) => {
    const handler = (_event: Electron.IpcRendererEvent, progress: ExportProgress) => {
      callback(progress)
    }
    ipcRenderer.on('ai:exportProgress', handler)
    return () => {
      ipcRenderer.removeListener('ai:exportProgress', handler)
    }
  },

  /**
   * 创建 AI 对话
   */
  createConversation: (sessionId: string, title: string | undefined, assistantId: string): Promise<AIConversation> => {
    return ipcRenderer.invoke('ai:createConversation', sessionId, title, assistantId)
  },

  /**
   * 获取会话的所有 AI 对话列表
   */
  getConversations: (sessionId: string): Promise<AIConversation[]> => {
    return ipcRenderer.invoke('ai:getConversations', sessionId)
  },

  /**
   * 获取单个 AI 对话
   */
  getConversation: (conversationId: string): Promise<AIConversation | null> => {
    return ipcRenderer.invoke('ai:getConversation', conversationId)
  },

  /**
   * 更新 AI 对话标题
   */
  updateConversationTitle: (conversationId: string, title: string): Promise<boolean> => {
    return ipcRenderer.invoke('ai:updateConversationTitle', conversationId, title)
  },

  /**
   * 删除 AI 对话
   */
  deleteConversation: (conversationId: string): Promise<boolean> => {
    return ipcRenderer.invoke('ai:deleteConversation', conversationId)
  },

  /**
   * 添加 AI 消息
   */
  addMessage: (
    conversationId: string,
    role: AIMessageRole,
    content: string,
    dataKeywords?: string[],
    dataMessageCount?: number,
    contentBlocks?: ContentBlock[],
    tokenUsage?: TokenUsageData
  ): Promise<AIMessage> => {
    return ipcRenderer.invoke(
      'ai:addMessage',
      conversationId,
      role,
      content,
      dataKeywords,
      dataMessageCount,
      contentBlocks,
      tokenUsage
    )
  },

  /**
   * 获取 AI 对话的所有消息
   */
  getMessages: (conversationId: string): Promise<AIMessage[]> => {
    return ipcRenderer.invoke('ai:getMessages', conversationId)
  },

  /**
   * 获取对话的累计 token 使用量
   */
  getConversationTokenUsage: (conversationId: string): Promise<TokenUsageData> => {
    return ipcRenderer.invoke('ai:getConversationTokenUsage', conversationId)
  },

  /**
   * 删除 AI 消息
   */
  deleteMessage: (messageId: string): Promise<boolean> => {
    return ipcRenderer.invoke('ai:deleteMessage', messageId)
  },

  /**
   * 打开当前 AI 日志文件并定位到文件
   */
  showAiLogFile: (): Promise<{ success: boolean; path?: string; error?: string }> => {
    return ipcRenderer.invoke('ai:showLogFile')
  },

  /**
   * 一键清除所有消息的 debug_context 数据
   */
  clearDebugContext: (): Promise<{ success: boolean; cleared: number }> => {
    return ipcRenderer.invoke('ai:clearDebugContext')
  },

  getDefaultDesensitizeRules: (locale: string): Promise<DesensitizeRule[]> => {
    return ipcRenderer.invoke('ai:getDefaultDesensitizeRules', locale)
  },

  mergeDesensitizeRules: (existingRules: DesensitizeRule[], locale: string): Promise<DesensitizeRule[]> => {
    return ipcRenderer.invoke('ai:mergeDesensitizeRules', existingRules, locale)
  },

  getToolCatalog: (): Promise<ToolCatalogEntry[]> => {
    return ipcRenderer.invoke('ai:getToolCatalog')
  },

  executeTool: (
    testId: string,
    toolName: string,
    params: Record<string, unknown>,
    sessionId: string
  ): Promise<ToolExecuteResult> => {
    return ipcRenderer.invoke('ai:executeTool', testId, toolName, params, sessionId)
  },

  cancelToolTest: (testId: string): Promise<{ success: boolean }> => {
    return ipcRenderer.invoke('ai:cancelToolTest', testId)
  },

  estimateContextTokens: (
    conversationId: string
  ): Promise<{ success: boolean; tokens: number; messageCount?: number; error?: string }> => {
    return ipcRenderer.invoke('ai:estimateContextTokens', conversationId)
  },

  compressContext: (
    conversationId: string,
    compressionConfig: {
      enabled: boolean
      tokenThresholdPercent: number
      bufferSizePercent: number
      maxToolResultPercent?: number
    },
    systemPrompt: string
  ): Promise<{
    success: boolean
    result?: {
      compressed: boolean
      reason: string
      tokensBefore?: number
      tokensAfter?: number
      error?: string
    }
    error?: string
  }> => {
    return ipcRenderer.invoke('ai:compressContext', conversationId, compressionConfig, systemPrompt)
  },

  /**
   * [Debug] 获取 AI 数据库 Schema
   */
  getAiSchema: (): Promise<
    Array<{ name: string; columns: Array<{ name: string; type: string; notnull: boolean; pk: boolean }> }>
  > => {
    return ipcRenderer.invoke('ai:getAiSchema')
  },

  /**
   * [Debug] 在 AI 数据库上执行原始 SQL
   */
  executeAiSQL: (
    sql: string
  ): Promise<{ columns: string[]; rows: any[][]; rowCount: number; duration: number; limited: boolean }> => {
    return ipcRenderer.invoke('ai:executeAiSQL', sql)
  },
}

// ==================== LLM API ====================

export const llmApi = {
  // ==================== Provider Registry / Model Catalog ====================

  getProviderRegistry: () => {
    return ipcRenderer.invoke('llm:getProviderRegistry')
  },

  getModelCatalog: () => {
    return ipcRenderer.invoke('llm:getModelCatalog')
  },

  addCustomProvider: (input: Record<string, unknown>) => {
    return ipcRenderer.invoke('llm:addCustomProvider', input)
  },

  updateCustomProvider: (id: string, updates: Record<string, unknown>) => {
    return ipcRenderer.invoke('llm:updateCustomProvider', id, updates)
  },

  deleteCustomProvider: (id: string) => {
    return ipcRenderer.invoke('llm:deleteCustomProvider', id)
  },

  addCustomModel: (input: Record<string, unknown>) => {
    return ipcRenderer.invoke('llm:addCustomModel', input)
  },

  updateCustomModel: (providerId: string, modelId: string, updates: Record<string, unknown>) => {
    return ipcRenderer.invoke('llm:updateCustomModel', providerId, modelId, updates)
  },

  deleteCustomModel: (providerId: string, modelId: string) => {
    return ipcRenderer.invoke('llm:deleteCustomModel', providerId, modelId)
  },

  /** @deprecated 使用 getProviderRegistry 代替 */
  getProviders: (): Promise<LLMProvider[]> => {
    return ipcRenderer.invoke('llm:getProviders')
  },

  // ==================== 多配置管理 API ====================

  /**
   * 获取所有配置列表
   */
  getAllConfigs: (): Promise<AIServiceConfigDisplay[]> => {
    return ipcRenderer.invoke('llm:getAllConfigs')
  },

  /**
   * 获取默认助手 slot（configId + modelId）
   */
  getDefaultAssistantSlot: (): Promise<{ configId: string; modelId: string } | null> => {
    return ipcRenderer.invoke('llm:getDefaultAssistantSlot')
  },

  /**
   * 获取快速模型 slot
   */
  getFastModelSlot: (): Promise<{ configId: string; modelId: string } | null> => {
    return ipcRenderer.invoke('llm:getFastModelSlot')
  },

  /**
   * 添加新配置
   */
  addConfig: (config: {
    name: string
    provider: string
    apiKey: string
    model?: string
    baseUrl?: string
    maxTokens?: number
    apiFormat?: string
    disableThinking?: boolean
    isReasoningModel?: boolean
    customModels?: Array<{ id: string; name: string }>
  }): Promise<{ success: boolean; config?: AIServiceConfigDisplay; error?: string }> => {
    return ipcRenderer.invoke('llm:addConfig', config)
  },

  /**
   * 更新配置
   */
  updateConfig: (
    id: string,
    updates: {
      name?: string
      provider?: string
      apiKey?: string
      model?: string
      baseUrl?: string
      maxTokens?: number
      apiFormat?: string
      disableThinking?: boolean
      isReasoningModel?: boolean
      customModels?: Array<{ id: string; name: string }>
    }
  ): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('llm:updateConfig', id, updates)
  },

  /**
   * 删除配置
   */
  deleteConfig: (id?: string): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('llm:deleteConfig', id)
  },

  /**
   * 设置默认助手模型（configId + modelId）
   */
  setDefaultAssistantModel: (configId: string, modelId: string): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('llm:setDefaultAssistantModel', configId, modelId)
  },

  /**
   * 设置快速模型
   */
  setFastModel: (slot: { configId: string; modelId: string } | null): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('llm:setFastModel', slot)
  },

  /**
   * 验证 API Key（支持自定义 baseUrl 和 model）
   */
  validateApiKey: (
    provider: string,
    apiKey: string,
    baseUrl?: string,
    model?: string
  ): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('llm:validateApiKey', provider, apiKey, baseUrl, model)
  },

  /**
   * 获取远程模型列表
   */
  fetchRemoteModels: (
    provider: string,
    apiKey: string,
    baseUrl?: string,
    apiFormat?: string
  ): Promise<{
    success: boolean
    models?: Array<{ id: string; name: string; ownedBy?: string; contextWindow?: number }>
    error?: string
  }> => {
    return ipcRenderer.invoke('llm:fetchRemoteModels', provider, apiKey, baseUrl, apiFormat)
  },

  /**
   * 检查是否已配置 LLM（是否有激活的配置）
   */
  hasConfig: (): Promise<boolean> => {
    return ipcRenderer.invoke('llm:hasConfig')
  },

  /**
   * 发送 LLM 聊天请求（非流式）
   */
  chat: (
    messages: ChatMessage[],
    options?: ChatOptions
  ): Promise<{ success: boolean; content?: string; error?: string }> => {
    return ipcRenderer.invoke('llm:chat', messages, options)
  },

  /**
   * 发送 LLM 聊天请求（流式）
   * 返回一个 Promise，该 Promise 在流完成后才 resolve
   */
  chatStream: (
    messages: ChatMessage[],
    options?: ChatOptions,
    onChunk?: (chunk: ChatStreamChunk) => void
  ): Promise<{ success: boolean; error?: string }> => {
    return new Promise((resolve) => {
      const requestId = `llm_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
      console.log('[preload] chatStream 开始，requestId:', requestId)

      const handler = (
        _event: Electron.IpcRendererEvent,
        data: { requestId: string; chunk: ChatStreamChunk; error?: string }
      ) => {
        if (data.requestId === requestId) {
          if (data.error) {
            console.log('[preload] chatStream 收到错误:', data.error)
            if (onChunk) {
              onChunk({ content: '', isFinished: true, finishReason: 'error' })
            }
            ipcRenderer.removeListener('llm:streamChunk', handler)
            resolve({ success: false, error: data.error })
          } else {
            if (onChunk) {
              onChunk(data.chunk)
            }

            // 如果已完成，移除监听器并 resolve
            if (data.chunk.isFinished) {
              console.log('[preload] chatStream 完成，requestId:', requestId)
              ipcRenderer.removeListener('llm:streamChunk', handler)
              resolve({ success: true })
            }
          }
        }
      }

      ipcRenderer.on('llm:streamChunk', handler)

      // 发起请求
      ipcRenderer
        .invoke('llm:chatStream', requestId, messages, options)
        .then((result) => {
          console.log('[preload] chatStream invoke 返回:', result)
          if (!result.success) {
            ipcRenderer.removeListener('llm:streamChunk', handler)
            resolve(result)
          }
          // 如果 success，等待流完成（由 handler 处理 resolve）
        })
        .catch((error) => {
          console.error('[preload] chatStream invoke 错误:', error)
          ipcRenderer.removeListener('llm:streamChunk', handler)
          resolve({ success: false, error: String(error) })
        })
    })
  },
}

// ==================== Assistant API ====================

export interface AssistantSummary {
  id: string
  name: string
  systemPrompt: string
  presetQuestions: string[]
  builtinId?: string
  applicableChatTypes?: ('group' | 'private')[]
  supportedLocales?: string[]
}

export interface AssistantConfigFull {
  id: string
  name: string
  systemPrompt: string
  presetQuestions: string[]
  allowedBuiltinTools?: string[]
  builtinId?: string
  applicableChatTypes?: ('group' | 'private')[]
  supportedLocales?: string[]
}

export interface BuiltinAssistantInfo {
  id: string
  name: string
  systemPrompt: string
  applicableChatTypes?: ('group' | 'private')[]
  supportedLocales?: string[]
  imported: boolean
}

export const assistantApi = {
  getAll: (): Promise<AssistantSummary[]> => {
    return ipcRenderer.invoke('assistant:getAll')
  },

  getConfig: (id: string): Promise<AssistantConfigFull | null> => {
    return ipcRenderer.invoke('assistant:getConfig', id)
  },

  update: (id: string, updates: Partial<AssistantConfigFull>): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('assistant:update', id, updates)
  },

  create: (config: Omit<AssistantConfigFull, 'id'>): Promise<{ success: boolean; id?: string; error?: string }> => {
    return ipcRenderer.invoke('assistant:create', config)
  },

  delete: (id: string): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('assistant:delete', id)
  },

  reset: (id: string): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('assistant:reset', id)
  },

  getBuiltinCatalog: (): Promise<BuiltinAssistantInfo[]> => {
    return ipcRenderer.invoke('assistant:getBuiltinCatalog')
  },

  getBuiltinToolCatalog: (): Promise<Array<{ name: string; category: 'core' | 'analysis' }>> => {
    return ipcRenderer.invoke('assistant:getBuiltinToolCatalog')
  },

  importAssistant: (builtinId: string): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('assistant:import', builtinId)
  },

  reimportAssistant: (id: string): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('assistant:reimport', id)
  },

  importFromMd: (rawMd: string): Promise<{ success: boolean; id?: string; error?: string }> => {
    return ipcRenderer.invoke('assistant:importFromMd', rawMd)
  },
}

// ==================== Skill API ====================

export interface SkillSummary {
  id: string
  name: string
  description: string
  tags: string[]
  chatScope: 'all' | 'group' | 'private'
  tools: string[]
  builtinId?: string
}

export interface SkillConfigFull {
  id: string
  name: string
  description: string
  tags: string[]
  chatScope: 'all' | 'group' | 'private'
  prompt: string
  tools: string[]
  builtinId?: string
}

export interface BuiltinSkillInfo extends SkillSummary {
  imported: boolean
  hasUpdate: boolean
}

export const skillApi = {
  getAll: (): Promise<SkillSummary[]> => {
    return ipcRenderer.invoke('skill:getAll')
  },

  getConfig: (id: string): Promise<SkillConfigFull | null> => {
    return ipcRenderer.invoke('skill:getConfig', id)
  },

  update: (id: string, rawMd: string): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('skill:update', id, rawMd)
  },

  create: (rawMd: string): Promise<{ success: boolean; id?: string; error?: string }> => {
    return ipcRenderer.invoke('skill:create', rawMd)
  },

  delete: (id: string): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('skill:delete', id)
  },

  getBuiltinCatalog: (): Promise<BuiltinSkillInfo[]> => {
    return ipcRenderer.invoke('skill:getBuiltinCatalog')
  },

  importSkill: (builtinId: string): Promise<{ success: boolean; id?: string; error?: string }> => {
    return ipcRenderer.invoke('skill:import', builtinId)
  },

  reimportSkill: (id: string): Promise<{ success: boolean; error?: string }> => {
    return ipcRenderer.invoke('skill:reimport', id)
  },

  importFromMd: (rawMd: string): Promise<{ success: boolean; id?: string; error?: string }> => {
    return ipcRenderer.invoke('skill:importFromMd', rawMd)
  },
}

// ==================== Agent API ====================

export const agentApi = {
  /**
   * 执行 Agent 对话（流式）
   * Agent 通过 context.conversationId 从后端 SQLite 读取对话历史
   * @param chatType 聊天类型（'group' | 'private'）
   * @param locale 语言设置（可选，默认 'zh-CN'）
   * @returns 返回 { requestId, promise }，requestId 可用于中止请求
   */
  runStream: (
    userMessage: string,
    context: ToolContext,
    onChunk?: (chunk: AgentStreamChunk) => void,
    chatType?: 'group' | 'private',
    locale?: string,
    assistantId?: string,
    skillId?: string | null,
    enableAutoSkill?: boolean,
    compressionConfig?: {
      enabled: boolean
      tokenThresholdPercent: number
      bufferSizePercent: number
      maxToolResultPercent?: number
    }
  ): {
    requestId: string
    promise: Promise<{ success: boolean; result?: AgentResult; error?: SerializedErrorInfo }>
  } => {
    // 防御性处理：确保传给 IPC 的 context 是“可结构化克隆”的纯对象
    // 避免调用方误传入响应式 Proxy（例如 Pinia/Vue state）导致 invoke 失败
    const sanitizedContext: ToolContext = {
      sessionId: context.sessionId,
      conversationId: context.conversationId,
      timeFilter: context.timeFilter
        ? {
            startTs: context.timeFilter.startTs,
            endTs: context.timeFilter.endTs,
          }
        : undefined,
      maxMessagesLimit: context.maxMessagesLimit,
      ownerInfo: context.ownerInfo
        ? {
            platformId: context.ownerInfo.platformId,
            displayName: context.ownerInfo.displayName,
          }
        : undefined,
      mentionedMembers: context.mentionedMembers
        ? context.mentionedMembers.map((member) => ({
            memberId: member.memberId,
            platformId: member.platformId,
            displayName: member.displayName,
            aliases: [...member.aliases],
            mentionText: member.mentionText,
          }))
        : undefined,
      locale: context.locale,
      preprocessConfig: context.preprocessConfig,
    }

    const requestId = `agent_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
    console.log(
      '[preload] Agent runStream 开始，requestId:',
      requestId,
      'conversationId:',
      sanitizedContext.conversationId ?? 'none',
      'chatType:',
      chatType ?? 'group'
    )

    const promise = new Promise<{ success: boolean; result?: AgentResult; error?: SerializedErrorInfo }>((resolve) => {
      // 监听流式 chunks
      const chunkHandler = (
        _event: Electron.IpcRendererEvent,
        data: { requestId: string; chunk: AgentStreamChunk }
      ) => {
        if (data.requestId === requestId) {
          if (onChunk) {
            onChunk(data.chunk)
          }
        }
      }

      // 监听完成事件
      const completeHandler = (
        _event: Electron.IpcRendererEvent,
        data: { requestId: string; result: AgentResult & { error?: SerializedErrorInfo } }
      ) => {
        if (data.requestId === requestId) {
          console.log('[preload] Agent 完成，requestId:', requestId, 'hasError:', !!data.result?.error)
          ipcRenderer.removeListener('agent:streamChunk', chunkHandler)
          ipcRenderer.removeListener('agent:complete', completeHandler)
          // 如果 result 中包含 error，返回失败状态
          if (data.result?.error) {
            resolve({ success: false, error: data.result.error })
          } else {
            resolve({ success: true, result: data.result })
          }
        }
      }

      ipcRenderer.on('agent:streamChunk', chunkHandler)
      ipcRenderer.on('agent:complete', completeHandler)

      ipcRenderer
        .invoke(
          'agent:runStream',
          requestId,
          userMessage,
          sanitizedContext,
          chatType,
          locale,
          assistantId,
          skillId,
          enableAutoSkill,
          compressionConfig
        )
        .then((result) => {
          console.log('[preload] Agent invoke 返回:', result)
          if (!result.success) {
            ipcRenderer.removeListener('agent:streamChunk', chunkHandler)
            ipcRenderer.removeListener('agent:complete', completeHandler)
            resolve(result)
          }
          // 如果 success，等待完成（由 completeHandler 处理 resolve）
        })
        .catch((error) => {
          console.error('[preload] Agent invoke 错误:', error)
          ipcRenderer.removeListener('agent:streamChunk', chunkHandler)
          ipcRenderer.removeListener('agent:complete', completeHandler)
          resolve({
            success: false,
            error: {
              name: error instanceof Error ? error.name : null,
              message: error instanceof Error ? error.message : String(error),
              stack: error instanceof Error ? (error.stack ?? null) : null,
            },
          })
        })
    })

    return { requestId, promise }
  },

  /**
   * 中止 Agent 请求
   * @param requestId 请求 ID
   */
  abort: (requestId: string): Promise<{ success: boolean; error?: string }> => {
    console.log('[preload] Agent abort 请求，requestId:', requestId)
    return ipcRenderer.invoke('agent:abort', requestId)
  },
}
