/**
 * Configurable API Client
 */

import type {
  Session,
  Message,
  HealthStatus,
  FileListResponse,
  FileReadResponse,
  FileTreeResponse,
  ServerConfig,
  CommandInfo,
  CommandSearchResult,
  CommandExecuteResult,
  CommandListResponse,
  CreateCommandInput,
  UpdateCommandInput,
  CommandContent,
  MCPServerStatus,
  MCPToolInfo,
  MCPConfig,
  HookConfig,
  FileHookConfig,
  ShellCommandConfig,
  HookTestResult,
  AgentListItem,
  AgentDetail,
  AgentInput,
  AgentDefaults,
  CheckpointListItem,
  CheckpointDetail,
  CheckpointStats,
  DiffInfo,
  FileDiffDetail,
  RestoreOptions,
  RestoreResult,
  SafetyCheckResult,
  UnrevertStatus,
  UnrevertResult,
  // Provider types
  ProviderListItem,
  ProviderDetail,
  ModelInfo,
  CustomProviderDefinition,
  ProviderConfig,
  ConnectionTestResult,
  // Context types
  ContextUsageInfo,
  CompressionResult,
  // File search types
  FileSearchResponse,
} from './types.js';

// Re-export types
export type {
  Session,
  Message,
  HealthStatus,
  FileInfo,
  FileListResponse,
  FileReadResponse,
  FileTreeNode,
  FileTreeResponse,
  ServerConfig,
  CommandInfo,
  CommandSearchResult,
  CommandExecuteResult,
  CommandListResponse,
  CreateCommandInput,
  UpdateCommandInput,
  CommandContent,
  MCPServerStatus,
  MCPServerStatusType,
  MCPToolInfo,
  MCPConfig,
  MCPServerConfigInfo,
  // Hooks types
  HookConfig,
  FileHookConfig,
  ShellCommandConfig,
  HookTestResult,
  // Agent types
  AgentMode,
  AgentModelConfig,
  AgentToolConfig,
  PermissionRule,
  AgentBashPermission,
  AgentFilePermission,
  AgentGitPermission,
  AgentPermission,
  AgentListItem,
  AgentDetail,
  AgentInput,
  AgentDefaults,
  // Checkpoint types
  CheckpointTrigger,
  FileChangeType,
  CheckpointListItem,
  CheckpointDetail,
  FileChange,
  DiffInfo,
  FileDiffDetail,
  RestoreMode,
  RestoreOptions,
  RestoreResult,
  SafetyCheckResult,
  CheckpointStats,
  UnrevertStatus,
  UnrevertResult,
  // Provider types
  BuiltinProviderType,
  ProviderType,
  ModelCapabilities,
  ModelInfo,
  ProviderListItem,
  ProviderDetail,
  CustomProviderDefinition,
  ProviderConfig,
  ConnectionTestResult,
  // Context compression types
  TokenUsage,
  ContextUsageInfo,
  CompressionStatus,
  CompressionType,
  CompressionResult,
  // WebSocket error types
  ConfigErrorPayload,
  // File search types
  FileSearchResult,
  FileSearchResponse,
  // Agent mode types
  AgentModeType,
} from './types.js';

// API Configuration
interface ApiConfig {
  baseUrl: string;
  wsBaseUrl: () => string;
  healthUrl: () => string;
}

let apiConfig: ApiConfig = {
  baseUrl: '/api',
  wsBaseUrl: () => {
    const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    return `${protocol}//${window.location.host}/api`;
  },
  healthUrl: () => '/health',
};

/**
 * Configure API client for different environments
 */
export function configureApiClient(config: {
  baseUrl: string;
  wsBaseUrl: string | (() => string);
  healthUrl?: string | (() => string);
}) {
  apiConfig = {
    baseUrl: config.baseUrl,
    wsBaseUrl:
      typeof config.wsBaseUrl === 'function'
        ? config.wsBaseUrl
        : () => config.wsBaseUrl as string,
    healthUrl: config.healthUrl
      ? typeof config.healthUrl === 'function'
        ? config.healthUrl
        : () => config.healthUrl as string
      : () => '/health',
  };
}

