import type { ModelMessage } from 'ai';
import * as storage from './storage/index.js';
import { SessionStorage, MessageStorage, PartStorage, TodoStorage } from './storage/index.js';
import type { SessionInfo, Part, TodoItem } from './storage/index.js';
import { generateSessionId } from './id.js';
import { getProjectId, isGitRepository } from './project.js';

/**
 * 会话摘要（用于列表展示）
 */
export interface SessionSummary {
  id: string;
  title: string;
  workdir: string;
  messageCount: number;
  createdAt: string;
  updatedAt: string;
}

/**
 * 运行时会话数据（兼容旧接口）
 */
export interface SessionData {
  id: string;
  projectId: string;
  parentId?: string;
  agentName?: string;
  createdAt: string;
  updatedAt: string;
  workdir: string;
  title?: string;
  messages: ModelMessage[];
  discoveredTools: string[];
  todos: TodoItem[];
}

/**
 * 项目元数据
 */
export interface ProjectMetadata {
  id: string;
  workdir: string;
  createdAt: string;
  isGitRepo: boolean;
}

/**
 * 会话管理器
 * 提供高级会话操作接口，使用新的三层存储结构
 */
export class SessionManager {
  private currentSession: SessionData | null = null;
  private currentProject: ProjectMetadata | null = null;
  private autoSaveInterval: ReturnType<typeof setInterval> | null = null;
  private storageDir?: string;

  constructor(storageDir?: string) {
    this.storageDir = storageDir;
  }

  /**
   * 初始化 - 尝试恢复或创建新会话
   */
  async init(workdir: string): Promise<SessionData> {
    // 初始化存储
    await storage.initStorage(this.storageDir);

    // 获取或创建项目
    this.currentProject = await this.getOrCreateProject(workdir);

    // 尝试加载当前会话
    const currentSessionId = await this.getCurrentSessionId();

    if (currentSessionId) {
      const existing = await this.loadSession(this.currentProject.id, currentSessionId);

      if (existing && existing.workdir === workdir) {
        this.currentSession = existing;
        this.startAutoSave();
        return this.currentSession;
      }
    }

    // 创建新会话
    this.currentSession = await this.createNewSession(workdir);
    await this.saveSessionInfo();
    await this.setCurrentSessionPointer(this.currentSession.id);

    this.startAutoSave();
    return this.currentSession;
  }

  /**
   * 获取或创建项目
   */
  private async getOrCreateProject(workdir: string): Promise<ProjectMetadata> {
    const projectId = await getProjectId(workdir);

    try {
      const existing = await storage.read<ProjectMetadata>(['project', projectId]);
      return existing;
    } catch (e) {
      if (e instanceof storage.StorageNotFoundError) {
        const isGitRepo = await isGitRepository(workdir);
        const project: ProjectMetadata = {
          id: projectId,
          workdir,
          createdAt: new Date().toISOString(),
          isGitRepo,
        };
        await storage.write(['project', projectId], project);
        return project;
      }
      throw e;
    }
  }

  /**
   * 创建新会话
   */
  private async createNewSession(workdir: string): Promise<SessionData> {
    if (!this.currentProject) {
      throw new Error('Project not initialized. Call init() first.');
    }

    const sessionInfo = await SessionStorage.create(this.currentProject.id, workdir);

    return {
      id: sessionInfo.id,
      projectId: sessionInfo.projectId,
      createdAt: new Date(sessionInfo.createdAt).toISOString(),
      updatedAt: new Date(sessionInfo.updatedAt).toISOString(),
      workdir: sessionInfo.workdir,
      title: sessionInfo.title,
      messages: [],
      discoveredTools: sessionInfo.discoveredTools,
      todos: [],
    };
  }

  /**
   * 加载会话（从存储重建）
   */
  private async loadSession(projectId: string, sessionId: string): Promise<SessionData | null> {
    const sessionInfo = await SessionStorage.get(projectId, sessionId);
    if (!sessionInfo) return null;

    // 加载消息
    const messages = await this.loadMessagesFromStorage(sessionId);

    // 加载 todos
    const todoList = await TodoStorage.get(sessionId);

    return {
      id: sessionInfo.id,
      projectId: sessionInfo.projectId,
      parentId: sessionInfo.parentId,
      agentName: sessionInfo.agentName,
      createdAt: new Date(sessionInfo.createdAt).toISOString(),
      updatedAt: new Date(sessionInfo.updatedAt).toISOString(),
      workdir: sessionInfo.workdir,
      title: sessionInfo.title,
      messages,
      discoveredTools: sessionInfo.discoveredTools,
      todos: todoList?.items || [],
    };
  }

