/**
 * Agent Adapter
 *
 * 将 core 模块的 Agent 适配到 Server 环境
 * 处理流式输出、事件推送等
 *
 * 使用接口定义避免直接依赖 @ai-assistant/core 类型
 */

import type { SessionStatus } from '../types.js';
import { getSessionManager } from '../session/manager.js';
import { broadcastToSession } from '../ws.js';
import { emitStatusEvent, emitLogEvent } from '../sse.js';
import { createServerPermissionCallback, setSessionAutoApprove } from '../permission/handler.js';
import { getConfig } from '../routes/config.js';

// ============================================================================
// Core 模块接口定义（避免直接依赖 @ai-assistant/core 类型）
// ============================================================================

/**
 * Token 使用情况接口
 */
export interface TokenUsage {
  input: number;
  contextLimit: number;
  available: number;
  usagePercent: number;
}

/**
 * 压缩结果接口
 */
export interface CompressionResult {
  type: 'prune' | 'compaction' | 'both' | 'none';
  status: 'success' | 'noop' | 'failed_empty_summary' | 'failed_token_inflated' | 'failed_error';
  freedTokens: number;
  error?: string;
  originalTokens?: number;
  summaryTokens?: number;
}

/**
 * Chat 返回结果
 */
interface ChatResult {
  text: string;
  messages: unknown[];
}

/**
 * Session Manager 接口（Core 的 SessionManager）
 */
interface SessionManagerInstance {
  init(workdir: string): Promise<unknown>;
  getSession(): { id: string; messages: unknown[] } | null;
  setMessages(messages: unknown[]): Promise<void>;
  setDiscoveredTools(tools: string[]): Promise<void>;
  save(): Promise<void>;
  close(): Promise<void>;
  restoreSession(sessionId: string): Promise<unknown | null>;
}

/**
 * Session Manager 构造函数接口
 */
interface SessionManagerConstructor {
  new (): SessionManagerInstance;
}

/**
 * 工具开始信息
 */
interface ToolStartInfo {
  id: string;
  toolName: string;
  args: Record<string, unknown>;
}

/**
 * 工具结束信息
 */
interface ToolEndInfo {
  id: string;
  status: 'completed' | 'error';
  result?: unknown;
  error?: string;
  duration?: number;
}

/**
 * Chat 选项接口
 */
interface ChatOptions {
  onStream?: (chunk: string) => void;
  onToolStart?: (info: ToolStartInfo) => void;
  onToolEnd?: (info: ToolEndInfo) => void;
  abortSignal?: AbortSignal;
}

/**
 * Agent 模式选项
 */
export interface AgentModeOptions {
  /** Agent 模式 (build/plan) */
  agentMode?: 'build' | 'plan';
  /** 是否自动授权文件写入/编辑 */
  autoApprove?: boolean;
}

/**
 * Agent 实例接口
 */
interface AgentInstance {
  setRegistry(registry: unknown): void;
  setSessionManager(manager: SessionManagerInstance): void;
  chat(message: string, options?: ChatOptions): Promise<ChatResult>;
  getToolCount(): { core: number; discovered: number; total: number };
  getContextUsageFormatted(): string;
  getContextUsage(): TokenUsage;
  compactHistory(): Promise<{ freedTokens: number; type: string }>;
  getCompressionManager(): {
    shouldCompress(messages: unknown[]): boolean;
  };
  getHistory(): unknown[];
  setAgentMode?(mode: 'build' | 'plan'): void;
  /** 切换模式（保留对话历史） */
  switchMode?(mode: 'build' | 'plan', preserveHistory?: boolean): void;
  setAutoApprove?(config: { file?: { write?: 'allow'; edit?: 'allow' } }): void;
  clearAutoApprove?(): void;
}

/**
 * Agent 构造函数接口
 */
interface AgentConstructor {
  new (config: unknown): AgentInstance;
}

/**
 * Tool Registry 接口
 */
interface ToolRegistry {
  getCoreTools(): unknown[];
  getAllTools(): unknown[];
}

