import { BaseHttpClient } from './BaseHttpClient';
import {
  ApiRespProviderRequesters,
  ApiRespProviderRequester,
  ApiRespProviderLLMModels,
  ApiRespProviderLLMModel,
  LLMModel,
  ApiRespPipelines,
  Pipeline,
  ApiRespPlatformAdapters,
  ApiRespPlatformAdapter,
  ApiRespPlatformBots,
  ApiRespPlatformBot,
  Bot,
  ApiRespPlugins,
  ApiRespPlugin,
  ApiRespPluginConfig,
  AsyncTaskCreatedResp,
  ApiRespSystemInfo,
  ApiRespAsyncTasks,
  ApiRespUserToken,
  GetPipelineResponseData,
  GetPipelineMetadataResponseData,
  AsyncTask,
  ApiRespWebChatMessages,
  ApiRespKnowledgeBases,
  ApiRespKnowledgeBase,
  KnowledgeBase,
  ApiRespKnowledgeBaseFiles,
  ApiRespKnowledgeBaseRetrieve,
  ApiRespProviderEmbeddingModels,
  ApiRespProviderEmbeddingModel,
  EmbeddingModel,
  ApiRespProviderRerankModels,
  ApiRespProviderRerankModel,
  RerankModel,
  ApiRespPluginSystemStatus,
  ApiRespMCPServers,
  ApiRespMCPServer,
  MCPServer,
  ApiRespModelProviders,
  ApiRespModelProvider,
  ApiRespScannedProviderModels,
  ModelProvider,
  ApiRespKnowledgeEngines,
  ApiRespParsers,
  RagMigrationStatusResp,
  ApiRespTools,
  ApiRespToolDetail,
  ApiRespWorkflows,
  ApiRespWorkflow,
  ApiRespWorkflowNodeTypes,
  ApiRespWorkflowExecutions,
  ApiRespWorkflowExecution,
  ApiRespWorkflowVersions,
  Workflow,
  CreateWorkflowRequest,
  UpdateWorkflowRequest,
  ExecuteWorkflowRequest,
} from '@/app/infra/entities/api';
import { Plugin } from '@/app/infra/entities/plugin';
import { GetBotLogsRequest } from '@/app/infra/http/requestParam/bots/GetBotLogsRequest';
import { GetBotLogsResponse } from '@/app/infra/http/requestParam/bots/GetBotLogsResponse';

/**
 * 后端服务客户端
 * 负责与后端 API 的所有交互
 */
export class BackendClient extends BaseHttpClient {
  constructor(baseURL: string) {
    super(baseURL, false);
  }

  // ============ Provider API ============
  public getProviderRequesters(
    model_type?: string,
  ): Promise<ApiRespProviderRequesters> {
    return this.get('/api/v1/provider/requesters', { type: model_type });
  }

  public getProviderRequester(name: string): Promise<ApiRespProviderRequester> {
    return this.get(`/api/v1/provider/requesters/${name}`);
  }

  public getProviderRequesterIconURL(name: string): string {
    if (this.instance.defaults.baseURL === '/') {
      const url = window.location.href;
      const baseURL = url.split('/').slice(0, 3).join('/');
      return `${baseURL}/api/v1/provider/requesters/${name}/icon`;
    }
    return (
      this.instance.defaults.baseURL +
      `/api/v1/provider/requesters/${name}/icon`
    );
  }

  // ============ Model Providers ============
  public getModelProviders(): Promise<ApiRespModelProviders> {
    return this.get('/api/v1/provider/providers');
  }

  public getModelProvider(uuid: string): Promise<ApiRespModelProvider> {
    return this.get(`/api/v1/provider/providers/${uuid}`);
  }

  public createModelProvider(
    provider: Omit<ModelProvider, 'uuid'>,
  ): Promise<{ uuid: string }> {
    return this.post('/api/v1/provider/providers', provider);
  }

  public updateModelProvider(
    uuid: string,
    provider: Partial<ModelProvider>,
  ): Promise<object> {
    return this.put(`/api/v1/provider/providers/${uuid}`, provider);
  }

  public deleteModelProvider(uuid: string): Promise<object> {
    return this.delete(`/api/v1/provider/providers/${uuid}`);
  }

  public scanProviderModels(
    uuid: string,
    modelType?: 'llm' | 'embedding',
  ): Promise<ApiRespScannedProviderModels> {
    const params = modelType ? { type: modelType } : {};
    return this.get(`/api/v1/provider/providers/${uuid}/scan-models`, params);
  }

  // ============ Provider Model LLM ============
  public getProviderLLMModels(
    providerUuid?: string,
  ): Promise<ApiRespProviderLLMModels> {
    const params = providerUuid ? { provider_uuid: providerUuid } : {};
    return this.get('/api/v1/provider/models/llm', params);
  }

  public getProviderLLMModel(uuid: string): Promise<ApiRespProviderLLMModel> {
    return this.get(`/api/v1/provider/models/llm/${uuid}`);
  }

  public createProviderLLMModel(model: LLMModel): Promise<object> {
    return this.post('/api/v1/provider/models/llm', model);
  }