async function request<T>(method: string, path: string, body?: unknown): Promise<T> {
  const response = await fetch(`${apiConfig.baseUrl}${path}`, {
    method,
    headers: {
      'Content-Type': 'application/json',
    },
    body: body ? JSON.stringify(body) : undefined,
  });

  if (!response.ok) {
    const error = await response.json().catch(() => ({ error: response.statusText }));
    throw new Error(error.error || `HTTP ${response.status}`);
  }

  return response.json();
}

// Health
export async function getHealth(): Promise<HealthStatus> {
  const healthUrl = apiConfig.healthUrl();
  const response = await fetch(healthUrl);
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }
  return response.json();
}

// Sessions
export async function listSessions(): Promise<{ success: boolean; data: Session[] }> {
  return request('GET', '/sessions');
}

export async function createSession(name?: string): Promise<{ success: boolean; data: Session }> {
  return request('POST', '/sessions', { name });
}

export async function getSession(id: string): Promise<{ success: boolean; data: Session }> {
  return request('GET', `/sessions/${id}`);
}

export async function deleteSession(id: string): Promise<{ success: boolean }> {
  return request('DELETE', `/sessions/${id}`);
}

// Messages
export async function getMessages(
  sessionId: string
): Promise<{ success: boolean; data: Message[] }> {
  return request('GET', `/sessions/${sessionId}/messages`);
}

export async function sendMessage(
  sessionId: string,
  content: string
): Promise<{ success: boolean; data: Message }> {
  return request('POST', `/sessions/${sessionId}/messages`, { content });
}

// WebSocket
export function createWebSocket(sessionId: string): WebSocket {
  const wsBase = apiConfig.wsBaseUrl();
  return new WebSocket(`${wsBase}/ws/${sessionId}`);
}

// Files
export async function getWorkingDirectory(): Promise<{
  success: boolean;
  data: { workingDirectory: string; separator: string };
}> {
  return request('GET', '/files');
}

export async function listFiles(
  path: string = '.',
  showHidden: boolean = false
): Promise<FileListResponse> {
  const params = new URLSearchParams({ path });
  if (showHidden) params.set('hidden', 'true');
  return request('GET', `/files/list?${params}`);
}

export async function readFile(path: string): Promise<FileReadResponse> {
  return request('GET', `/files/read?path=${encodeURIComponent(path)}`);
}

export async function getFileTree(path: string = '.', depth: number = 3): Promise<FileTreeResponse> {
  const params = new URLSearchParams({ path, depth: String(depth) });
  return request('GET', `/files/tree?${params}`);
}

// Config
export async function getConfig(): Promise<{ success: boolean; data: ServerConfig }> {
  return request('GET', '/config');
}

export async function updateConfig(
  config: Partial<ServerConfig>
): Promise<{ success: boolean; data: ServerConfig }> {
  return request('PATCH', '/config', config);
}

// Commands
export async function listCommands(): Promise<{ success: boolean; data: CommandListResponse }> {
  return request('GET', '/commands');
}

export async function getCommand(name: string): Promise<{ success: boolean; data: CommandInfo }> {
  return request('GET', `/commands/${encodeURIComponent(name)}`);
}

export async function executeCommand(
  name: string,
  args: string = ''
): Promise<{ success: boolean; data?: CommandExecuteResult; error?: string }> {
  return request('POST', `/commands/${encodeURIComponent(name)}/execute`, {
    arguments: args,
  });
}

export async function searchCommands(
  query: string,
  limit: number = 10
): Promise<{ success: boolean; data: CommandSearchResult[] }> {
  return request('POST', '/commands/search', { query, limit });
}

export async function reloadCommands(): Promise<{
  success: boolean;
  data: { message: string; stats: { total: number; bySource: Record<string, number> } };
}> {
  return request('POST', '/commands/reload');
}

// Commands CRUD
export async function createCommand(
  input: CreateCommandInput
): Promise<{ success: boolean; data?: { name: string; path: string }; error?: string }> {
  return request('POST', '/commands', input);
}