/**
 * Permission Manager 接口
 */
interface PermissionManager {
  setAskCallback(callback: (ctx: unknown) => Promise<{ allow: boolean; remember?: boolean }>): void;
}

/**
 * Provider Registry 接口
 */
interface ProviderRegistryInterface {
  init(): Promise<void>;
  isInitialized(): boolean;
}

/**
 * Agent Registry 接口
 */
interface AgentRegistryInterface {
  init(): Promise<void>;
  isInitialized(): boolean;
}

/**
 * Core 模块接口
 */
interface CoreModule {
  Agent: AgentConstructor;
  SessionManager: SessionManagerConstructor;
  toolRegistry: ToolRegistry;
  loadConfig: () => unknown;
  saveConfig: (config: Record<string, unknown>) => void;
  getPermissionManager: (projectRoot?: string) => PermissionManager;
  getProviderRegistry: () => ProviderRegistryInterface;
  agentRegistry: AgentRegistryInterface;
}

// ============================================================================
// 模块状态
// ============================================================================

// Core 模块引用
let coreModule: CoreModule | null = null;

// Agent 实例缓存（每个 session 一个）
const agentCache: Map<string, AgentInstance> = new Map();

// SessionManager 实例缓存（每个 session 一个）
const sessionManagerCache: Map<string, SessionManagerInstance> = new Map();

// AbortController 缓存（每个 session 一个，用于取消正在进行的请求）
const abortControllerCache: Map<string, AbortController> = new Map();

// 配置错误缓存（用于向客户端返回友好错误）
let lastConfigError: { provider: string; message: string } | null = null;

// ============================================================================
// 公共 API
// ============================================================================

/**
 * 初始化 core 模块
 */
export async function initCore(): Promise<boolean> {
  try {
    // 使用变量避免 TypeScript 静态分析 import 路径
    const corePath = '@ai-assistant/core';
    // eslint-disable-next-line @typescript-eslint/no-require-imports
    const core = (await import(/* webpackIgnore: true */ corePath)) as unknown as CoreModule;

    // 验证模块结构
    if (!core.Agent || !core.toolRegistry || !core.loadConfig) {
      console.warn('[Agent] Core module missing required exports');
      return false;
    }

    // 初始化 ProviderRegistry（加载用户配置）
    const providerRegistry = core.getProviderRegistry();
    if (!providerRegistry.isInitialized()) {
      await providerRegistry.init();
      console.log('[Agent] ProviderRegistry initialized');
    }

    // 初始化 AgentRegistry（加载用户自定义 Agent 配置）
    const agentRegistry = core.agentRegistry;
    if (!agentRegistry.isInitialized()) {
      await agentRegistry.init();
      console.log('[Agent] AgentRegistry initialized');
    }

    coreModule = core;
    console.log('[Agent] Core module loaded');
    return true;
  } catch (error) {
    console.warn('[Agent] Core module not available:', error);
    return false;
  }
}

/**
 * 检查 core 模块是否可用
 */
export function isCoreAvailable(): boolean {
  return coreModule !== null;
}

/**
 * 获取或创建 Agent 实例
 *
 * @returns Agent 实例，或 null（Core 不可用或配置错误）
 */
export async function getOrCreateAgent(sessionId: string): Promise<AgentInstance | null> {
  // 清除之前的配置错误
  lastConfigError = null;

  if (!coreModule) {
    return null;
  }

  // 检查缓存
  if (agentCache.has(sessionId)) {
    return agentCache.get(sessionId)!;
  }

  try {
    // 创建新 Agent（可能抛出 ConfigurationError）
    const config = coreModule.loadConfig();
    const agent = new coreModule.Agent(config);
    agent.setRegistry(coreModule.toolRegistry);

    // 默认使用 Build 模式
    if (agent.setAgentMode) {
      agent.setAgentMode('build');
    }

    // 设置权限回调，通过 WebSocket 请求用户确认
    const permissionManager = coreModule.getPermissionManager();
    permissionManager.setAskCallback(createServerPermissionCallback(sessionId));

    // 创建并初始化 SessionManager（用于消息持久化）
    const sessionMgr = await getOrCreateSessionManager(sessionId);
    if (sessionMgr) {
      agent.setSessionManager(sessionMgr);
    }

    agentCache.set(sessionId, agent);
    return agent;
  } catch (error) {
    // 检测配置错误（通过 error.name 识别，避免直接依赖 Core 类型）
    if (error instanceof Error && error.name === 'ConfigurationError') {
      const configError = error as Error & { provider?: string };
      lastConfigError = {
        provider: configError.provider || 'unknown',
        message: error.message,
      };
      console.warn(`[Agent] Configuration error: ${error.message}`);
      return null;
    }
    // 其他错误继续抛出
    throw error;
  }
}