  public deleteProviderLLMModel(uuid: string): Promise<object> {
    return this.delete(`/api/v1/provider/models/llm/${uuid}`);
  }

  public updateProviderLLMModel(
    uuid: string,
    model: LLMModel,
  ): Promise<object> {
    return this.put(`/api/v1/provider/models/llm/${uuid}`, model);
  }

  public testLLMModel(uuid: string, model: LLMModel): Promise<object> {
    return this.post(`/api/v1/provider/models/llm/${uuid}/test`, model);
  }

  // ============ Provider Model Embedding ============
  public getProviderEmbeddingModels(
    providerUuid?: string,
  ): Promise<ApiRespProviderEmbeddingModels> {
    const params = providerUuid ? { provider_uuid: providerUuid } : {};
    return this.get('/api/v1/provider/models/embedding', params);
  }

  public getProviderEmbeddingModel(
    uuid: string,
  ): Promise<ApiRespProviderEmbeddingModel> {
    return this.get(`/api/v1/provider/models/embedding/${uuid}`);
  }

  public createProviderEmbeddingModel(model: EmbeddingModel): Promise<object> {
    return this.post('/api/v1/provider/models/embedding', model);
  }

  public deleteProviderEmbeddingModel(uuid: string): Promise<object> {
    return this.delete(`/api/v1/provider/models/embedding/${uuid}`);
  }

  public updateProviderEmbeddingModel(
    uuid: string,
    model: EmbeddingModel,
  ): Promise<object> {
    return this.put(`/api/v1/provider/models/embedding/${uuid}`, model);
  }

  public testEmbeddingModel(
    uuid: string,
    model: EmbeddingModel,
  ): Promise<object> {
    return this.post(`/api/v1/provider/models/embedding/${uuid}/test`, model);
  }

  // ============ Provider Model Rerank ============
  public getProviderRerankModels(
    providerUuid?: string,
  ): Promise<ApiRespProviderRerankModels> {
    const params = providerUuid ? { provider_uuid: providerUuid } : {};
    return this.get('/api/v1/provider/models/rerank', params);
  }

  public getProviderRerankModel(
    uuid: string,
  ): Promise<ApiRespProviderRerankModel> {
    return this.get(`/api/v1/provider/models/rerank/${uuid}`);
  }

  public createProviderRerankModel(model: RerankModel): Promise<object> {
    return this.post('/api/v1/provider/models/rerank', model);
  }

  public deleteProviderRerankModel(uuid: string): Promise<object> {
    return this.delete(`/api/v1/provider/models/rerank/${uuid}`);
  }

  public updateProviderRerankModel(
    uuid: string,
    model: RerankModel,
  ): Promise<object> {
    return this.put(`/api/v1/provider/models/rerank/${uuid}`, model);
  }

  public testRerankModel(uuid: string, model: RerankModel): Promise<object> {
    return this.post(`/api/v1/provider/models/rerank/${uuid}/test`, model);
  }

  // ============ Pipeline API ============
  public getGeneralPipelineMetadata(): Promise<GetPipelineMetadataResponseData> {
    // as designed, this method will be deprecated, and only for developer to check the prefered config schema
    return this.get('/api/v1/pipelines/_/metadata');
  }

  public getPipelines(
    sortBy?: string,
    sortOrder?: string,
  ): Promise<ApiRespPipelines> {
    const params = new URLSearchParams();
    if (sortBy) params.append('sort_by', sortBy);
    if (sortOrder) params.append('sort_order', sortOrder);
    const queryString = params.toString();
    return this.get(`/api/v1/pipelines${queryString ? `?${queryString}` : ''}`);
  }

  public getPipeline(uuid: string): Promise<GetPipelineResponseData> {
    return this.get(`/api/v1/pipelines/${uuid}`);
  }

  public createPipeline(pipeline: Pipeline): Promise<{
    uuid: string;
  }> {
    return this.post('/api/v1/pipelines', pipeline);
  }

  public updatePipeline(uuid: string, pipeline: Pipeline): Promise<object> {
    return this.put(`/api/v1/pipelines/${uuid}`, pipeline);
  }

  public deletePipeline(uuid: string): Promise<object> {
    return this.delete(`/api/v1/pipelines/${uuid}`);
  }

  public copyPipeline(uuid: string): Promise<{ uuid: string }> {
    return this.post(`/api/v1/pipelines/${uuid}/copy`);
  }

  public getPipelineExtensions(uuid: string): Promise<{
    enable_all_plugins: boolean;
    enable_all_mcp_servers: boolean;
    bound_plugins: Array<{ author: string; name: string }>;
    available_plugins: Plugin[];
    bound_mcp_servers: string[];
    available_mcp_servers: MCPServer[];
  }> {
    return this.get(`/api/v1/pipelines/${uuid}/extensions`);
  }

  public updatePipelineExtensions(
    uuid: string,
    bound_plugins: Array<{ author: string; name: string }>,
    bound_mcp_servers: string[],
    enable_all_plugins: boolean = true,
    enable_all_mcp_servers: boolean = true,
  ): Promise<object> {
    return this.put(`/api/v1/pipelines/${uuid}/extensions`, {
      bound_plugins,
      bound_mcp_servers,
      enable_all_plugins,
      enable_all_mcp_servers,
    });
  }

