import { UserService } from '../../../../src/server/modules/users/user.service';
import { UserEntity as User } from '../../../../src/server/modules/users/user.entity';
import * as bcrypt from 'bcrypt';
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';

// Mock TypeORM 数据源和仓库
vi.mock('typeorm', async (importOriginal) => {
  const actual = await importOriginal() as any
  return {
    ...actual,
    DataSource: vi.fn().mockImplementation(() => ({
      getRepository: vi.fn()
    })),
    Repository: vi.fn()
  }
});

// Mock bcrypt
vi.mock('bcrypt', () => ({
  hash: vi.fn().mockResolvedValue('hashed_password'),
  compare: vi.fn().mockResolvedValue(true)
}));

describe('UserService', () => {
  let userService: UserService;
  let mockDataSource: any;
  let mockUserRepository: any;
  let mockRoleRepository: any;

  beforeEach(() => {
    // 创建模拟的仓库实例
    mockUserRepository = {
      create: vi.fn(),
      save: vi.fn(),
      findOne: vi.fn(),
      update: vi.fn(),
      delete: vi.fn(),
      createQueryBuilder: vi.fn(),
      find: vi.fn(),
      findByIds: vi.fn()
    } as any;

    mockRoleRepository = {
      findByIds: vi.fn()
    } as any;

    // 创建模拟的数据源
    mockDataSource = {
      getRepository: vi.fn()
    } as any;

    // 设置数据源返回模拟的仓库
    mockDataSource.getRepository
      .mockReturnValueOnce(mockUserRepository)
      .mockReturnValueOnce(mockRoleRepository);

    userService = new UserService(mockDataSource);
  });

  afterEach(() => {
    vi.clearAllMocks();
  });

  describe('createUser', () => {
    it('应该成功创建用户并哈希密码', async () => {
      const userData = {
        username: 'testuser',
        password: 'password123',
        email: 'test@example.com'
      };

      const mockUser = { id: 1, ...userData, password: 'hashed_password' } as User;

      mockUserRepository.create.mockReturnValue(mockUser);
      mockUserRepository.save.mockResolvedValue(mockUser);

      const result = await userService.createUser(userData);

      expect(bcrypt.hash).toHaveBeenCalledWith('password123', 10);
      expect(mockUserRepository.create).toHaveBeenCalledWith({
        ...userData,
        password: 'hashed_password'
      });
      expect(mockUserRepository.save).toHaveBeenCalledWith(mockUser);
      expect(result).toEqual(mockUser);
    });

    it('应该在创建用户失败时抛出错误', async () => {
      const userData = { username: 'testuser', password: 'password123' };
      const error = new Error('Database error');

      mockUserRepository.create.mockImplementation(() => {
        throw error;
      });

      await expect(userService.createUser(userData)).rejects.toThrow('Failed to create user');
    });
  });

  describe('getUserById', () => {
    it('应该通过ID成功获取用户', async () => {
      const mockUser = { id: 1, username: 'testuser' } as User;
      mockUserRepository.findOne.mockResolvedValue(mockUser);

      const result = await userService.getUserById(1);

      expect(mockUserRepository.findOne).toHaveBeenCalledWith({
        where: { id: 1 },
        relations: ['roles', 'avatarFile']
      });
      expect(result).toEqual(mockUser);
    });

    it('应该在用户不存在时返回null', async () => {
      mockUserRepository.findOne.mockResolvedValue(null);

      const result = await userService.getUserById(999);

      expect(result).toBeNull();
    });
  });

  // getUsersWithPagination 方法已移除，使用通用CRUD服务替代

  describe('verifyPassword', () => {
    it('应该验证密码正确', async () => {
      const user = { password: 'hashed_password' } as User;

      const result = await userService.verifyPassword(user, 'password123');

      expect(bcrypt.compare).toHaveBeenCalledWith('password123', 'hashed_password');
      expect(result).toBe(true);
    });

    it('应该验证密码错误', async () => {
      (vi.mocked(bcrypt.compare) as any).mockResolvedValueOnce(false);
      const user = { password: 'hashed_password' } as User;

      const result = await userService.verifyPassword(user, 'wrong_password');

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