/**
 * 获取或创建 SessionManager 实例
 */
async function getOrCreateSessionManager(sessionId: string): Promise<SessionManagerInstance | null> {
  if (!coreModule) {
    return null;
  }

  // 检查缓存
  if (sessionManagerCache.has(sessionId)) {
    return sessionManagerCache.get(sessionId)!;
  }

  try {
    // 获取 session 的工作目录
    const serverSessionManager = getSessionManager();
    const session = serverSessionManager.get(sessionId);
    const workdir = session?.workdir || process.cwd();

    // 创建新的 Core SessionManager
    const sessionMgr = new coreModule.SessionManager();

    // 初始化（这会创建或加载项目）
    await sessionMgr.init(workdir);

    // 尝试恢复指定的 session（如果存在）
    const restored = await sessionMgr.restoreSession(sessionId);
    if (restored) {
      console.log(`[Agent] Restored session ${sessionId} with ${(restored as { messages: unknown[] }).messages?.length || 0} messages`);
    }

    sessionManagerCache.set(sessionId, sessionMgr);
    return sessionMgr;
  } catch (error) {
    console.error(`[Agent] Failed to create SessionManager for ${sessionId}:`, error);
    return null;
  }
}

/**
 * 销毁 Agent 实例
 */
export async function destroyAgent(sessionId: string): Promise<void> {
  // 关闭并清理 SessionManager
  const sessionMgr = sessionManagerCache.get(sessionId);
  if (sessionMgr) {
    await sessionMgr.close();
    sessionManagerCache.delete(sessionId);
  }

  agentCache.delete(sessionId);
}

/**
 * 处理用户消息并流式返回响应
 */