  // ============ WebSocket Chat API ============
  public getWebSocketHistoryMessages(
    pipelineId: string,
    sessionType: string,
  ): Promise<ApiRespWebChatMessages> {
    return this.get(
      `/api/v1/pipelines/${pipelineId}/ws/messages/${sessionType}`,
    );
  }

  public async uploadWebSocketImage(
    pipelineId: string,
    imageFile: File,
  ): Promise<{ file_key: string }> {
    const formData = new FormData();
    formData.append('file', imageFile);

    return this.postFile(`/api/v1/files/images`, formData);
  }

  public resetWebSocketSession(
    pipelineId: string,
    sessionType: string,
  ): Promise<{ message: string }> {
    return this.post(`/api/v1/pipelines/${pipelineId}/ws/reset/${sessionType}`);
  }

  public getWebSocketConnections(pipelineId: string): Promise<{
    stats: {
      total_connections: number;
      pipelines: number;
      connections_by_pipeline: Record<string, number>;
      connections_by_session_type: Record<string, number>;
    };
    connections: Array<{
      connection_id: string;
      session_type: string;
      created_at: string;
      last_active: string;
      is_active: boolean;
    }>;
  }> {
    return this.get(`/api/v1/pipelines/${pipelineId}/ws/connections`);
  }

  public broadcastWebSocketMessage(
    pipelineId: string,
    message: string,
  ): Promise<{ message: string }> {
    return this.post(`/api/v1/pipelines/${pipelineId}/ws/broadcast`, {
      message,
    });
  }

  // ============ Platform API ============
  public getAdapters(): Promise<ApiRespPlatformAdapters> {
    return this.get('/api/v1/platform/adapters');
  }

  public getAdapter(name: string): Promise<ApiRespPlatformAdapter> {
    return this.get(`/api/v1/platform/adapters/${name}`);
  }

  public getAdapterIconURL(name: string): string {
    if (this.instance.defaults.baseURL === '/') {
      // 获取用户访问的URL
      const url = window.location.href;
      const baseURL = url.split('/').slice(0, 3).join('/');
      return `${baseURL}/api/v1/platform/adapters/${name}/icon`;
    }
    return (
      this.instance.defaults.baseURL + `/api/v1/platform/adapters/${name}/icon`
    );
  }

  // ============ Platform Bots ============
  public getBots(): Promise<ApiRespPlatformBots> {
    return this.get('/api/v1/platform/bots');
  }

  public getBot(uuid: string): Promise<ApiRespPlatformBot> {
    return this.get(`/api/v1/platform/bots/${uuid}`);
  }

  public createBot(bot: Bot): Promise<{ uuid: string }> {
    return this.post('/api/v1/platform/bots', bot);
  }

  public updateBot(uuid: string, bot: Bot): Promise<object> {
    return this.put(`/api/v1/platform/bots/${uuid}`, bot);
  }

  public deleteBot(uuid: string): Promise<object> {
    return this.delete(`/api/v1/platform/bots/${uuid}`);
  }

  public getBotLogs(
    botId: string,
    request: GetBotLogsRequest,
  ): Promise<GetBotLogsResponse> {
    return this.post(`/api/v1/platform/bots/${botId}/logs`, request);
  }

  public getBotSessions(
    botId: string,
    limit: number = 100,
    offset: number = 0,
  ): Promise<{
    sessions: Array<{
      session_id: string;
      bot_id: string;
      bot_name: string;
      pipeline_id: string;
      pipeline_name: string;
      message_count: number;
      start_time: string;
      last_activity: string;
      is_active: boolean;
      platform: string | null;
      user_id: string | null;
      user_name: string | null;
    }>;
    total: number;
  }> {
    const queryParams = new URLSearchParams();
    queryParams.append('botId', botId);
    queryParams.append('limit', limit.toString());
    queryParams.append('offset', offset.toString());
    return this.get(`/api/v1/monitoring/sessions?${queryParams.toString()}`);
  }

  public getSessionMessages(
    sessionId: string,
    limit: number = 200,
    offset: number = 0,
  ): Promise<{
    messages: Array<{
      id: string;
      timestamp: string;
      bot_id: string;
      bot_name: string;
      pipeline_id: string;
      pipeline_name: string;
      message_content: string;
      session_id: string;
      status: string;
      level: string;
      platform: string | null;
      user_id: string | null;
      user_name: string | null;
      runner_name: string | null;
      variables: string | null;
      role: string | null;
    }>;
    total: number;
  }> {
    const queryParams = new URLSearchParams();
    queryParams.append('sessionId', sessionId);
    queryParams.append('limit', limit.toString());
    queryParams.append('offset', offset.toString());
    return this.get(`/api/v1/monitoring/messages?${queryParams.toString()}`);
  }

  // ============ File management API ============
  public uploadDocumentFile(file: File): Promise<{ file_id: string }> {
    const formData = new FormData();
    formData.append('file', file);

    return this.request<{ file_id: string }>({
      method: 'post',
      url: '/api/v1/files/documents',
      data: formData,
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    });
  }