  /**
   * 从存储加载消息并转换为 AI SDK 格式
   */
  private async loadMessagesFromStorage(sessionId: string): Promise<ModelMessage[]> {
    const messageInfos = await MessageStorage.listBySession(sessionId);
    const messages: ModelMessage[] = [];

    for (const messageInfo of messageInfos) {
      const parts = await PartStorage.getByIds(messageInfo.id, messageInfo.partIds);
      const modelMessages = this.partsToModelMessages(messageInfo.role, parts);
      messages.push(...modelMessages);
    }

    return messages;
  }

  /**
   * 将 Parts 转换为 AI SDK ModelMessage（用于加载历史消息）
   *
   * 新逻辑：
   * - user 消息：直接转换
   * - assistant 消息：转换文本和工具调用，然后为已完成的工具生成 tool 消息
   */
  private partsToModelMessages(role: string, parts: Part[]): ModelMessage[] {
    if (parts.length === 0) return [];

    const result: ModelMessage[] = [];

    if (role === 'user') {
      // User 消息：只有文本和文件
      const content: unknown[] = [];
      for (const part of parts) {
        if (part.type === 'text') {
          content.push({ type: 'text', text: part.text });
        } else if (part.type === 'file') {
          content.push({
            type: 'image',
            image: part.data,
            mimeType: part.mimeType,
          });
        }
      }

      if (content.length === 1 && (content[0] as { type: string }).type === 'text') {
        result.push({
          role: 'user',
          content: (content[0] as { text: string }).text,
        });
      } else if (content.length > 0) {
        result.push({
          role: 'user',
          content,
        } as ModelMessage);
      }

    } else if (role === 'assistant') {
      // Assistant 消息：文本 + 工具调用
      const content: unknown[] = [];
      // input 使用 unknown 类型以兼容 AI SDK（可能是对象、字符串等）
      const completedTools: Array<{ toolCallId: string; toolName: string; input: unknown; output: unknown }> = [];

      for (const part of parts) {
        if (part.type === 'text') {
          content.push({ type: 'text', text: part.text });
        } else if (part.type === 'tool') {
          // 只有非 pending 状态的工具调用才添加到 AI SDK 消息
          if (part.state.status !== 'pending') {
            // AI SDK v5 使用 input 字段（不是 args）
            content.push({
              type: 'tool-call',
              toolCallId: part.toolCallId,
              toolName: part.toolName,
              input: part.state.input,
            });

            // 收集已完成的工具结果
            if (part.state.status === 'completed') {
              completedTools.push({
                toolCallId: part.toolCallId,
                toolName: part.toolName,
                input: part.state.input,
                output: part.state.output,
              });
            } else if (part.state.status === 'error') {
              completedTools.push({
                toolCallId: part.toolCallId,
                toolName: part.toolName,
                input: part.state.input,
                output: part.state.error,
              });
            }
          }
        } else if (part.type === 'reasoning') {
          content.push({ type: 'text', text: `[Reasoning] ${part.text}` });
        }
      }

      // 添加 assistant 消息
      if (content.length === 1 && (content[0] as { type: string }).type === 'text') {
        result.push({
          role: 'assistant',
          content: (content[0] as { text: string }).text,
        });
      } else if (content.length > 0) {
        result.push({
          role: 'assistant',
          content,
        } as ModelMessage);
      }

      // 添加 tool 消息（如果有已完成的工具）
      // AI SDK v5 要求 tool-result 必须包含 input 和 output 字段
      if (completedTools.length > 0) {
        result.push({
          role: 'tool',
          content: completedTools.map((t) => ({
            type: 'tool-result',
            toolCallId: t.toolCallId,
            toolName: t.toolName,
            input: t.input,
            output: t.output,
          })),
        } as unknown as ModelMessage);
      }
    }

    return result;
  }

  /**
   * 获取当前会话
   */
  getSession(): SessionData | null {
    return this.currentSession;
  }

  /**
   * 获取当前项目
   */
  getProject(): ProjectMetadata | null {
    return this.currentProject;
  }