export async function processMessage(
  sessionId: string,
  content: string,
  options?: AgentModeOptions
): Promise<void> {
  const sessionManager = getSessionManager();

  // 取消之前可能存在的请求
  const existingController = abortControllerCache.get(sessionId);
  if (existingController) {
    existingController.abort();
  }

  // 创建新的 AbortController
  const abortController = new AbortController();
  abortControllerCache.set(sessionId, abortController);

  // 更新状态
  sessionManager.updateStatus(sessionId, 'busy' as SessionStatus);
  emitStatusEvent(sessionId, 'processing', { message: '正在处理...' });

  // 获取 Agent
  const agent = await getOrCreateAgent(sessionId);

  if (!agent) {
    // 检查是否为配置错误
    if (lastConfigError) {
      // 返回配置错误，引导用户配置 Provider
      broadcastToSession(sessionId, {
        type: 'error',
        sessionId,
        payload: {
          type: 'config_error',
          message: lastConfigError.message,
          provider: lastConfigError.provider,
          action: 'open_providers_panel',
        },
      });

      emitLogEvent(sessionId, 'error', `配置错误: ${lastConfigError.message}`);
      sessionManager.updateStatus(sessionId, 'idle' as SessionStatus);
      emitStatusEvent(sessionId, 'idle');
      abortControllerCache.delete(sessionId);
      return;
    }

    // Core 模块不可用，返回占位响应
    const errorContent = 'Agent core module not available. Please build @ai-assistant/core first.';
    broadcastToSession(sessionId, {
      type: 'chunk',
      sessionId,
      payload: { content: errorContent },
    });

    broadcastToSession(sessionId, {
      type: 'done',
      sessionId,
      payload: { text: errorContent, hasToolCalls: false, messageCount: 0 },
    });

    sessionManager.updateStatus(sessionId, 'idle' as SessionStatus);
    emitStatusEvent(sessionId, 'idle');
    abortControllerCache.delete(sessionId);
    return;
  }

  // 应用 Agent 模式和自动授权配置
  if (options?.agentMode && agent.setAgentMode) {
    agent.setAgentMode(options.agentMode);
  }

  // autoApprove 仅对 build 模式生效，且只允许 write/edit（不含 delete）
  if (options?.autoApprove && options?.agentMode !== 'plan') {
    // 设置会话级别的 auto-approve 配置（用于权限回调）
    setSessionAutoApprove(sessionId, {
      file: { write: 'allow', edit: 'allow' },
    });
  } else {
    // 清除 auto-approve 配置
    setSessionAutoApprove(sessionId, null);
  }

  try {
    // 调用 Agent 的 chat 方法，使用流式回调和 AbortSignal
    const result = await agent.chat(content, {
      onStream: (chunk: string) => {
        // 检查是否已取消
        if (abortController.signal.aborted) return;

        // 推送流式内容
        broadcastToSession(sessionId, {
          type: 'chunk',
          sessionId,
          payload: { content: chunk },
        });

        // 检测工具调用（向后兼容 - SSE 日志）
        if (chunk.includes('[调用工具:')) {
          const match = chunk.match(/\[调用工具: (.+?)\]/);
          if (match) {
            emitLogEvent(sessionId, 'info', `调用工具: ${match[1]}`);
          }
        }
      },
      onToolStart: (info) => {
        // 检查是否已取消
        if (abortController.signal.aborted) return;

        // 推送工具开始事件
        broadcastToSession(sessionId, {
          type: 'tool_start',
          sessionId,
          payload: {
            id: info.id,
            toolName: info.toolName,
            arguments: info.args,
          },
        });
      },
      onToolEnd: (info) => {
        // 检查是否已取消
        if (abortController.signal.aborted) return;

        // 推送工具结束事件
        broadcastToSession(sessionId, {
          type: 'tool_end',
          sessionId,
          payload: {
            id: info.id,
            status: info.status,
            result: info.result,
            error: info.error,
            duration: info.duration,
          },
        });
      },
      abortSignal: abortController.signal,
    });

    // 消息已由 Core Agent 自动持久化，这里只更新 Server 端的会话计数
    const session = sessionManager.get(sessionId);
    if (session) {
      // 从 Agent 获取实际消息数
      const history = agent.getHistory();
      session.messageCount = history.length;
      session.updatedAt = new Date().toISOString();
    }

    // 检查是否有工具调用
    const hasToolCalls = result.messages.some((m: unknown) => {
      const msg = m as { content?: unknown };
      return Array.isArray(msg.content) && msg.content.some((c: unknown) => {
        const block = c as { type?: string };
        return block.type === 'tool-call';
      });
    });

    // 发送完成消息
    broadcastToSession(sessionId, {
      type: 'done',
      sessionId,
      payload: {
        text: result.text,
        hasToolCalls,
        messageCount: result.messages.length,
        agentName: options?.agentMode || 'build',
      },
    });

    // 检查是否需要生成会话标题（首次对话完成后）
    if (session && !session.name) {
      // 异步生成标题，不阻塞响应
      generateSessionTitle(sessionId, content, result.text).catch(err => {
        console.error('[Agent] Failed to generate session title:', err);
      });
    }

    emitStatusEvent(sessionId, 'idle');
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : String(error);

    // 发送错误
    broadcastToSession(sessionId, {
      type: 'error',
      sessionId,
      payload: { message: errorMessage },
    });

    emitLogEvent(sessionId, 'error', errorMessage);
  } finally {
    // 清理 AbortController
    abortControllerCache.delete(sessionId);
    sessionManager.updateStatus(sessionId, 'idle' as SessionStatus);
  }
}

/**
 * 取消正在进行的处理
 */
