/**
 * 用户档案服务集成测试
 * 
 * 功能描述：
 * - 测试用户档案服务的完整集成场景
 * - 验证数据库模式和内存模式的一致性
 * - 测试模块配置和依赖注入的正确性
 * - 验证复杂业务场景的端到端流程
 * 
 * 测试场景：
 * - 模块配置测试：数据库模式和内存模式的正确配置
 * - 服务一致性测试：两种实现的行为一致性
 * - 并发操作测试：多用户同时操作的场景
 * - 数据完整性测试：复杂操作的数据一致性
 * - 性能基准测试：基本的性能指标验证
 * 
 * 最近修改：
 * - 2026-01-08: 功能新增 - 创建用户档案服务集成测试 (修改者: moyin)
 * 
 * @author moyin
 * @version 1.0.0
 * @since 2026-01-08
 * @lastModified 2026-01-08
 */

import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { UserProfilesModule } from './user_profiles.module';
import { UserProfilesService } from './user_profiles.service';
import { UserProfilesMemoryService } from './user_profiles_memory.service';
import { UserProfiles } from './user_profiles.entity';
import { CreateUserProfileDto, UpdatePositionDto } from './user_profiles.dto';

describe('UserProfiles Integration Tests', () => {
  describe('Module Configuration', () => {
    it('should configure database module correctly', async () => {
      // Arrange
      const mockRepository = {
        save: jest.fn(),
        findOne: jest.fn(),
        find: jest.fn(),
        update: jest.fn(),
        delete: jest.fn(),
        count: jest.fn(),
      };

      // Act
      const module: TestingModule = await Test.createTestingModule({
        imports: [UserProfilesModule.forDatabase()],
      })
        .overrideProvider(getRepositoryToken(UserProfiles))
        .useValue(mockRepository)
        .compile();

      // Assert
      const service = module.get<UserProfilesService>(UserProfilesService);
      const injectedService = module.get('IUserProfilesService');
      
      expect(service).toBeInstanceOf(UserProfilesService);
      expect(injectedService).toBeInstanceOf(UserProfilesService);
      // 检查服务类型而不是实例相等性，因为NestJS可能创建不同的实例
      expect(service.constructor).toBe(injectedService.constructor);
    });

    it('should configure memory module correctly', async () => {
      // Act
      const module: TestingModule = await Test.createTestingModule({
        imports: [UserProfilesModule.forMemory()],
      }).compile();

      // Assert
      const service = module.get<UserProfilesMemoryService>(UserProfilesMemoryService);
      const injectedService = module.get('IUserProfilesService');
      
      expect(service).toBeInstanceOf(UserProfilesMemoryService);
      expect(injectedService).toBeInstanceOf(UserProfilesMemoryService);
      // 检查服务类型而不是实例相等性，因为NestJS可能创建不同的实例
      expect(service.constructor).toBe(injectedService.constructor);
    });

    it('should configure root module based on environment', async () => {
      // Arrange
      const originalEnv = process.env.NODE_ENV;
      process.env.NODE_ENV = 'test';

      try {
        // Act
        const module: TestingModule = await Test.createTestingModule({
          imports: [UserProfilesModule.forRoot()],
        }).compile();

        // Assert
        const service = module.get('IUserProfilesService');
        expect(service).toBeInstanceOf(UserProfilesMemoryService);
      } finally {
        process.env.NODE_ENV = originalEnv;
      }
    });
  });

  describe('Service Consistency Tests', () => {
    let memoryService: UserProfilesMemoryService;
    let databaseService: UserProfilesService;
    let mockRepository: jest.Mocked<Repository<UserProfiles>>;

    beforeEach(async () => {
      // 设置内存服务
      const memoryModule = await Test.createTestingModule({
        providers: [UserProfilesMemoryService],
      }).compile();
      memoryService = memoryModule.get<UserProfilesMemoryService>(UserProfilesMemoryService);

      // 设置数据库服务（使用mock）
      mockRepository = {
        save: jest.fn(),
        findOne: jest.fn(),
        find: jest.fn(),
        update: jest.fn(),
        delete: jest.fn(),
        count: jest.fn(),
      } as any;

      const databaseModule = await Test.createTestingModule({
        providers: [
          UserProfilesService,
          {
            provide: getRepositoryToken(UserProfiles),
            useValue: mockRepository,
          },
        ],
      }).compile();
      databaseService = databaseModule.get<UserProfilesService>(UserProfilesService);
    });

    afterEach(async () => {
      await memoryService.clearAll();
      jest.clearAllMocks();
      
      // 等待任何正在进行的异步操作完成
      await new Promise(resolve => setImmediate(resolve));
    });

    it('should create profiles consistently', async () => {
      // Arrange
      const createDto: CreateUserProfileDto = {
        user_id: BigInt(100),
        bio: '测试用户',
        current_map: 'plaza',
        pos_x: 100,
        pos_y: 200,
        status: 1,
      };

      const mockProfile: UserProfiles = {
        id: BigInt(1),
        user_id: createDto.user_id,
        bio: createDto.bio,
        resume_content: null,
        tags: null,
        social_links: null,
        skin_id: null,
        current_map: createDto.current_map,
        pos_x: createDto.pos_x,
        pos_y: createDto.pos_y,
        status: createDto.status,
        last_login_at: undefined,
        last_position_update: new Date(),
      };

      mockRepository.findOne.mockResolvedValue(null);
      mockRepository.save.mockResolvedValue(mockProfile);

      // Act
      const memoryResult = await memoryService.create(createDto);
      const databaseResult = await databaseService.create(createDto);

      // Assert
      expect(memoryResult.user_id).toBe(databaseResult.user_id);
      expect(memoryResult.bio).toBe(databaseResult.bio);
      expect(memoryResult.current_map).toBe(databaseResult.current_map);
      expect(memoryResult.pos_x).toBe(databaseResult.pos_x);
      expect(memoryResult.pos_y).toBe(databaseResult.pos_y);
      expect(memoryResult.status).toBe(databaseResult.status);
    });

    it('should handle conflicts consistently', async () => {
      // Arrange
      const createDto: CreateUserProfileDto = {
        user_id: BigInt(100),
        current_map: 'plaza',
        pos_x: 0,
        pos_y: 0,
      };

      // 内存服务：先创建一个档案
      await memoryService.create(createDto);

      // 数据库服务：模拟已存在的档案，需要包含id属性
      const mockExistingProfile = {
        id: BigInt(1),
        user_id: BigInt(100),
        current_map: 'plaza',
        pos_x: 0,
        pos_y: 0,
      } as UserProfiles;
      mockRepository.findOne.mockResolvedValue(mockExistingProfile);

      // Act & Assert
      await expect(memoryService.create(createDto)).rejects.toThrow('该用户已存在档案记录');
      await expect(databaseService.create(createDto)).rejects.toThrow('该用户已存在档案记录');
    });

    it('should update positions consistently', async () => {
      // Arrange
      const createDto: CreateUserProfileDto = {
        user_id: BigInt(100),
        current_map: 'plaza',
        pos_x: 0,
        pos_y: 0,
      };

      const positionDto: UpdatePositionDto = {
        current_map: 'forest',
        pos_x: 150.5,
        pos_y: 250.3,
      };

      // 内存服务
      await memoryService.create(createDto);

      // 数据库服务
      const mockProfile: UserProfiles = {
        id: BigInt(1),
        user_id: createDto.user_id,
        bio: null,
        resume_content: null,
        tags: null,
        social_links: null,
        skin_id: null,
        current_map: createDto.current_map,
        pos_x: createDto.pos_x,
        pos_y: createDto.pos_y,
        status: 0,
        last_login_at: undefined,
        last_position_update: new Date(),
      };

      mockRepository.findOne.mockResolvedValue(mockProfile);
      mockRepository.save.mockImplementation((entity) => Promise.resolve(entity as UserProfiles));

      // Act
      const memoryResult = await memoryService.updatePosition(BigInt(100), positionDto);
      const databaseResult = await databaseService.updatePosition(BigInt(100), positionDto);

      // Assert
      expect(memoryResult.current_map).toBe(databaseResult.current_map);
      expect(memoryResult.pos_x).toBe(databaseResult.pos_x);
      expect(memoryResult.pos_y).toBe(databaseResult.pos_y);
      expect(memoryResult.last_position_update).toBeInstanceOf(Date);
      expect(databaseResult.last_position_update).toBeInstanceOf(Date);
    });
  });

  describe('Concurrent Operations', () => {
    let service: UserProfilesMemoryService;

    beforeEach(async () => {
      const module = await Test.createTestingModule({
        providers: [UserProfilesMemoryService],
      }).compile();
      service = module.get<UserProfilesMemoryService>(UserProfilesMemoryService);
    });

    afterEach(async () => {
      await service.clearAll();
      
      // 等待任何正在进行的异步操作完成
      await new Promise(resolve => setImmediate(resolve));
    });

    it('should handle concurrent profile creation', async () => {
      // Arrange
      const createPromises = Array.from({ length: 10 }, (_, i) =>
        service.create({
          user_id: BigInt(100 + i),
          current_map: 'plaza',
          pos_x: i * 10,
          pos_y: i * 10,
        })
      );

      // Act
      const results = await Promise.all(createPromises);

      // Assert
      expect(results).toHaveLength(10);
      
      // 验证ID唯一性
      const ids = results.map(r => r.id.toString());
      const uniqueIds = new Set(ids);
      expect(uniqueIds.size).toBe(10);

      // 验证用户ID唯一性
      const userIds = results.map(r => r.user_id.toString());
      const uniqueUserIds = new Set(userIds);
      expect(uniqueUserIds.size).toBe(10);
    });

    it('should handle concurrent position updates', async () => {
      // Arrange
      const userIds = Array.from({ length: 5 }, (_, i) => BigInt(100 + i));
      
      // 先创建用户档案
      for (const userId of userIds) {
        await service.create({
          user_id: userId,
          current_map: 'plaza',
          pos_x: 0,
          pos_y: 0,
        });
      }

      // Act
      const updatePromises = userIds.map((userId, i) =>
        service.updatePosition(userId, {
          current_map: 'forest',
          pos_x: i * 50,
          pos_y: i * 50,
        })
      );

      const results = await Promise.all(updatePromises);

      // Assert
      expect(results).toHaveLength(5);
      results.forEach((result, i) => {
        expect(result.current_map).toBe('forest');
        expect(result.pos_x).toBe(i * 50);
        expect(result.pos_y).toBe(i * 50);
      });
    });

    it('should handle concurrent batch status updates', async () => {
      // Arrange
      const userIds = Array.from({ length: 10 }, (_, i) => BigInt(100 + i));
      
      // 创建用户档案
      for (const userId of userIds) {
        await service.create({
          user_id: userId,
          current_map: 'plaza',
          pos_x: 0,
          pos_y: 0,
        });
      }

      // Act
      const batchPromises = [
        service.batchUpdateStatus(userIds.slice(0, 5), 1),
        service.batchUpdateStatus(userIds.slice(5, 10), 2),
      ];

      const results = await Promise.all(batchPromises);

      // Assert
      expect(results[0]).toBe(5);
      expect(results[1]).toBe(5);

      // 验证状态更新
      for (let i = 0; i < 5; i++) {
        const profile = await service.findByUserId(userIds[i]);
        expect(profile?.status).toBe(1);
      }
      for (let i = 5; i < 10; i++) {
        const profile = await service.findByUserId(userIds[i]);
        expect(profile?.status).toBe(2);
      }
    });
  });

  describe('Data Integrity Tests', () => {
    let service: UserProfilesMemoryService;

    beforeEach(async () => {
      const module = await Test.createTestingModule({
        providers: [UserProfilesMemoryService],
      }).compile();
      service = module.get<UserProfilesMemoryService>(UserProfilesMemoryService);
    });

    afterEach(async () => {
      await service.clearAll();
      
      // 等待任何正在进行的异步操作完成
      await new Promise(resolve => setImmediate(resolve));
    });

    it('should maintain data consistency during complex operations', async () => {
      // Arrange
      const userId = BigInt(100);
      
      // Act
      const created = await service.create({
        user_id: userId,
        bio: '原始简介',
        current_map: 'plaza',
        pos_x: 0,
        pos_y: 0,
        status: 0,
      });

      await service.update(created.id, {
        bio: '更新简介',
        status: 1,
      });

      const positioned = await service.updatePosition(userId, {
        current_map: 'forest',
        pos_x: 100,
        pos_y: 200,
      });

      // Assert
      expect(positioned.id).toBe(created.id);
      expect(positioned.user_id).toBe(userId);
      expect(positioned.bio).toBe('更新简介');
      expect(positioned.status).toBe(1);
      expect(positioned.current_map).toBe('forest');
      expect(positioned.pos_x).toBe(100);
      expect(positioned.pos_y).toBe(200);

      // 验证通过不同方法查询的一致性
      const foundById = await service.findOne(created.id);
      const foundByUserId = await service.findByUserId(userId);
      
      expect(foundById).toEqual(positioned);
      expect(foundByUserId).toEqual(positioned);
    });

    it('should handle deletion and recreation correctly', async () => {
      // Arrange
      const userId = BigInt(100);
      
      // Act
      const created = await service.create({
        user_id: userId,
        current_map: 'plaza',
        pos_x: 0,
        pos_y: 0,
      });

      await service.remove(created.id);

      // 验证删除
      expect(await service.findByUserId(userId)).toBeNull();
      expect(await service.existsByUserId(userId)).toBe(false);

      // 重新创建
      const recreated = await service.create({
        user_id: userId,
        current_map: 'forest',
        pos_x: 100,
        pos_y: 200,
      });

      // Assert
      expect(recreated.id).not.toBe(created.id); // 新的ID
      expect(recreated.user_id).toBe(userId);
      expect(recreated.current_map).toBe('forest');
      expect(await service.existsByUserId(userId)).toBe(true);
    });
  });

  describe('Performance Benchmarks', () => {
    let service: UserProfilesMemoryService;

    beforeEach(async () => {
      const module = await Test.createTestingModule({
        providers: [UserProfilesMemoryService],
      }).compile();
      service = module.get<UserProfilesMemoryService>(UserProfilesMemoryService);
    });

    afterEach(async () => {
      await service.clearAll();
      
      // 等待任何正在进行的异步操作完成
      await new Promise(resolve => setImmediate(resolve));
    });

    it('should create profiles within reasonable time', async () => {
      // Arrange
      const startTime = Date.now();
      const profileCount = 100;

      // Act
      const promises = Array.from({ length: profileCount }, (_, i) =>
        service.create({
          user_id: BigInt(100 + i),
          current_map: 'plaza',
          pos_x: i,
          pos_y: i,
        })
      );

      await Promise.all(promises);
      const duration = Date.now() - startTime;

      // Assert
      expect(duration).toBeLessThan(1000); // 应该在1秒内完成
      
      const stats = service.getMemoryStats();
      expect(stats.profileCount).toBe(profileCount);
    });

    it('should query profiles efficiently', async () => {
      // Arrange
      const profileCount = 1000;
      
      // 创建大量档案
      for (let i = 0; i < profileCount; i++) {
        await service.create({
          user_id: BigInt(100 + i),
          current_map: i % 2 === 0 ? 'plaza' : 'forest',
          pos_x: i,
          pos_y: i,
          status: i % 3,
        });
      }

      // Act
      const startTime = Date.now();
      
      const plazaUsers = await service.findByMap('plaza');
      const forestUsers = await service.findByMap('forest');
      const activeUsers = await service.findAll({ status: 1 });
      
      const duration = Date.now() - startTime;

      // Assert
      expect(duration).toBeLessThan(100); // 查询应该很快
      expect(plazaUsers.length).toBeGreaterThan(0);
      expect(forestUsers.length).toBeGreaterThan(0);
      expect(activeUsers.length).toBeGreaterThan(0);
    });
  });
});