  // ============ Knowledge Base API ============
  public getKnowledgeBases(): Promise<ApiRespKnowledgeBases> {
    return this.get('/api/v1/knowledge/bases');
  }

  public getKnowledgeBase(uuid: string): Promise<ApiRespKnowledgeBase> {
    return this.get(`/api/v1/knowledge/bases/${uuid}`);
  }

  public createKnowledgeBase(base: KnowledgeBase): Promise<{ uuid: string }> {
    return this.post('/api/v1/knowledge/bases', base);
  }

  public updateKnowledgeBase(
    uuid: string,
    base: KnowledgeBase,
  ): Promise<{ uuid: string }> {
    return this.put(`/api/v1/knowledge/bases/${uuid}`, base);
  }

  public uploadKnowledgeBaseFile(
    uuid: string,
    file_id: string,
    parserPluginId?: string,
  ): Promise<object> {
    return this.post(`/api/v1/knowledge/bases/${uuid}/files`, {
      file_id,
      parser_plugin_id: parserPluginId,
    });
  }

  public getKnowledgeBaseFiles(
    uuid: string,
  ): Promise<ApiRespKnowledgeBaseFiles> {
    return this.get(`/api/v1/knowledge/bases/${uuid}/files`);
  }

  public deleteKnowledgeBaseFile(
    uuid: string,
    file_id: string,
  ): Promise<object> {
    return this.delete(`/api/v1/knowledge/bases/${uuid}/files/${file_id}`);
  }

  public deleteKnowledgeBase(uuid: string): Promise<object> {
    return this.delete(`/api/v1/knowledge/bases/${uuid}`);
  }

  public retrieveKnowledgeBase(
    uuid: string,
    query: string,
    retrievalSettings?: Record<string, unknown>,
  ): Promise<ApiRespKnowledgeBaseRetrieve> {
    return this.post(`/api/v1/knowledge/bases/${uuid}/retrieve`, {
      query,
      retrieval_settings: retrievalSettings ?? {},
    });
  }

  // ============ Knowledge Engines API ============
  public getKnowledgeEngines(): Promise<ApiRespKnowledgeEngines> {
    return this.get('/api/v1/knowledge/engines');
  }

  // ============ Parsers API ============
  public listParsers(mimeType?: string): Promise<ApiRespParsers> {
    const params = mimeType ? `?mime_type=${encodeURIComponent(mimeType)}` : '';
    return this.get(`/api/v1/knowledge/parsers${params}`);
  }

  // ============ Plugins API ============
  public getPlugins(): Promise<ApiRespPlugins> {
    return this.get('/api/v1/plugins');
  }

  public getPlugin(author: string, name: string): Promise<ApiRespPlugin> {
    return this.get(`/api/v1/plugins/${author}/${name}`);
  }

  public getPluginConfig(
    author: string,
    name: string,
  ): Promise<ApiRespPluginConfig> {
    return this.get(`/api/v1/plugins/${author}/${name}/config`);
  }

  public updatePluginConfig(
    author: string,
    name: string,
    config: object,
  ): Promise<object> {
    return this.put(`/api/v1/plugins/${author}/${name}/config`, config);
  }

  public uploadPluginConfigFile(file: File): Promise<{ file_key: string }> {
    const formData = new FormData();
    formData.append('file', file);

    return this.request<{ file_key: string }>({
      method: 'post',
      url: '/api/v1/plugins/config-files',
      data: formData,
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    });
  }

  public deletePluginConfigFile(
    fileKey: string,
  ): Promise<{ deleted: boolean }> {
    return this.delete(`/api/v1/plugins/config-files/${fileKey}`);
  }

  public getPluginReadme(
    author: string,
    name: string,
    language: string = 'en',
  ): Promise<{ readme: string }> {
    return this.get(
      `/api/v1/plugins/${author}/${name}/readme?language=${language}`,
    );
  }

  public getPluginAssetURL(
    author: string,
    name: string,
    filepath: string,
  ): string {
    return (
      this.instance.defaults.baseURL +
      `/api/v1/plugins/${author}/${name}/assets/${filepath}`
    );
  }

  public getPluginIconURL(author: string, name: string): string {
    if (this.instance.defaults.baseURL === '/') {
      const url = window.location.href;
      const baseURL = url.split('/').slice(0, 3).join('/');
      return `${baseURL}/api/v1/plugins/${author}/${name}/icon`;
    }
    return (
      this.instance.defaults.baseURL + `/api/v1/plugins/${author}/${name}/icon`
    );
  }

  public installPluginFromGithub(
    assetUrl: string,
    owner: string,
    repo: string,
    releaseTag: string,
  ): Promise<AsyncTaskCreatedResp> {
    return this.post('/api/v1/plugins/install/github', {
      asset_url: assetUrl,
      owner,
      repo,
      release_tag: releaseTag,
    });
  }

  public getGithubReleases(repoUrl: string): Promise<{
    releases: Array<{
      id: number;
      tag_name: string;
      name: string;
      published_at: string;
      prerelease: boolean;
      draft: boolean;
    }>;
    owner: string;
    repo: string;
  }> {
    return this.post('/api/v1/plugins/github/releases', { repo_url: repoUrl });
  }