export function cancelProcessing(sessionId: string): void {
  // 获取并中止 AbortController
  const controller = abortControllerCache.get(sessionId);
  if (controller) {
    controller.abort();
    abortControllerCache.delete(sessionId);
  }

  const sessionManager = getSessionManager();
  sessionManager.updateStatus(sessionId, 'idle' as SessionStatus);
  emitStatusEvent(sessionId, 'cancelled');

  // 通知客户端已取消
  broadcastToSession(sessionId, {
    type: 'cancelled',
    sessionId,
    payload: { message: '用户取消了请求' },
  });
}

/**
 * 获取 Agent 统计信息
 */
export function getAgentStats(sessionId: string): {
  available: boolean;
  toolCount?: { core: number; discovered: number; total: number };
  contextUsage?: string;
} {
  if (!coreModule) {
    return { available: false };
  }

  const agent = agentCache.get(sessionId);
  if (!agent) {
    return { available: true };
  }

  return {
    available: true,
    toolCount: agent.getToolCount(),
    contextUsage: agent.getContextUsageFormatted(),
  };
}

// ============================================================================
// 会话标题生成
// ============================================================================

/**
 * 从用户消息中提取简短标题
 * 使用简单的启发式方法，不依赖 LLM
 */
function extractTitleFromMessage(userMessage: string): string {
  // 移除多余空白
  const cleaned = userMessage.trim().replace(/\s+/g, ' ');

  // 如果消息很短，直接使用
  if (cleaned.length <= 30) {
    return cleaned;
  }

  // 尝试提取第一句话
  const firstSentence = cleaned.match(/^[^。！？.!?]+[。！？.!?]?/)?.[0] || cleaned;

  // 如果第一句话也很长，截断
  if (firstSentence.length > 40) {
    return firstSentence.slice(0, 37) + '...';
  }

  return firstSentence;
}

/**
 * 生成会话标题并更新
 */
async function generateSessionTitle(
  sessionId: string,
  userMessage: string,
  _assistantResponse: string
): Promise<void> {
  const sessionManager = getSessionManager();

  // 使用简单提取方式生成标题
  const title = extractTitleFromMessage(userMessage);

  // 更新会话标题
  const updatedSession = await sessionManager.updateSessionName(sessionId, title);

  if (updatedSession) {
    // 广播标题更新事件
    broadcastToSession(sessionId, {
      type: 'session_updated',
      sessionId,
      payload: {
        id: updatedSession.id,
        name: updatedSession.name,
      },
    });

    console.log(`[Agent] Session title generated: "${title}"`);
  }
}

// ============================================================================
// 上下文压缩 API
// ============================================================================

/**
 * 上下文使用情况（带额外字段）
 */
export interface ContextUsageInfo extends TokenUsage {
  formatted: string;
  shouldCompress: boolean;
}

/**
 * 获取会话的上下文使用情况
 */
export function getContextUsage(sessionId: string): ContextUsageInfo | null {
  if (!coreModule) {
    return null;
  }

  const agent = agentCache.get(sessionId);
  if (!agent) {
    return null;
  }

  const usage = agent.getContextUsage();
  const formatted = agent.getContextUsageFormatted();

  return {
    ...usage,
    formatted,
    shouldCompress: usage.usagePercent >= 80, // 80% 阈值建议压缩
  };
}

/**
 * 执行上下文压缩
 */
export async function compressContext(
  sessionId: string,
  force: boolean = false
): Promise<CompressionResult | null> {
  if (!coreModule) {
    return null;
  }

  const agent = agentCache.get(sessionId);
  if (!agent) {
    return null;
  }

  try {
    // 使用强制压缩或普通压缩
    const result = await agent.compactHistory();

    return {
      type: result.type as CompressionResult['type'],
      status: result.freedTokens > 0 ? 'success' : 'noop',
      freedTokens: result.freedTokens,
    };
  } catch (error) {
    return {
      type: 'none',
      status: 'failed_error',
      freedTokens: 0,
      error: error instanceof Error ? error.message : String(error),
    };
  }
}