export async function getCommandContent(
  name: string
): Promise<{ success: boolean; data?: CommandContent; error?: string }> {
  return request('GET', `/commands/${encodeURIComponent(name)}/content`);
}

export async function updateCommand(
  name: string,
  input: UpdateCommandInput
): Promise<{ success: boolean; data?: { name: string; path: string }; error?: string }> {
  return request('PUT', `/commands/${encodeURIComponent(name)}`, input);
}

export async function deleteCommand(
  name: string
): Promise<{ success: boolean; data?: { name: string; path: string }; error?: string }> {
  return request('DELETE', `/commands/${encodeURIComponent(name)}`);
}

// ============ MCP API ============

/**
 * 获取所有 MCP 服务器状态
 */
export async function listMCPServers(): Promise<{
  success: boolean;
  data: MCPServerStatus[];
  error?: string;
}> {
  return request('GET', '/mcp/servers');
}

/**
 * 获取单个 MCP 服务器详情
 */
export async function getMCPServer(name: string): Promise<{
  success: boolean;
  data?: MCPServerStatus;
  error?: string;
}> {
  return request('GET', `/mcp/servers/${encodeURIComponent(name)}`);
}

/**
 * 连接 MCP 服务器
 */
export async function connectMCPServer(name: string): Promise<{
  success: boolean;
  data?: { message: string; status: MCPServerStatus };
  error?: string;
}> {
  return request('POST', `/mcp/servers/${encodeURIComponent(name)}/connect`);
}

/**
 * 断开 MCP 服务器
 */
export async function disconnectMCPServer(name: string): Promise<{
  success: boolean;
  data?: { message: string; status: MCPServerStatus };
  error?: string;
}> {
  return request('POST', `/mcp/servers/${encodeURIComponent(name)}/disconnect`);
}

/**
 * 启用 MCP 服务器
 */
export async function enableMCPServer(name: string): Promise<{
  success: boolean;
  data?: { message: string; status: MCPServerStatus };
  error?: string;
}> {
  return request('POST', `/mcp/servers/${encodeURIComponent(name)}/enable`);
}

/**
 * 禁用 MCP 服务器
 */
export async function disableMCPServer(name: string): Promise<{
  success: boolean;
  data?: { message: string; status: MCPServerStatus };
  error?: string;
}> {
  return request('POST', `/mcp/servers/${encodeURIComponent(name)}/disable`);
}

/**
 * 获取所有 MCP 工具
 */
export async function listMCPTools(): Promise<{
  success: boolean;
  data: MCPToolInfo[];
  error?: string;
}> {
  return request('GET', '/mcp/tools');
}

/**
 * 获取单个 MCP 工具详情
 */
export async function getMCPTool(name: string): Promise<{
  success: boolean;
  data?: MCPToolInfo;
  error?: string;
}> {
  return request('GET', `/mcp/tools/${encodeURIComponent(name)}`);
}

/**
 * 获取 MCP 配置
 */
export async function getMCPConfig(): Promise<{
  success: boolean;
  data?: MCPConfig;
  error?: string;
}> {
  return request('GET', '/mcp/config');
}

// ============ Hooks API ============

/**
 * 获取完整钩子配置
 */
export async function getHooksConfig(): Promise<{
  success: boolean;
  data: HookConfig;
  error?: string;
}> {
  return request('GET', '/hooks/config');
}

/**
 * 更新完整钩子配置
 */
export async function updateHooksConfig(config: HookConfig): Promise<{
  success: boolean;
  data: HookConfig;
  error?: string;
}> {
  return request('PUT', '/hooks/config', config);
}

/**
 * 获取 file_edited 钩子配置
 */
export async function getFileEditedHooks(): Promise<{
  success: boolean;
  data: FileHookConfig;
  error?: string;
}> {
  return request('GET', '/hooks/file-edited');
}

/**
 * 更新 file_edited 钩子配置
 */