  public getGithubReleaseAssets(
    owner: string,
    repo: string,
    releaseId: number,
  ): Promise<{
    assets: Array<{
      id: number;
      name: string;
      size: number;
      download_url: string;
      content_type: string;
    }>;
  }> {
    return this.post('/api/v1/plugins/github/release-assets', {
      owner,
      repo,
      release_id: releaseId,
    });
  }

  public installPluginFromLocal(file: File): Promise<AsyncTaskCreatedResp> {
    const formData = new FormData();
    formData.append('file', file);
    return this.postFile('/api/v1/plugins/install/local', formData);
  }

  public installPluginFromMarketplace(
    author: string,
    name: string,
    version: string,
  ): Promise<AsyncTaskCreatedResp> {
    return this.post('/api/v1/plugins/install/marketplace', {
      plugin_author: author,
      plugin_name: name,
      plugin_version: version,
    });
  }

  public removePlugin(
    author: string,
    name: string,
    deleteData: boolean = false,
  ): Promise<AsyncTaskCreatedResp> {
    return this.delete(
      `/api/v1/plugins/${author}/${name}?delete_data=${deleteData}`,
    );
  }

  public upgradePlugin(
    author: string,
    name: string,
  ): Promise<AsyncTaskCreatedResp> {
    return this.post(`/api/v1/plugins/${author}/${name}/upgrade`);
  }

  // ============ MCP API ============
  public getMCPServers(): Promise<ApiRespMCPServers> {
    return this.get('/api/v1/mcp/servers');
  }

  // ========== Tools ==========

  public getTools(): Promise<ApiRespTools> {
    return this.get('/api/v1/tools');
  }

  public getToolDetail(toolName: string): Promise<ApiRespToolDetail> {
    return this.get(`/api/v1/tools/${toolName}`);
  }

  public getMCPServer(serverName: string): Promise<ApiRespMCPServer> {
    return this.get(`/api/v1/mcp/servers/${serverName}`);
  }

  public createMCPServer(server: MCPServer): Promise<AsyncTaskCreatedResp> {
    return this.post('/api/v1/mcp/servers', server);
  }

  public updateMCPServer(
    serverName: string,
    server: Partial<MCPServer>,
  ): Promise<AsyncTaskCreatedResp> {
    return this.put(`/api/v1/mcp/servers/${serverName}`, server);
  }

  public deleteMCPServer(serverName: string): Promise<AsyncTaskCreatedResp> {
    return this.delete(`/api/v1/mcp/servers/${serverName}`);
  }

  public toggleMCPServer(
    serverName: string,
    target_enabled: boolean,
  ): Promise<AsyncTaskCreatedResp> {
    return this.put(`/api/v1/mcp/servers/${serverName}`, {
      enable: target_enabled,
    });
  }

  public testMCPServer(
    serverName: string,
    serverData: object,
  ): Promise<AsyncTaskCreatedResp> {
    return this.post(`/api/v1/mcp/servers/${serverName}/test`, serverData);
  }

  public installMCPServerFromGithub(
    source: string,
  ): Promise<AsyncTaskCreatedResp> {
    return this.post('/api/v1/mcp/install/github', { source });
  }

  public installMCPServerFromSSE(
    source: object,
  ): Promise<AsyncTaskCreatedResp> {
    return this.post('/api/v1/mcp/servers', { source });
  }

  // ============ System API ============
  public getSystemInfo(): Promise<ApiRespSystemInfo> {
    return this.get('/api/v1/system/info');
  }

  public updateWizardStatus(status: 'skipped' | 'completed'): Promise<void> {
    return this.post('/api/v1/system/wizard/completed', { status });
  }

  public saveWizardProgress(progress: {
    step: number;
    selected_adapter: string | null;
    created_bot_uuid: string | null;
    bot_saved: boolean;
    selected_runner: string | null;
  }): Promise<void> {
    return this.put('/api/v1/system/wizard/progress', progress);
  }

  public getAsyncTasks(params?: {
    type?: string;
    kind?: string;
  }): Promise<ApiRespAsyncTasks> {
    const query = new URLSearchParams();
    if (params?.type) query.set('type', params.type);
    if (params?.kind) query.set('kind', params.kind);
    const qs = query.toString();
    return this.get(`/api/v1/system/tasks${qs ? `?${qs}` : ''}`);
  }

  public getAsyncTask(id: number): Promise<AsyncTask> {
    return this.get(`/api/v1/system/tasks/${id}`);
  }

  public getPluginSystemStatus(): Promise<ApiRespPluginSystemStatus> {
    return this.get('/api/v1/system/status/plugin-system');
  }

  // ============ RAG Migration API ============
  public getRagMigrationStatus(): Promise<RagMigrationStatusResp> {
    return this.get('/api/v1/knowledge/migration/status');
  }

  public executeRagMigration(
    installPlugin: boolean = true,
  ): Promise<AsyncTaskCreatedResp> {
    return this.post('/api/v1/knowledge/migration/execute', {
      install_plugin: installPlugin,
    });
  }

  public dismissRagMigration(): Promise<object> {
    return this.post('/api/v1/knowledge/migration/dismiss');
  }