  /**
   * 保存会话信息
   */
  private async saveSessionInfo(): Promise<void> {
    if (!this.currentSession) return;

    const sessionInfo: SessionInfo = {
      id: this.currentSession.id,
      projectId: this.currentSession.projectId,
      parentId: this.currentSession.parentId,
      agentName: this.currentSession.agentName,
      createdAt: new Date(this.currentSession.createdAt).getTime(),
      updatedAt: Date.now(),
      workdir: this.currentSession.workdir,
      title: this.currentSession.title,
      discoveredTools: this.currentSession.discoveredTools,
      stats: {
        messageCount: this.currentSession.messages.length,
        inputTokens: 0,
        outputTokens: 0,
      },
    };

    await SessionStorage.save(sessionInfo);
  }

  /**
   * 保存当前会话
   */
  async save(): Promise<void> {
    if (!this.currentSession) return;
    await this.saveSessionInfo();
  }

  /**
   * 同步消息到存储（将 AI SDK 消息转换为 Message + Parts）
   *
   * 新逻辑：只存储 user 和 assistant 消息
   * - user 消息：直接存储
   * - assistant 消息：合并后续的 tool 消息中的工具结果
   * - tool 消息：跳过（结果合并到 assistant）
   */
  async syncMessages(messages: ModelMessage[]): Promise<void> {
    if (!this.currentSession) return;

    const sessionId = this.currentSession.id;

    // 删除旧消息
    await MessageStorage.removeBySession(sessionId);

    // 用于跟踪当前 assistant 消息的工具调用
    let currentAssistantMsgId: string | null = null;
    let currentUserMsgId: string | null = null;
    const toolCallPartIds = new Map<string, string>(); // toolCallId -> partId

    for (let i = 0; i < messages.length; i++) {
      const message = messages[i];

      if (message.role === 'user') {
        // User 消息
        const messageInfo = await MessageStorage.create(sessionId, 'user');
        currentUserMsgId = messageInfo.id;
        const partIds: string[] = [];

        if (typeof message.content === 'string') {
          const part = await PartStorage.createText(messageInfo.id, message.content);
          partIds.push(part.id);
        } else if (Array.isArray(message.content)) {
          for (const item of message.content) {
            const itemType = (item as { type: string }).type;
            if (itemType === 'text') {
              const part = await PartStorage.createText(messageInfo.id, (item as { text: string }).text);
              partIds.push(part.id);
            } else if (itemType === 'image') {
              const img = item as unknown as { image: string; mimeType: string };
              const part = await PartStorage.create(messageInfo.id, 'file', {
                filename: 'image',
                mimeType: img.mimeType,
                data: typeof img.image === 'string' ? img.image : '',
              });
              partIds.push(part.id);
            }
          }
        }

        if (partIds.length > 0) {
          await MessageStorage.update(sessionId, messageInfo.id, { partIds });
        }

        // 重置工具调用追踪
        currentAssistantMsgId = null;
        toolCallPartIds.clear();

      } else if (message.role === 'assistant') {
        // Assistant 消息：如果当前轮次已有 assistant 消息，则追加 Parts
        let messageId: string;
        let existingPartIds: string[] = [];

        if (currentAssistantMsgId) {
          // 同一轮对话的后续 assistant 消息，追加到现有消息
          messageId = currentAssistantMsgId;
          const existingMsg = await MessageStorage.get(sessionId, messageId);
          existingPartIds = existingMsg?.partIds ?? [];
        } else {
          // 新的 assistant 消息
          const messageInfo = await MessageStorage.create(sessionId, 'assistant', {
            parentId: currentUserMsgId ?? undefined,
          });
          messageId = messageInfo.id;
          currentAssistantMsgId = messageId;
        }

        const newPartIds: string[] = [];

        if (typeof message.content === 'string') {
          const part = await PartStorage.createText(messageId, message.content);
          newPartIds.push(part.id);
        } else if (Array.isArray(message.content)) {
          for (const item of message.content) {
            const itemType = (item as { type: string }).type;
            if (itemType === 'text') {
              const part = await PartStorage.createText(messageId, (item as { text: string }).text);
              newPartIds.push(part.id);
            } else if (itemType === 'tool-call') {
              // AI SDK 的 tool-call 使用 input 字段存储参数（不是 args）
              const toolCall = item as unknown as { toolCallId: string; toolName: string; input: Record<string, unknown> };
              // 创建 running 状态的工具 Part
              const part = await PartStorage.createToolRunning(
                messageId,
                toolCall.toolCallId,
                toolCall.toolName,
                (toolCall.input as Record<string, unknown>) ?? {}
              );
              newPartIds.push(part.id);
              toolCallPartIds.set(toolCall.toolCallId, part.id);
            }
          }
        }

        if (newPartIds.length > 0) {
          // 合并已有的和新的 partIds
          const allPartIds = [...existingPartIds, ...newPartIds];
          await MessageStorage.update(sessionId, messageId, { partIds: allPartIds });
        }

      } else if (message.role === 'tool' && currentAssistantMsgId) {
        // Tool 消息：更新对应 assistant 消息中的工具 Part 状态
        if (Array.isArray(message.content)) {
          for (const item of message.content) {
            const itemType = (item as { type: string }).type;
            if (itemType === 'tool-result') {
              // AI SDK v5 使用 output 字段存储结果（不是 result）
              const toolResult = item as unknown as { toolCallId: string; toolName: string; output: unknown };
              const partId = toolCallPartIds.get(toolResult.toolCallId);
              if (partId) {
                // 更新工具状态为 completed
                // 获取原始 start time
                const part = await PartStorage.get(currentAssistantMsgId, partId);
                const startTime = part?.type === 'tool' && part.state.status === 'running'
                  ? part.state.time.start
                  : Date.now();
                await PartStorage.setToolCompleted(currentAssistantMsgId, partId, toolResult.output, startTime);
              }
            }
          }
        }
        // 不创建新消息，跳过 tool role
      }
      // 忽略 system 消息（system prompt 通过其他方式注入）
    }
  }