export async function updateFileEditedHooks(hooks: FileHookConfig): Promise<{
  success: boolean;
  data: FileHookConfig;
  error?: string;
}> {
  return request('PUT', '/hooks/file-edited', hooks);
}

/**
 * 获取 file_created 钩子配置
 */
export async function getFileCreatedHooks(): Promise<{
  success: boolean;
  data: FileHookConfig;
  error?: string;
}> {
  return request('GET', '/hooks/file-created');
}

/**
 * 更新 file_created 钩子配置
 */
export async function updateFileCreatedHooks(hooks: FileHookConfig): Promise<{
  success: boolean;
  data: FileHookConfig;
  error?: string;
}> {
  return request('PUT', '/hooks/file-created', hooks);
}

/**
 * 获取 file_deleted 钩子配置
 */
export async function getFileDeletedHooks(): Promise<{
  success: boolean;
  data: FileHookConfig;
  error?: string;
}> {
  return request('GET', '/hooks/file-deleted');
}

/**
 * 更新 file_deleted 钩子配置
 */
export async function updateFileDeletedHooks(hooks: FileHookConfig): Promise<{
  success: boolean;
  data: FileHookConfig;
  error?: string;
}> {
  return request('PUT', '/hooks/file-deleted', hooks);
}

/**
 * 获取 session_completed 钩子配置
 */
export async function getSessionCompletedHooks(): Promise<{
  success: boolean;
  data: ShellCommandConfig[];
  error?: string;
}> {
  return request('GET', '/hooks/session-completed');
}

/**
 * 更新 session_completed 钩子配置
 */
export async function updateSessionCompletedHooks(hooks: ShellCommandConfig[]): Promise<{
  success: boolean;
  data: ShellCommandConfig[];
  error?: string;
}> {
  return request('PUT', '/hooks/session-completed', hooks);
}

/**
 * 测试执行钩子命令
 */
export async function testHookCommand(command: ShellCommandConfig): Promise<{
  success: boolean;
  data?: HookTestResult;
  error?: string;
}> {
  return request('POST', '/hooks/test', command);
}

// ============ Agents API ============

/**
 * 获取所有 Agent 列表
 */
export async function listAgents(): Promise<{
  success: boolean;
  data: AgentListItem[];
  error?: string;
}> {
  return request('GET', '/agents');
}

/**
 * 获取单个 Agent 详情
 */
export async function getAgent(name: string): Promise<{
  success: boolean;
  data?: AgentDetail;
  error?: string;
}> {
  return request('GET', `/agents/${encodeURIComponent(name)}`);
}

/**
 * 创建新 Agent
 */
export async function createAgent(
  name: string,
  config: AgentInput
): Promise<{
  success: boolean;
  data?: AgentDetail;
  error?: string;
}> {
  return request('POST', '/agents', { name, ...config });
}

/**
 * 更新 Agent
 */
export async function updateAgent(
  name: string,
  config: AgentInput
): Promise<{
  success: boolean;
  data?: AgentDetail;
  error?: string;
}> {
  return request('PUT', `/agents/${encodeURIComponent(name)}`, config);
}

/**
 * 删除 Agent
 */
export async function deleteAgent(name: string): Promise<{
  success: boolean;
  error?: string;
}> {
  return request('DELETE', `/agents/${encodeURIComponent(name)}`);
}

/**
 * 获取预设 Agent 列表
 */
export async function listPresetAgents(): Promise<{
  success: boolean;
  data: AgentListItem[];
  error?: string;
}> {
  return request('GET', '/agents/presets');
}

/**
 * 获取全局默认配置
 */
export async function getAgentDefaults(): Promise<{
  success: boolean;
  data: AgentDefaults;
  error?: string;
}> {
  return request('GET', '/agents/defaults');
}

/**
 * 更新全局默认配置
 */
export async function updateAgentDefaults(defaults: AgentDefaults): Promise<{
  success: boolean;
  data: AgentDefaults;
  error?: string;
}> {
  return request('PUT', '/agents/defaults', defaults);
}

// ============ Checkpoints API ============