  public getPluginDebugInfo(): Promise<{
    debug_url: string;
    plugin_debug_key: string;
  }> {
    return this.get('/api/v1/plugins/debug-info');
  }

  // ============ User API ============
  public checkIfInited(): Promise<{ initialized: boolean }> {
    return this.get('/api/v1/user/init');
  }

  public initUser(user: string, password: string): Promise<object> {
    return this.post('/api/v1/user/init', { user, password });
  }

  public authUser(user: string, password: string): Promise<ApiRespUserToken> {
    return this.post('/api/v1/user/auth', { user, password });
  }

  public checkUserToken(): Promise<ApiRespUserToken> {
    return this.get('/api/v1/user/check-token');
  }

  public resetPassword(
    user: string,
    recoveryKey: string,
    newPassword: string,
  ): Promise<{ user: string }> {
    return this.post('/api/v1/user/reset-password', {
      user,
      recovery_key: recoveryKey,
      new_password: newPassword,
    });
  }

  public changePassword(
    currentPassword: string,
    newPassword: string,
  ): Promise<{ user: string }> {
    return this.post('/api/v1/user/change-password', {
      current_password: currentPassword,
      new_password: newPassword,
    });
  }

  public getUserInfo(): Promise<{
    user: string;
    account_type: 'local' | 'space';
    has_password: boolean;
  }> {
    return this.get('/api/v1/user/info');
  }

  public getSpaceCredits(): Promise<{ credits: number | null }> {
    return this.get('/api/v1/user/space-credits');
  }

  public getAccountInfo(): Promise<{
    initialized: boolean;
    account_type?: 'local' | 'space';
    has_password?: boolean;
  }> {
    return this.get('/api/v1/user/account-info');
  }

  public setPassword(
    newPassword: string,
    currentPassword?: string,
  ): Promise<{ user: string }> {
    return this.post('/api/v1/user/set-password', {
      new_password: newPassword,
      current_password: currentPassword,
    });
  }

  public async bindSpaceAccount(
    code: string,
    state: string,
  ): Promise<{
    token: string;
    user: string;
    account_type: 'local' | 'space';
  }> {
    const response = await this.instance.post('/api/v1/user/bind-space', {
      code,
      state,
    });
    if (response.data.code !== 0) {
      throw {
        code: response.data.code,
        msg: response.data.msg || 'Unknown error',
      };
    }
    return response.data.data;
  }

  // ============ Space OAuth API (Redirect Flow) ============
  public getSpaceAuthorizeUrl(
    redirectUri: string,
    state?: string,
  ): Promise<{
    authorize_url: string;
  }> {
    const params: Record<string, string> = { redirect_uri: redirectUri };
    if (state) {
      params.state = state;
    }
    return this.get('/api/v1/user/space/authorize-url', params);
  }

  public async exchangeSpaceOAuthCode(code: string): Promise<{
    token: string;
    user: string;
  }> {
    const response = await this.instance.post('/api/v1/user/space/callback', {
      code,
    });
    if (response.data.code !== 0) {
      throw {
        code: response.data.code,
        msg: response.data.msg || 'Unknown error',
      };
    }
    return response.data.data;
  }

  // ============ Monitoring API ============
  public getMonitoringData(params: {
    botId?: string[];
    pipelineId?: string[];
    startTime?: string;
    endTime?: string;
    limit?: number;
  }): Promise<{
    overview: {
      total_messages: number;
      llm_calls: number;
      embedding_calls: number;
      model_calls: number;
      success_rate: number;
      active_sessions: number;
    };
    messages: Array<{
      id: string;
      timestamp: string;
      bot_id: string;
      bot_name: string;
      pipeline_id: string;
      pipeline_name: string;
      message_content: string;
      session_id: string;
      status: string;
      level: string;
      platform?: string;
      user_id?: string;
      runner_name?: string;
      variables?: string;
    }>;
    llmCalls: Array<{
      id: string;
      timestamp: string;
      model_name: string;
      input_tokens: number;
      output_tokens: number;
      total_tokens: number;
      duration: number;
      cost?: number;
      status: string;
      bot_id: string;
      bot_name: string;
      pipeline_id: string;
      pipeline_name: string;
      error_message?: string;
      message_id?: string;
    }>;
    embeddingCalls: Array<{
      id: string;
      timestamp: string;
      model_name: string;
      prompt_tokens: number;
      total_tokens: number;
      duration: number;
      input_count: number;
      status: string;
      error_message?: string;
      knowledge_base_id?: string;
      query_text?: string;
      session_id?: string;
      message_id?: string;
      call_type?: string;
    }>;
    sessions: Array<{
      session_id: string;
      bot_id: string;
      bot_name: string;
      pipeline_id: string;
      pipeline_name: string;
      message_count: number;
      last_activity: string;
      start_time: string;
      platform?: string;
      user_id?: string;
    }>;
    errors: Array<{
      id: string;
      timestamp: string;
      error_type: string;
      error_message: string;
      bot_id: string;
      bot_name: string;
      pipeline_id: string;
      pipeline_name: string;
      session_id?: string;
      stack_trace?: string;
      message_id?: string;
    }>;
    totalCount: {
      messages: number;
      llmCalls: number;
      embeddingCalls: number;
      sessions: number;
      errors: number;
    };
  }> {
    const queryParams = new URLSearchParams();
    if (params.botId) {
      params.botId.forEach((id) => queryParams.append('botId', id));
    }
    if (params.pipelineId) {
      params.pipelineId.forEach((id) => queryParams.append('pipelineId', id));
    }
    if (params.startTime) {
      queryParams.append('startTime', params.startTime);
    }
    if (params.endTime) {
      queryParams.append('endTime', params.endTime);
    }
    if (params.limit) {
      queryParams.append('limit', params.limit.toString());
    }

    return this.get(`/api/v1/monitoring/data?${queryParams.toString()}`);
  }

