import { describe, it, expect, beforeEach, vi } from 'vitest';
import type { Todo, TodoStatus } from '../../../src/session/types.js';
import type { SessionManager } from '../../../src/session/index.js';

// 需要单独导入 todoManager 因为它是单例
// 每个测试创建新的实例来避免状态污染

// 简单的 TodoManager 测试类（复制逻辑以测试）
class TestTodoManager {
  private sessionManager: SessionManager | null = null;

  setSessionManager(manager: SessionManager): void {
    this.sessionManager = manager;
  }

  getTodos(): Todo[] {
    if (!this.sessionManager) {
      return [];
    }
    return this.sessionManager.getTodos();
  }

  async setTodos(todos: Todo[]): Promise<void> {
    if (!this.sessionManager) {
      return;
    }
    await this.sessionManager.setTodos(todos);
  }

  async addTodo(content: string, status: TodoStatus = 'pending'): Promise<Todo> {
    const todos = this.getTodos();
    const now = new Date().toISOString();
    const newTodo: Todo = {
      id: this.generateId(),
      content,
      status,
      createdAt: now,
      updatedAt: now,
    };
    todos.push(newTodo);
    await this.setTodos(todos);
    return newTodo;
  }

  async updateTodoStatus(id: string, status: TodoStatus): Promise<boolean> {
    const todos = this.getTodos();
    const todo = todos.find((t) => t.id === id);
    if (!todo) return false;

    todo.status = status;
    todo.updatedAt = new Date().toISOString();
    await this.setTodos(todos);
    return true;
  }

  async deleteTodo(id: string): Promise<boolean> {
    const todos = this.getTodos();
    const index = todos.findIndex((t) => t.id === id);
    if (index === -1) return false;

    todos.splice(index, 1);
    await this.setTodos(todos);
    return true;
  }

  async clearTodos(): Promise<void> {
    await this.setTodos([]);
  }

  private generateId(): string {
    return Math.random().toString(36).substring(2, 10);
  }

  isInitialized(): boolean {
    return this.sessionManager !== null;
  }
}

// Mock SessionManager
function createMockSessionManager(): SessionManager {
  let todos: Todo[] = [];

  return {
    getTodos: vi.fn(() => [...todos]),
    setTodos: vi.fn(async (newTodos: Todo[]) => {
      todos = [...newTodos];
    }),
  } as unknown as SessionManager;
}