/**
 * 获取所有检查点列表
 */
export async function listCheckpoints(): Promise<{
  success: boolean;
  data: CheckpointListItem[];
  error?: string;
}> {
  return request('GET', '/checkpoints');
}

/**
 * 获取检查点统计信息
 */
export async function getCheckpointStats(): Promise<{
  success: boolean;
  data: CheckpointStats;
  error?: string;
}> {
  return request('GET', '/checkpoints/stats');
}

/**
 * 获取最新检查点
 */
export async function getLatestCheckpoint(): Promise<{
  success: boolean;
  data: CheckpointDetail | null;
  error?: string;
}> {
  return request('GET', '/checkpoints/latest');
}

/**
 * 获取单个检查点详情
 */
export async function getCheckpoint(id: string): Promise<{
  success: boolean;
  data?: CheckpointDetail;
  error?: string;
}> {
  return request('GET', `/checkpoints/${encodeURIComponent(id)}`);
}

/**
 * 创建手动检查点
 */
export async function createCheckpoint(options?: {
  name?: string;
  description?: string;
}): Promise<{
  success: boolean;
  data?: CheckpointDetail;
  error?: string;
}> {
  return request('POST', '/checkpoints', options || {});
}

/**
 * 删除检查点
 */
export async function deleteCheckpoint(id: string): Promise<{
  success: boolean;
  data?: { deleted: boolean };
  error?: string;
}> {
  return request('DELETE', `/checkpoints/${encodeURIComponent(id)}`);
}

/**
 * 获取检查点与当前工作区的差异
 */
export async function getCheckpointDiff(id: string): Promise<{
  success: boolean;
  data?: DiffInfo;
  error?: string;
}> {
  return request('GET', `/checkpoints/${encodeURIComponent(id)}/diff`);
}

/**
 * 获取单个文件的详细差异
 */
export async function getFileDiff(checkpointId: string, filePath: string): Promise<{
  success: boolean;
  data?: FileDiffDetail;
  error?: string;
}> {
  const params = new URLSearchParams({ path: filePath });
  return request('GET', `/checkpoints/${encodeURIComponent(checkpointId)}/file-diff?${params}`);
}

/**
 * 回滚到检查点
 */
export async function restoreCheckpoint(
  id: string,
  options?: RestoreOptions
): Promise<{
  success: boolean;
  data?: RestoreResult;
  error?: string;
}> {
  return request('POST', `/checkpoints/${encodeURIComponent(id)}/restore`, options || {});
}

/**
 * 预览回滚（dry run）
 */
export async function previewRestore(
  id: string,
  options?: { mode?: RestoreOptions['mode']; files?: string[] }
): Promise<{
  success: boolean;
  data?: RestoreResult;
  error?: string;
}> {
  const params = new URLSearchParams();
  if (options?.mode) params.set('mode', options.mode);
  if (options?.files) params.set('files', options.files.join(','));
  return request('GET', `/checkpoints/${encodeURIComponent(id)}/restore/preview?${params}`);
}

/**
 * 撤销最近一次回滚
 */
export async function unrevert(): Promise<{
  success: boolean;
  data?: UnrevertResult;
  error?: string;
}> {
  return request('POST', '/checkpoints/unrevert');
}

/**
 * 检查是否可撤销回滚
 */
export async function getUnrevertStatus(): Promise<{
  success: boolean;
  data?: UnrevertStatus;
  error?: string;
}> {
  return request('GET', '/checkpoints/unrevert/status');
}

/**
 * 执行安全检查
 */
export async function checkSafety(id: string): Promise<{
  success: boolean;
  data?: SafetyCheckResult;
  error?: string;
}> {
  return request('GET', `/checkpoints/${encodeURIComponent(id)}/safety-check`);
}

/**
 * 清理过期检查点
 */
export async function cleanupCheckpoints(): Promise<{
  success: boolean;
  data?: { deleted: number };
  error?: string;
}> {
  return request('POST', '/checkpoints/cleanup');
}

/**
 * 获取会话的所有检查点
 */