  /**
   * 批量设置消息（用于同步整个对话历史）
   */
  async setMessages(messages: ModelMessage[]): Promise<void> {
    if (!this.currentSession) return;
    this.currentSession.messages = messages;
    await this.syncMessages(messages);
    await this.saveSessionInfo();
  }

  /**
   * 添加消息
   */
  async addMessage(message: ModelMessage): Promise<void> {
    if (!this.currentSession) return;
    this.currentSession.messages.push(message);
    await this.setMessages(this.currentSession.messages);
  }

  /**
   * 获取对话历史
   */
  getMessages(): ModelMessage[] {
    return this.currentSession?.messages || [];
  }

  /**
   * 设置已发现的工具
   */
  async setDiscoveredTools(tools: string[]): Promise<void> {
    if (!this.currentSession) return;
    this.currentSession.discoveredTools = tools;
    await this.saveSessionInfo();
  }

  /**
   * 获取已发现的工具
   */
  getDiscoveredTools(): string[] {
    return this.currentSession?.discoveredTools || [];
  }

  /**
   * 更新待办事项
   */
  async setTodos(todos: Array<{ content: string; status: 'pending' | 'in_progress' | 'completed' }>): Promise<void> {
    if (!this.currentSession) return;
    const todoList = await TodoStorage.replace(this.currentSession.id, todos);
    this.currentSession.todos = todoList.items;
  }

  /**
   * 获取待办事项
   */
  getTodos(): TodoItem[] {
    return this.currentSession?.todos || [];
  }

  /**
   * 清空当前会话并创建新会话
   */
  async newSession(workdir?: string): Promise<SessionData> {
    if (!this.currentProject) {
      throw new Error('Project not initialized. Call init() first.');
    }

    const newWorkdir = workdir || this.currentSession?.workdir || process.cwd();

    // 如果工作目录变化，需要切换项目
    if (workdir && workdir !== this.currentProject.workdir) {
      this.currentProject = await this.getOrCreateProject(workdir);
    }

    this.currentSession = await this.createNewSession(newWorkdir);
    await this.saveSessionInfo();
    await this.setCurrentSessionPointer(this.currentSession.id);

    return this.currentSession;
  }

  /**
   * 创建子会话（用于 Task 工具）
   */
  createChildSession(parentId: string, agentName: string, title?: string): SessionData {
    if (!this.currentProject) {
      throw new Error('Project not initialized. Call init() first.');
    }

    const workdir = this.currentSession?.workdir || process.cwd();
    return {
      id: generateSessionId(),
      projectId: this.currentProject.id,
      parentId,
      agentName,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
      workdir,
      title: title || `子任务 (@${agentName})`,
      messages: [],
      discoveredTools: [],
      todos: [],
    };
  }