describe('TodoManager - Todo 管理器', () => {
  let todoManager: TestTodoManager;
  let mockSessionManager: SessionManager;

  beforeEach(() => {
    todoManager = new TestTodoManager();
    mockSessionManager = createMockSessionManager();
  });

  describe('初始化状态', () => {
    it('未设置 sessionManager 时 isInitialized 返回 false', () => {
      expect(todoManager.isInitialized()).toBe(false);
    });

    it('设置 sessionManager 后 isInitialized 返回 true', () => {
      todoManager.setSessionManager(mockSessionManager);

      expect(todoManager.isInitialized()).toBe(true);
    });

    it('未初始化时 getTodos 返回空数组', () => {
      expect(todoManager.getTodos()).toEqual([]);
    });

    it('未初始化时 setTodos 不报错', async () => {
      await expect(todoManager.setTodos([{
        id: '1',
        content: 'test',
        status: 'pending',
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString(),
      }])).resolves.not.toThrow();
    });
  });

  describe('getTodos', () => {
    beforeEach(() => {
      todoManager.setSessionManager(mockSessionManager);
    });

    it('返回空数组当没有 todos', () => {
      const todos = todoManager.getTodos();

      expect(todos).toEqual([]);
    });

    it('返回 sessionManager 中的 todos', async () => {
      await todoManager.addTodo('Task 1');
      await todoManager.addTodo('Task 2');

      const todos = todoManager.getTodos();

      expect(todos).toHaveLength(2);
    });
  });

  describe('setTodos', () => {
    beforeEach(() => {
      todoManager.setSessionManager(mockSessionManager);
    });

    it('设置 todos 列表', async () => {
      const todos: Todo[] = [
        {
          id: '1',
          content: 'Task 1',
          status: 'pending',
          createdAt: new Date().toISOString(),
          updatedAt: new Date().toISOString(),
        },
      ];

      await todoManager.setTodos(todos);

      expect(todoManager.getTodos()).toHaveLength(1);
      expect(todoManager.getTodos()[0].content).toBe('Task 1');
    });

    it('清空 todos', async () => {
      await todoManager.addTodo('Task 1');
      await todoManager.setTodos([]);

      expect(todoManager.getTodos()).toHaveLength(0);
    });
  });

  describe('addTodo', () => {
    beforeEach(() => {
      todoManager.setSessionManager(mockSessionManager);
    });

    it('添加新 todo 默认状态为 pending', async () => {
      const todo = await todoManager.addTodo('New task');

      expect(todo.content).toBe('New task');
      expect(todo.status).toBe('pending');
      expect(todo.id).toBeDefined();
      expect(todo.createdAt).toBeDefined();
      expect(todo.updatedAt).toBeDefined();
    });

    it('添加新 todo 指定状态', async () => {
      const todo = await todoManager.addTodo('In progress task', 'in_progress');

      expect(todo.status).toBe('in_progress');
    });

    it('添加的 todo 出现在列表中', async () => {
      await todoManager.addTodo('Task 1');
      await todoManager.addTodo('Task 2');

      const todos = todoManager.getTodos();

      expect(todos).toHaveLength(2);
      expect(todos.some(t => t.content === 'Task 1')).toBe(true);
      expect(todos.some(t => t.content === 'Task 2')).toBe(true);
    });

    it('每个 todo 有唯一 ID', async () => {
      const todo1 = await todoManager.addTodo('Task 1');
      const todo2 = await todoManager.addTodo('Task 2');

      expect(todo1.id).not.toBe(todo2.id);
    });
  });

  describe('updateTodoStatus', () => {
    beforeEach(() => {
      todoManager.setSessionManager(mockSessionManager);
    });

    it('更新存在的 todo 状态', async () => {
      const todo = await todoManager.addTodo('Task');
      const result = await todoManager.updateTodoStatus(todo.id, 'completed');

      expect(result).toBe(true);
      const updated = todoManager.getTodos().find(t => t.id === todo.id);
      expect(updated?.status).toBe('completed');
    });

    it('更新不存在的 todo 返回 false', async () => {
      const result = await todoManager.updateTodoStatus('non-existent-id', 'completed');

      expect(result).toBe(false);
    });

    it('更新状态时更新 updatedAt', async () => {
      const todo = await todoManager.addTodo('Task');
      const originalUpdatedAt = todo.updatedAt;

      // 等待一小段时间确保时间戳不同
      await new Promise(resolve => setTimeout(resolve, 10));

      await todoManager.updateTodoStatus(todo.id, 'in_progress');
      const updated = todoManager.getTodos().find(t => t.id === todo.id);

      expect(updated?.updatedAt).not.toBe(originalUpdatedAt);
    });
  });

  describe('deleteTodo', () => {
    beforeEach(() => {
      todoManager.setSessionManager(mockSessionManager);
    });

    it('删除存在的 todo', async () => {
      const todo = await todoManager.addTodo('Task to delete');
      const result = await todoManager.deleteTodo(todo.id);

      expect(result).toBe(true);
      expect(todoManager.getTodos().find(t => t.id === todo.id)).toBeUndefined();
    });

    it('删除不存在的 todo 返回 false', async () => {
      const result = await todoManager.deleteTodo('non-existent-id');

      expect(result).toBe(false);
    });

    it('删除后列表长度减少', async () => {
      await todoManager.addTodo('Task 1');
      const todo2 = await todoManager.addTodo('Task 2');
      await todoManager.addTodo('Task 3');

      await todoManager.deleteTodo(todo2.id);

      expect(todoManager.getTodos()).toHaveLength(2);
    });
  });

  describe('clearTodos', () => {
    beforeEach(() => {
      todoManager.setSessionManager(mockSessionManager);
    });

    it('清空所有 todos', async () => {
      await todoManager.addTodo('Task 1');
      await todoManager.addTodo('Task 2');
      await todoManager.addTodo('Task 3');

      await todoManager.clearTodos();

      expect(todoManager.getTodos()).toHaveLength(0);
    });

    it('清空空列表不报错', async () => {
      await expect(todoManager.clearTodos()).resolves.not.toThrow();
    });
  });
});

describe('Todo 状态流转', () => {
  let todoManager: TestTodoManager;
  let mockSessionManager: SessionManager;

  beforeEach(() => {
    todoManager = new TestTodoManager();
    mockSessionManager = createMockSessionManager();
    todoManager.setSessionManager(mockSessionManager);
  });

  it('pending -> in_progress -> completed', async () => {
    const todo = await todoManager.addTodo('Task');

    expect(todo.status).toBe('pending');

    await todoManager.updateTodoStatus(todo.id, 'in_progress');
    let updated = todoManager.getTodos().find(t => t.id === todo.id);
    expect(updated?.status).toBe('in_progress');

    await todoManager.updateTodoStatus(todo.id, 'completed');
    updated = todoManager.getTodos().find(t => t.id === todo.id);
    expect(updated?.status).toBe('completed');
  });

  it('直接从 pending 到 completed', async () => {
    const todo = await todoManager.addTodo('Quick task');

    await todoManager.updateTodoStatus(todo.id, 'completed');
    const updated = todoManager.getTodos().find(t => t.id === todo.id);
    expect(updated?.status).toBe('completed');
  });
});
