/**
 * Session Manager 测试
 *
 * 测试会话管理器的核心功能
 *
 * 注意：SessionManager 使用动态 import 加载 @ai-assistant/core。
 * 测试中会创建新实例并记录初始会话数量，以确保测试独立性。
 *
 * 消息存储已移至 Core 层，Server 的 SessionManager 只负责会话元数据管理。
 */

import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { SessionManager, getSessionManager } from '../../../src/session/manager.js';

describe('SessionManager', () => {
  let manager: SessionManager;
  let initialCount: number;
  // 追踪测试中创建的 session ID，用于清理
  let createdSessionIds: string[] = [];

  beforeEach(async () => {
    vi.clearAllMocks();
    createdSessionIds = [];
    // Create a fresh instance for each test
    manager = new SessionManager();
    await manager.init();
    // Record initial session count (may include sessions from storage)
    initialCount = manager.count();
  });

  afterEach(async () => {
    // 清理测试中创建的所有 session
    for (const sessionId of createdSessionIds) {
      try {
        await manager.delete(sessionId);
      } catch {
        // 忽略删除失败（可能已经被测试删除）
      }
    }
  });

  // 辅助函数：创建 session 并追踪 ID
  async function createTrackedSession(data: Parameters<SessionManager['create']>[0]) {
    const session = await manager.create(data);
    createdSessionIds.push(session.id);
    return session;
  }

  describe('init - 初始化', () => {
    it('初始化成功', async () => {
      // Manager is already initialized in beforeEach
      // Verify it works by creating a session
      const session = await createTrackedSession({ name: 'Test' });
      expect(session).toBeDefined();
    });

    it('重复初始化只执行一次', async () => {
      await manager.init();
      await manager.init();

      // 不会抛错，可以正常工作
      const session = await createTrackedSession({ name: 'Test' });
      expect(session).toBeDefined();
    });
  });

  describe('create - 创建会话', () => {
    it('创建新会话', async () => {
      const session = await createTrackedSession({ name: 'New Session' });

      expect(session).toBeDefined();
      expect(session.name).toBe('New Session');
      expect(session.status).toBe('idle');
      expect(session.messageCount).toBe(0);
    });

    it('生成唯一 ID', async () => {
      const session1 = await createTrackedSession({ name: 'Session 1' });
      const session2 = await createTrackedSession({ name: 'Session 2' });

      expect(session1.id).not.toBe(session2.id);
    });

    it('使用自定义工作目录', async () => {
      const session = await createTrackedSession({
        name: 'Custom Workdir',
        workdir: '/custom/path',
      });

      expect(session.workdir).toBe('/custom/path');
    });

    it('无名称时创建匿名会话', async () => {
      const session = await createTrackedSession({});

      expect(session).toBeDefined();
      expect(session.name).toBeUndefined();
    });

    it('设置正确的时间戳', async () => {
      const before = new Date().toISOString();
      const session = await createTrackedSession({ name: 'Test' });
      const after = new Date().toISOString();

      expect(session.createdAt).toBeDefined();
      expect(session.createdAt >= before).toBe(true);
      expect(session.createdAt <= after).toBe(true);
      expect(session.createdAt).toBe(session.updatedAt);
    });

    it('创建后 count 增加', async () => {
      const before = manager.count();
      await createTrackedSession({ name: 'Test' });
      expect(manager.count()).toBe(before + 1);
    });
  });

  describe('list - 列出会话', () => {
    it('返回所有会话（包含新创建的）', async () => {
      const countBefore = manager.list().length;
      await createTrackedSession({ name: 'Session 1' });
      await createTrackedSession({ name: 'Session 2' });

      const sessions = manager.list();
      expect(sessions.length).toBe(countBefore + 2);
    });

    it('按更新时间排序（最新在前）', async () => {
      const session1 = await createTrackedSession({ name: 'Older Session' });
      const session2 = await createTrackedSession({ name: 'Newer Session' });

      // Wait a bit and update session1
      await new Promise((resolve) => setTimeout(resolve, 10));
      manager.updateStatus(session1.id, 'active');

      const sessions = manager.list();
      // session1 should be first as it was updated last
      expect(sessions[0].id).toBe(session1.id);
    });

    it('返回数组类型', () => {
      const sessions = manager.list();
      expect(Array.isArray(sessions)).toBe(true);
    });
  });

  describe('get - 获取会话', () => {
    it('返回存在的会话', async () => {
      const created = await createTrackedSession({ name: 'Test' });
      const session = manager.get(created.id);

      expect(session).toBeDefined();
      expect(session?.id).toBe(created.id);
    });

    it('不存在返回 undefined', () => {
      const session = manager.get('non-existent-id-12345');
      expect(session).toBeUndefined();
    });
  });

  describe('delete - 删除会话', () => {
    it('删除存在的会话', async () => {
      // 注意：这个测试会自己删除 session，不需要追踪
      const session = await manager.create({ name: 'To Delete' });
      const result = await manager.delete(session.id);

      expect(result).toBe(true);
      expect(manager.exists(session.id)).toBe(false);
    });

    it('删除不存在的会话返回 false', async () => {
      const result = await manager.delete('non-existent-id-12345');
      expect(result).toBe(false);
    });

    it('删除后 count 减少', async () => {
      // 注意：这个测试会自己删除 session，不需要追踪
      const session = await manager.create({ name: 'Test' });
      const countAfterCreate = manager.count();

      await manager.delete(session.id);
      expect(manager.count()).toBe(countAfterCreate - 1);
    });
  });

  describe('updateStatus - 更新状态', () => {
    it('更新会话状态', async () => {
      const session = await createTrackedSession({ name: 'Test' });
      const updated = manager.updateStatus(session.id, 'active');

      expect(updated?.status).toBe('active');
    });

    it('更新为 busy 状态', async () => {
      const session = await createTrackedSession({ name: 'Test' });
      const updated = manager.updateStatus(session.id, 'busy');

      expect(updated?.status).toBe('busy');
    });

    it('更新为 idle 状态', async () => {
      const session = await createTrackedSession({ name: 'Test' });
      manager.updateStatus(session.id, 'active');
      const updated = manager.updateStatus(session.id, 'idle');

      expect(updated?.status).toBe('idle');
    });

    it('更新时更新 updatedAt', async () => {
      const session = await createTrackedSession({ name: 'Test' });
      const originalUpdatedAt = session.updatedAt;

      // Wait a bit to ensure time difference
      await new Promise((resolve) => setTimeout(resolve, 10));

      const updated = manager.updateStatus(session.id, 'busy');
      expect(updated?.updatedAt).not.toBe(originalUpdatedAt);
    });

    it('不存在的会话返回 undefined', () => {
      const result = manager.updateStatus('non-existent-id-12345', 'active');
      expect(result).toBeUndefined();
    });
  });

  describe('updateMessageCount - 更新消息计数', () => {
    it('更新消息计数', async () => {
      const session = await createTrackedSession({ name: 'Test' });
      expect(session.messageCount).toBe(0);

      const updated = manager.updateMessageCount(session.id, 5);
      expect(updated?.messageCount).toBe(5);
    });

    it('更新时更新 updatedAt', async () => {
      const session = await createTrackedSession({ name: 'Test' });
      const originalUpdatedAt = session.updatedAt;

      await new Promise((resolve) => setTimeout(resolve, 10));
      manager.updateMessageCount(session.id, 3);

      const updated = manager.get(session.id);
      expect(updated?.updatedAt).not.toBe(originalUpdatedAt);
    });

    it('不存在的会话返回 undefined', () => {
      const result = manager.updateMessageCount('non-existent-id-12345', 10);
      expect(result).toBeUndefined();
    });
  });

  describe('updateSessionName - 更新名称', () => {
    it('更新会话名称', async () => {
      const session = await createTrackedSession({ name: 'Old Name' });
      const updated = await manager.updateSessionName(session.id, 'New Name');

      expect(updated?.name).toBe('New Name');
    });

    it('更新名称更新 updatedAt', async () => {
      const session = await createTrackedSession({ name: 'Test' });
      const originalUpdatedAt = session.updatedAt;

      await new Promise((resolve) => setTimeout(resolve, 10));
      await manager.updateSessionName(session.id, 'Updated');

      expect(manager.get(session.id)?.updatedAt).not.toBe(originalUpdatedAt);
    });

    it('不存在的会话返回 undefined', async () => {
      const result = await manager.updateSessionName('non-existent-id-12345', 'Name');
      expect(result).toBeUndefined();
    });

    it('更新为空名称', async () => {
      const session = await createTrackedSession({ name: 'Has Name' });
      const updated = await manager.updateSessionName(session.id, '');

      expect(updated?.name).toBe('');
    });
  });

  describe('count - 会话数量', () => {
    it('创建后数量增加', async () => {
      const before = manager.count();
      await createTrackedSession({ name: 'Session 1' });
      expect(manager.count()).toBe(before + 1);

      await createTrackedSession({ name: 'Session 2' });
      expect(manager.count()).toBe(before + 2);

      await createTrackedSession({ name: 'Session 3' });
      expect(manager.count()).toBe(before + 3);
    });

    it('返回非负整数', () => {
      expect(manager.count()).toBeGreaterThanOrEqual(0);
      expect(Number.isInteger(manager.count())).toBe(true);
    });
  });

  describe('exists - 检查存在', () => {
    it('存在的会话返回 true', async () => {
      const session = await createTrackedSession({ name: 'Test' });
      expect(manager.exists(session.id)).toBe(true);
    });

    it('不存在的会话返回 false', () => {
      expect(manager.exists('non-existent-id-12345')).toBe(false);
    });

    it('删除后返回 false', async () => {
      // 注意：这个测试会自己删除 session，不需要追踪
      const session = await manager.create({ name: 'Test' });
      await manager.delete(session.id);
      expect(manager.exists(session.id)).toBe(false);
    });
  });

  describe('getStorage 和 getProjectId - Storage 访问', () => {
    it('getStorage 返回 Storage 实例或 null', () => {
      const storage = manager.getStorage();
      // 可能为 null（如果 Core 未加载）或者是 SessionStorage 实例
      expect(storage === null || typeof storage === 'object').toBe(true);
    });

    it('getProjectId 返回字符串', async () => {
      const session = await createTrackedSession({ name: 'Test' });
      const projectId = manager.getProjectId(session.id);
      expect(typeof projectId).toBe('string');
    });

    it('不存在的会话返回默认 projectId', () => {
      const projectId = manager.getProjectId('non-existent-id');
      expect(typeof projectId).toBe('string');
    });
  });

  describe('边界情况', () => {
    it('处理特殊字符的会话名称', async () => {
      const session = await createTrackedSession({ name: '测试会话 <>&"\'`' });
      expect(session.name).toBe('测试会话 <>&"\'`');
    });
  });
});

describe('getSessionManager - 单例', () => {
  it('返回同一实例', () => {
    const manager1 = getSessionManager();
    const manager2 = getSessionManager();

    expect(manager1).toBe(manager2);
  });

  it('返回 SessionManager 实例', () => {
    const manager = getSessionManager();
    expect(manager).toBeInstanceOf(SessionManager);
  });
});