  /**
   * 保存子会话
   */
  async saveChildSession(session: SessionData): Promise<void> {
    const sessionInfo: SessionInfo = {
      id: session.id,
      projectId: session.projectId,
      parentId: session.parentId,
      agentName: session.agentName,
      createdAt: new Date(session.createdAt).getTime(),
      updatedAt: Date.now(),
      workdir: session.workdir,
      title: session.title,
      discoveredTools: session.discoveredTools,
    };
    await SessionStorage.save(sessionInfo);
  }

  /**
   * 获取当前会话 ID
   */
  getSessionId(): string | undefined {
    return this.currentSession?.id;
  }

  /**
   * 恢复指定会话
   */
  async restoreSession(sessionId: string): Promise<SessionData | null> {
    if (!this.currentProject) {
      throw new Error('Project not initialized. Call init() first.');
    }

    const session = await this.loadSession(this.currentProject.id, sessionId);
    if (!session) return null;

    this.currentSession = session;
    await this.setCurrentSessionPointer(sessionId);

    return session;
  }

  /**
   * 列出当前项目的历史会话
   */
  async listSessions(): Promise<SessionSummary[]> {
    if (!this.currentProject) {
      return this.listAllSessions();
    }

    const sessions = await SessionStorage.listByProject(this.currentProject.id);
    return sessions.map((s) => ({
      id: s.id,
      title: s.title || `会话 ${s.id}`,
      workdir: s.workdir,
      messageCount: s.stats?.messageCount || 0,
      createdAt: new Date(s.createdAt).toISOString(),
      updatedAt: new Date(s.updatedAt).toISOString(),
    }));
  }

  /**
   * 列出所有项目的会话
   */
  async listAllSessions(): Promise<SessionSummary[]> {
    const sessions = await SessionStorage.listAll();
    return sessions.map((s) => ({
      id: s.id,
      title: s.title || `会话 ${s.id}`,
      workdir: s.workdir,
      messageCount: s.stats?.messageCount || 0,
      createdAt: new Date(s.createdAt).toISOString(),
      updatedAt: new Date(s.updatedAt).toISOString(),
    }));
  }

  /**
   * 删除历史会话
   */
  async deleteSession(sessionId: string): Promise<boolean> {
    if (!this.currentProject) return false;

    try {
      // 删除会话的消息和 Parts
      const messageInfos = await MessageStorage.listBySession(sessionId);
      for (const msg of messageInfos) {
        await PartStorage.removeByMessage(msg.id);
      }
      await MessageStorage.removeBySession(sessionId);

      // 删除 todos
      await TodoStorage.removeBySession(sessionId);

      // 删除会话信息
      await SessionStorage.remove(this.currentProject.id, sessionId);

      return true;
    } catch {
      return false;
    }
  }

  /**
   * 获取当前会话 ID（从存储）
   */
  private async getCurrentSessionId(): Promise<string | null> {
    try {
      const pointer = await storage.read<{ sessionId: string }>(['current-session']);
      return pointer.sessionId;
    } catch {
      return null;
    }
  }

  /**
   * 设置当前会话指针
   */
  private async setCurrentSessionPointer(sessionId: string): Promise<void> {
    await storage.write(['current-session'], { sessionId });
  }

  /**
   * 启动自动保存（每 30 秒）
   */
  private startAutoSave(): void {
    if (this.autoSaveInterval) return;

    this.autoSaveInterval = setInterval(async () => {
      await this.save();
    }, 30000);
  }

  /**
   * 停止自动保存
   */
  stopAutoSave(): void {
    if (this.autoSaveInterval) {
      clearInterval(this.autoSaveInterval);
      this.autoSaveInterval = null;
    }
  }

  /**
   * 关闭管理器（保存并停止自动保存）
   */
  async close(): Promise<void> {
    this.stopAutoSave();
    await this.save();
  }

  /**
   * 清理旧会话
   */
  async cleanup(keepCount: number = 50): Promise<number> {
    const sessions = await this.listAllSessions();
    if (sessions.length <= keepCount) {
      return 0;
    }

    const toDelete = sessions.slice(keepCount);
    let deletedCount = 0;

    for (const session of toDelete) {
      if (await this.deleteSession(session.id)) {
        deletedCount++;
      }
    }

    return deletedCount;
  }

  /**
   * 获取存储目录
   */
  getStorageDir(): string {
    return this.storageDir || storage.getDefaultStorageDir();
  }
}

// 导出默认实例
export const sessionManager = new SessionManager();