  public getMonitoringOverview(params: {
    botId?: string[];
    pipelineId?: string[];
    startTime?: string;
    endTime?: string;
  }): Promise<{
    total_messages: number;
    llm_calls: number;
    success_rate: number;
    active_sessions: number;
  }> {
    const queryParams = new URLSearchParams();
    if (params.botId) {
      params.botId.forEach((id) => queryParams.append('botId', id));
    }
    if (params.pipelineId) {
      params.pipelineId.forEach((id) => queryParams.append('pipelineId', id));
    }
    if (params.startTime) {
      queryParams.append('startTime', params.startTime);
    }
    if (params.endTime) {
      queryParams.append('endTime', params.endTime);
    }

    return this.get(`/api/v1/monitoring/overview?${queryParams.toString()}`);
  }

  // ============ Survey API ============
  public getSurveyPending(): Promise<{
    survey: {
      survey_id: string;
      version: number;
      title: Record<string, string>;
      description: Record<string, string>;
      questions: SurveyQuestion[];
    } | null;
  }> {
    return this.get('/api/v1/survey/pending');
  }

  public submitSurveyResponse(
    surveyId: string,
    answers: Record<string, unknown>,
    completed: boolean = true,
  ): Promise<object> {
    return this.post('/api/v1/survey/respond', {
      survey_id: surveyId,
      answers,
      completed,
    });
  }

  public dismissSurvey(surveyId: string): Promise<object> {
    return this.post('/api/v1/survey/dismiss', { survey_id: surveyId });
  }

  // ============ Workflow API ============
  public getWorkflows(
    sortBy?: string,
    sortOrder?: string,
  ): Promise<ApiRespWorkflows> {
    const params = new URLSearchParams();
    if (sortBy) params.append('sort_by', sortBy);
    if (sortOrder) params.append('sort_order', sortOrder);
    const queryString = params.toString();
    return this.get(`/api/v1/workflows${queryString ? `?${queryString}` : ''}`);
  }

  public getWorkflow(uuid: string): Promise<ApiRespWorkflow> {
    return this.get(`/api/v1/workflows/${uuid}`);
  }

  public createWorkflow(
    workflow: CreateWorkflowRequest,
  ): Promise<{ uuid: string }> {
    return this.post('/api/v1/workflows', workflow);
  }

  public updateWorkflow(
    uuid: string,
    workflow: UpdateWorkflowRequest,
  ): Promise<object> {
    return this.put(`/api/v1/workflows/${uuid}`, workflow);
  }

  public deleteWorkflow(uuid: string): Promise<object> {
    return this.delete(`/api/v1/workflows/${uuid}`);
  }

  public copyWorkflow(uuid: string): Promise<{ uuid: string }> {
    return this.post(`/api/v1/workflows/${uuid}/copy`);
  }

  public publishWorkflow(uuid: string): Promise<{ version: number }> {
    return this.post(`/api/v1/workflows/${uuid}/publish`);
  }

  public getWorkflowVersions(uuid: string): Promise<ApiRespWorkflowVersions> {
    return this.get(`/api/v1/workflows/${uuid}/versions`);
  }

  public rollbackWorkflow(
    uuid: string,
    version: number,
  ): Promise<{ version: number }> {
    return this.post(`/api/v1/workflows/${uuid}/rollback`, { version });
  }

  public executeWorkflow(
    uuid: string,
    request: ExecuteWorkflowRequest,
  ): Promise<{ execution_id: string }> {
    return this.post(`/api/v1/workflows/${uuid}/execute`, request);
  }

  public getWorkflowExecutions(
    uuid: string,
    limit?: number,
    offset?: number,
  ): Promise<ApiRespWorkflowExecutions> {
    const params = new URLSearchParams();
    if (limit) params.append('limit', limit.toString());
    if (offset) params.append('offset', offset.toString());
    const queryString = params.toString();
    return this.get(
      `/api/v1/workflows/${uuid}/executions${queryString ? `?${queryString}` : ''}`,
    );
  }

  public getWorkflowExecution(
    workflowUuid: string,
    executionUuid: string,
  ): Promise<ApiRespWorkflowExecution> {
    const url = `/api/v1/workflows/${workflowUuid}/executions/${executionUuid}`;
    console.debug('[WorkflowExecution] requesting execution detail', {
      url,
      workflowUuid,
      executionUuid,
      baseURL: this.baseURL,
      stack: new Error().stack,
    });
    return this.get(url);
  }