export async function getSessionCheckpoints(sessionId: string): Promise<{
  success: boolean;
  data: CheckpointListItem[];
  error?: string;
}> {
  return request('GET', `/checkpoints/sessions/${encodeURIComponent(sessionId)}`);
}

/**
 * 获取消息关联的检查点
 */
export async function getMessageCheckpoints(messageId: string): Promise<{
  success: boolean;
  data: CheckpointListItem[];
  error?: string;
}> {
  return request('GET', `/checkpoints/messages/${encodeURIComponent(messageId)}`);
}

// ============ Providers API ============

/**
 * 获取所有提供商列表
 */
export async function listProviders(): Promise<{
  success: boolean;
  data: ProviderListItem[];
  error?: string;
}> {
  return request('GET', '/providers');
}

/**
 * 获取单个提供商详情
 */
export async function getProvider(id: string): Promise<{
  success: boolean;
  data?: ProviderDetail;
  error?: string;
}> {
  return request('GET', `/providers/${encodeURIComponent(id)}`);
}

/**
 * 获取提供商的模型列表
 */
export async function getProviderModels(id: string): Promise<{
  success: boolean;
  data: ModelInfo[];
  error?: string;
}> {
  return request('GET', `/providers/${encodeURIComponent(id)}/models`);
}

/**
 * 测试提供商连接
 */
export async function testProviderConnection(
  id: string,
  apiKey?: string
): Promise<{
  success: boolean;
  data: ConnectionTestResult;
  error?: string;
}> {
  return request('POST', `/providers/${encodeURIComponent(id)}/test`, apiKey ? { apiKey } : {});
}

/**
 * 注册自定义提供商
 */
export async function registerProvider(
  definition: CustomProviderDefinition
): Promise<{
  success: boolean;
  message?: string;
  error?: string;
}> {
  return request('POST', '/providers', definition);
}

/**
 * 更新提供商配置
 */
export async function updateProviderConfig(
  id: string,
  config: ProviderConfig
): Promise<{
  success: boolean;
  message?: string;
  error?: string;
}> {
  return request('PUT', `/providers/${encodeURIComponent(id)}`, config);
}

/**
 * 删除自定义提供商
 */
export async function deleteProvider(id: string): Promise<{
  success: boolean;
  message?: string;
  error?: string;
}> {
  return request('DELETE', `/providers/${encodeURIComponent(id)}`);
}

/**
 * 添加自定义模型
 */
export async function addProviderModel(
  providerId: string,
  model: ModelInfo
): Promise<{
  success: boolean;
  message?: string;
  error?: string;
}> {
  return request('POST', `/providers/${encodeURIComponent(providerId)}/models`, model);
}

/**
 * 删除自定义模型
 */
export async function deleteProviderModel(
  providerId: string,
  modelId: string
): Promise<{
  success: boolean;
  message?: string;
  error?: string;
}> {
  return request('DELETE', `/providers/${encodeURIComponent(providerId)}/models/${encodeURIComponent(modelId)}`);
}

// ============ Context Compression API ============

/**
 * 获取会话上下文使用情况
 */
export async function getContextUsage(sessionId: string): Promise<{
  success: boolean;
  data?: ContextUsageInfo;
  error?: string;
}> {
  return request('GET', `/sessions/${encodeURIComponent(sessionId)}/context`);
}

/**
 * 触发上下文压缩
 */
export async function compressContext(
  sessionId: string,
  options?: { force?: boolean }
): Promise<{
  success: boolean;
  data?: CompressionResult;
  error?: string;
}> {
  return request('POST', `/sessions/${encodeURIComponent(sessionId)}/compress`, options || {});
}

// ============ File Search API ============

/**
 * 模糊搜索项目文件
 */
export async function searchFiles(
  query: string = '',
  limit: number = 10,
  type: 'file' | 'directory' | 'all' = 'file'
): Promise<FileSearchResponse> {
  const params = new URLSearchParams({
    query,
    limit: String(limit),
    type,
  });
  return request('GET', `/files/search?${params}`);
}