  public cancelWorkflowExecution(
    workflowUuid: string,
    executionUuid: string,
  ): Promise<object> {
    return this.post(`/api/v1/executions/${executionUuid}/cancel`);
  }

  public getWorkflowNodeTypes(): Promise<ApiRespWorkflowNodeTypes> {
    return this.get('/api/v1/workflows/_/node-types');
  }

  public toggleWorkflow(uuid: string, enabled: boolean): Promise<object> {
    return this.put(`/api/v1/workflows/${uuid}`, { is_enabled: enabled });
  }

  // ============ Workflow WebSocket Chat API ============
  public getWorkflowWebSocketHistoryMessages(
    workflowId: string,
    sessionType: string,
  ): Promise<ApiRespWebChatMessages> {
    return this.get(
      `/api/v1/workflows/${workflowId}/ws/messages/${sessionType}`,
    );
  }

  public async uploadWorkflowWebSocketImage(
    workflowId: string,
    imageFile: File,
  ): Promise<{ file_key: string }> {
    const formData = new FormData();
    formData.append('file', imageFile);

    return this.postFile(`/api/v1/files/images`, formData);
  }

  public resetWorkflowWebSocketSession(
    workflowId: string,
    sessionType: string,
  ): Promise<{ message: string }> {
    return this.post(`/api/v1/workflows/${workflowId}/ws/reset/${sessionType}`);
  }

  // ============ Workflow Debug API ============
  public startWorkflowDebug(
    uuid: string,
    options: {
      context?: {
        message_content?: string;
        sender_id?: string;
        sender_name?: string;
        platform?: string;
        conversation_id?: string;
        is_group?: boolean;
      };
      variables?: Record<string, unknown>;
      breakpoints?: string[];
    },
  ): Promise<{ execution_id: string }> {
    return this.post(`/api/v1/workflows/${uuid}/debug/start`, options);
  }

  public pauseWorkflowDebug(uuid: string, executionId: string): Promise<object> {
    return this.post(`/api/v1/workflows/${uuid}/debug/${executionId}/pause`);
  }

  public resumeWorkflowDebug(uuid: string, executionId: string): Promise<object> {
    return this.post(`/api/v1/workflows/${uuid}/debug/${executionId}/resume`);
  }

  public stepWorkflowDebug(
    uuid: string,
    executionId: string,
  ): Promise<{
    node_id?: string;
    node_state?: {
      status: string;
      inputs?: Record<string, unknown>;
      outputs?: Record<string, unknown>;
      error?: string;
    };
    completed: boolean;
  }> {
    return this.post(`/api/v1/workflows/${uuid}/debug/${executionId}/step`);
  }

  public stopWorkflowDebug(uuid: string, executionId: string): Promise<object> {
    return this.post(`/api/v1/workflows/${uuid}/debug/${executionId}/stop`);
  }

  public getWorkflowDebugState(
    uuid: string,
    executionId: string,
  ): Promise<{
    status: string;
    current_node_id?: string;
    node_states?: Record<
      string,
      {
        status: string;
        inputs?: Record<string, unknown>;
        outputs?: Record<string, unknown>;
        error?: string;
        startTime?: string;
        endTime?: string;
        duration?: number;
      }
    >;
    new_logs?: Array<{
      level: 'info' | 'warning' | 'error' | 'debug';
      nodeId?: string;
      message: string;
      data?: Record<string, unknown>;
    }>;
    error?: string;
  }> {
    return this.get(`/api/v1/workflows/${uuid}/debug/${executionId}/state`);
  }

  // ============ Workflow Execution Logs API ============
  public getWorkflowExecutionLogs(
    workflowUuid: string,
    executionUuid: string,
    limit?: number,
    offset?: number,
  ): Promise<{
    logs: Array<{
      id: string;
      timestamp: string;
      level: string;
      node_id?: string;
      message: string;
      data?: Record<string, unknown>;
    }>;
    total: number;
  }> {
    const params = new URLSearchParams();
    if (limit) params.append('limit', limit.toString());
    if (offset) params.append('offset', offset.toString());
    const queryString = params.toString();
    return this.get(
      `/api/v1/workflows/${workflowUuid}/executions/${executionUuid}/logs${queryString ? `?${queryString}` : ''}`,
    );
  }

  public getWorkflowStats(uuid: string): Promise<{
    total_executions: number;
    successful_executions: number;
    failed_executions: number;
    success_rate: number;
    average_duration_ms: number;
    last_execution_time?: string;
  }> {
    return this.get(`/api/v1/workflows/${uuid}/stats`);
  }

  public rerunWorkflowExecution(
    workflowUuid: string,
    executionUuid: string,
  ): Promise<{ execution_uuid: string }> {
    return this.post(
      `/api/v1/workflows/${workflowUuid}/executions/${executionUuid}/rerun`,
    );
  }
}

export interface SurveyQuestion {
  id: string;
  type: 'single_select' | 'multi_select' | 'text';
  title: Record<string, string>;
  subtitle?: Record<string, string>;
  required: boolean;
  options?: SurveyOption[];
  placeholder?: Record<string, string>;
  max_length?: number;
}

export interface SurveyOption {
  id: string;
  label: Record<string, string>;
  has_input?: boolean;
}
