/**
 * DatabaseManagementService 单元测试
 * 
 * 功能描述：
 * - 测试数据库管理服务的所有方法
 * - 验证CRUD操作的正确性
 * - 测试异常处理和边界情况
 * 
 * 职责分离：
 * - 业务逻辑测试，不涉及HTTP层
 * - Mock数据库服务，专注业务服务逻辑
 * - 验证数据处理和格式化的正确性
 * 
 * 最近修改：
 * - 2026-01-09: 功能新增 - 创建DatabaseManagementService单元测试 (修改者: moyin)
 * 
 * @author moyin
 * @version 1.0.0
 * @since 2026-01-09
 * @lastModified 2026-01-09
 */

import { Test, TestingModule } from '@nestjs/testing';
import { NotFoundException, ConflictException } from '@nestjs/common';
import { DatabaseManagementService } from './database_management.service';
import { UsersService } from '../../core/db/users/users.service';
import { UserProfilesService } from '../../core/db/user_profiles/user_profiles.service';
import { ZulipAccountsService } from '../../core/db/zulip_accounts/zulip_accounts.service';
import { Users } from '../../core/db/users/users.entity';
import { UserProfiles } from '../../core/db/user_profiles/user_profiles.entity';

describe('DatabaseManagementService', () => {
  let service: DatabaseManagementService;
  let usersService: jest.Mocked<UsersService>;
  let userProfilesService: jest.Mocked<UserProfilesService>;
  let zulipAccountsService: jest.Mocked<ZulipAccountsService>;

  const mockUsersService = {
    findAll: jest.fn(),
    findOne: jest.fn(),
    search: jest.fn(),
    create: jest.fn(),
    update: jest.fn(),
    remove: jest.fn(),
    count: jest.fn(),
  };

  const mockUserProfilesService = {
    findAll: jest.fn(),
    findOne: jest.fn(),
    findByMap: jest.fn(),
    create: jest.fn(),
    update: jest.fn(),
    remove: jest.fn(),
    count: jest.fn(),
  };

  const mockZulipAccountsService = {
    findMany: jest.fn(),
    findById: jest.fn(),
    getStatusStatistics: jest.fn(),
    create: jest.fn(),
    update: jest.fn(),
    delete: jest.fn(),
    batchUpdateStatus: jest.fn(),
  };

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        DatabaseManagementService,
        {
          provide: 'UsersService',
          useValue: mockUsersService,
        },
        {
          provide: 'IUserProfilesService',
          useValue: mockUserProfilesService,
        },
        {
          provide: 'ZulipAccountsService',
          useValue: mockZulipAccountsService,
        },
      ],
    }).compile();

    service = module.get<DatabaseManagementService>(DatabaseManagementService);
    usersService = module.get('UsersService');
    userProfilesService = module.get('IUserProfilesService');
    zulipAccountsService = module.get('ZulipAccountsService');
  });

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

  describe('getUserList', () => {
    it('should return user list successfully', async () => {
      const mockUsers = [
        { id: BigInt(1), username: 'user1', email: 'user1@test.com' },
        { id: BigInt(2), username: 'user2', email: 'user2@test.com' }
      ] as Users[];

      usersService.findAll.mockResolvedValue(mockUsers);
      usersService.count.mockResolvedValue(2);

      const result = await service.getUserList(20, 0);

      expect(result.success).toBe(true);
      expect(result.data.items).toHaveLength(2);
      expect(result.data.total).toBe(2);
      expect(result.message).toBe('用户列表获取成功');
    });

    it('should handle database error', async () => {
      usersService.findAll.mockRejectedValue(new Error('Database error'));

      const result = await service.getUserList(20, 0);

      expect(result.success).toBe(true);
      expect(result.data.items).toEqual([]);
      expect(result.message).toContain('失败，返回空列表');
    });
  });

  describe('getUserById', () => {
    it('should return user by id successfully', async () => {
      const mockUser = { id: BigInt(1), username: 'user1', email: 'user1@test.com' } as Users;

      usersService.findOne.mockResolvedValue(mockUser);

      const result = await service.getUserById(BigInt(1));

      expect(result.success).toBe(true);
      expect(result.data.id).toBe('1');
      expect(result.message).toBe('用户详情获取成功');
    });

    it('should handle user not found', async () => {
      usersService.findOne.mockRejectedValue(new NotFoundException('User not found'));

      const result = await service.getUserById(BigInt(999));

      expect(result.success).toBe(false);
      expect(result.error_code).toBe('RESOURCE_NOT_FOUND');
    });
  });

  describe('searchUsers', () => {
    it('should search users successfully', async () => {
      const mockUsers = [
        { id: BigInt(1), username: 'admin', email: 'admin@test.com' }
      ] as Users[];

      usersService.search.mockResolvedValue(mockUsers);

      const result = await service.searchUsers('admin', 20);

      expect(result.success).toBe(true);
      expect(result.data.items).toHaveLength(1);
      expect(result.message).toBe('用户搜索成功');
    });
  });

  describe('createUser', () => {
    it('should create user successfully', async () => {
      const userData = { username: 'newuser', email: 'new@test.com', nickname: 'New User' };
      const mockUser = { id: BigInt(1), ...userData } as Users;

      usersService.create.mockResolvedValue(mockUser);

      const result = await service.createUser(userData);

      expect(result.success).toBe(true);
      expect(result.data.username).toBe('newuser');
      expect(result.message).toBe('用户创建成功');
    });

    it('should handle creation conflict', async () => {
      const userData = { username: 'existing', email: 'existing@test.com', nickname: 'Existing' };

      usersService.create.mockRejectedValue(new ConflictException('Username already exists'));

      const result = await service.createUser(userData);

      expect(result.success).toBe(false);
      expect(result.error_code).toBe('RESOURCE_CONFLICT');
    });
  });

  describe('updateUser', () => {
    it('should update user successfully', async () => {
      const updateData = { nickname: 'Updated User' };
      const mockUser = { id: BigInt(1), username: 'user1', nickname: 'Updated User' } as Users;

      usersService.update.mockResolvedValue(mockUser);

      const result = await service.updateUser(BigInt(1), updateData);

      expect(result.success).toBe(true);
      expect(result.data.nickname).toBe('Updated User');
      expect(result.message).toBe('用户更新成功');
    });
  });

  describe('deleteUser', () => {
    it('should delete user successfully', async () => {
      usersService.remove.mockResolvedValue(undefined);

      const result = await service.deleteUser(BigInt(1));

      expect(result.success).toBe(true);
      expect(result.data.deleted).toBe(true);
      expect(result.message).toBe('用户删除成功');
    });
  });

  describe('getUserProfileList', () => {
    it('should return user profile list successfully', async () => {
      const mockProfiles = [
        { id: BigInt(1), user_id: BigInt(1), bio: 'Test bio' }
      ] as UserProfiles[];

      userProfilesService.findAll.mockResolvedValue(mockProfiles);
      userProfilesService.count.mockResolvedValue(1);

      const result = await service.getUserProfileList(20, 0);

      expect(result.success).toBe(true);
      expect(result.data.items).toHaveLength(1);
      expect(result.message).toBe('用户档案列表获取成功');
    });
  });

  describe('getUserProfileById', () => {
    it('should return user profile by id successfully', async () => {
      const mockProfile = { id: BigInt(1), user_id: BigInt(1), bio: 'Test bio' } as UserProfiles;

      userProfilesService.findOne.mockResolvedValue(mockProfile);

      const result = await service.getUserProfileById(BigInt(1));

      expect(result.success).toBe(true);
      expect(result.data.id).toBe('1');
      expect(result.message).toBe('用户档案详情获取成功');
    });
  });

  describe('getUserProfilesByMap', () => {
    it('should return user profiles by map successfully', async () => {
      const mockProfiles = [
        { id: BigInt(1), user_id: BigInt(1), current_map: 'plaza' }
      ] as UserProfiles[];

      userProfilesService.findByMap.mockResolvedValue(mockProfiles);

      const result = await service.getUserProfilesByMap('plaza', 20, 0);

      expect(result.success).toBe(true);
      expect(result.data.items).toHaveLength(1);
      expect(result.message).toContain('plaza');
    });
  });

  describe('createUserProfile', () => {
    it('should create user profile successfully', async () => {
      const profileData = {
        user_id: '1',
        bio: 'Test bio',
        resume_content: 'Test resume',
        tags: '["tag1"]',
        social_links: '{"github":"test"}',
        skin_id: '1',
        current_map: 'plaza',
        pos_x: 100,
        pos_y: 200,
        status: 1
      };

      const mockProfile = { id: BigInt(1), user_id: BigInt(1), bio: 'Test bio' } as UserProfiles;

      userProfilesService.create.mockResolvedValue(mockProfile);

      const result = await service.createUserProfile(profileData);

      expect(result.success).toBe(true);
      expect(result.message).toBe('用户档案创建成功');
    });
  });

  describe('updateUserProfile', () => {
    it('should update user profile successfully', async () => {
      const updateData = { bio: 'Updated bio' };
      const mockProfile = { id: BigInt(1), user_id: BigInt(1), bio: 'Updated bio' } as UserProfiles;

      userProfilesService.update.mockResolvedValue(mockProfile);

      const result = await service.updateUserProfile(BigInt(1), updateData);

      expect(result.success).toBe(true);
      expect(result.message).toBe('用户档案更新成功');
    });
  });

  describe('deleteUserProfile', () => {
    it('should delete user profile successfully', async () => {
      userProfilesService.remove.mockResolvedValue({ affected: 1, message: 'Deleted successfully' });

      const result = await service.deleteUserProfile(BigInt(1));

      expect(result.success).toBe(true);
      expect(result.data.deleted).toBe(true);
      expect(result.message).toBe('用户档案删除成功');
    });
  });

  describe('getZulipAccountList', () => {
    it('should return zulip account list successfully', async () => {
      const mockAccounts = {
        accounts: [{
          id: '1',
          gameUserId: '1',
          zulipUserId: 123,
          zulipEmail: 'test@zulip.com',
          zulipFullName: 'Test User',
          status: 'active' as const,
          retryCount: 0,
          createdAt: '2026-01-09T00:00:00.000Z',
          updatedAt: '2026-01-09T00:00:00.000Z'
        }],
        total: 1,
        count: 1
      };

      zulipAccountsService.findMany.mockResolvedValue(mockAccounts);

      const result = await service.getZulipAccountList(20, 0);

      expect(result.success).toBe(true);
      expect(result.data.items).toHaveLength(1);
      expect(result.message).toBe('Zulip账号关联列表获取成功');
    });
  });

  describe('getZulipAccountById', () => {
    it('should return zulip account by id successfully', async () => {
      const mockAccount = { 
        id: '1', 
        gameUserId: '1', 
        zulipUserId: 123,
        zulipEmail: 'test@zulip.com',
        zulipFullName: 'Test User',
        status: 'active' as const,
        retryCount: 0,
        createdAt: '2026-01-09T00:00:00.000Z',
        updatedAt: '2026-01-09T00:00:00.000Z'
      };

      zulipAccountsService.findById.mockResolvedValue(mockAccount);

      const result = await service.getZulipAccountById('1');

      expect(result.success).toBe(true);
      expect(result.data.id).toBe('1');
      expect(result.message).toBe('Zulip账号关联详情获取成功');
    });
  });

  describe('getZulipAccountStatistics', () => {
    it('should return zulip account statistics successfully', async () => {
      const mockStats = { 
        active: 10, 
        inactive: 5, 
        suspended: 2,
        error: 1,
        total: 18 
      };

      zulipAccountsService.getStatusStatistics.mockResolvedValue(mockStats);

      const result = await service.getZulipAccountStatistics();

      expect(result.success).toBe(true);
      expect(result.data).toEqual(mockStats);
      expect(result.message).toBe('Zulip账号关联统计获取成功');
    });
  });

  describe('createZulipAccount', () => {
    it('should create zulip account successfully', async () => {
      const accountData = {
        gameUserId: '1',
        zulipUserId: 123,
        zulipEmail: 'test@zulip.com',
        zulipFullName: 'Test User',
        zulipApiKeyEncrypted: 'encrypted_key'
      };

      const mockAccount = { 
        id: '1', 
        gameUserId: '1',
        zulipUserId: 123,
        zulipEmail: 'test@zulip.com',
        zulipFullName: 'Test User',
        zulipApiKeyEncrypted: 'encrypted_key',
        status: 'active' as const,
        retryCount: 0,
        createdAt: '2026-01-09T00:00:00.000Z',
        updatedAt: '2026-01-09T00:00:00.000Z'
      };

      zulipAccountsService.create.mockResolvedValue(mockAccount);

      const result = await service.createZulipAccount(accountData);

      expect(result.success).toBe(true);
      expect(result.message).toBe('Zulip账号关联创建成功');
    });
  });

  describe('updateZulipAccount', () => {
    it('should update zulip account successfully', async () => {
      const updateData = { zulipFullName: 'Updated Name' };
      const mockAccount = { 
        id: '1', 
        gameUserId: '1',
        zulipUserId: 123,
        zulipEmail: 'test@zulip.com',
        zulipFullName: 'Updated Name',
        status: 'active' as const,
        retryCount: 0,
        createdAt: '2026-01-09T00:00:00.000Z',
        updatedAt: '2026-01-09T00:00:00.000Z'
      };

      zulipAccountsService.update.mockResolvedValue(mockAccount);

      const result = await service.updateZulipAccount('1', updateData);

      expect(result.success).toBe(true);
      expect(result.message).toBe('Zulip账号关联更新成功');
    });
  });

  describe('deleteZulipAccount', () => {
    it('should delete zulip account successfully', async () => {
      zulipAccountsService.delete.mockResolvedValue(true);

      const result = await service.deleteZulipAccount('1');

      expect(result.success).toBe(true);
      expect(result.data.deleted).toBe(true);
      expect(result.message).toBe('Zulip账号关联删除成功');
    });
  });

  describe('batchUpdateZulipAccountStatus', () => {
    it('should batch update zulip account status successfully', async () => {
      const ids = ['1', '2', '3'];
      const status = 'active';
      const reason = 'Batch activation';

      zulipAccountsService.batchUpdateStatus.mockResolvedValue({ 
        success: true,
        updatedCount: 3 
      });

      const result = await service.batchUpdateZulipAccountStatus(ids, status, reason);

      expect(result.success).toBe(true);
      expect(result.data.success_count).toBe(3);
      expect(result.data.failed_count).toBe(0);
      expect(result.message).toContain('成功：3，失败：0');
    });

    it('should handle partial batch update failure', async () => {
      const ids = ['1', '2', '3'];
      const status = 'active';

      zulipAccountsService.batchUpdateStatus.mockResolvedValue({ 
        success: true,
        updatedCount: 2 
      });

      const result = await service.batchUpdateZulipAccountStatus(ids, status);

      expect(result.success).toBe(true);
      expect(result.data.success_count).toBe(2);
      expect(result.data.failed_count).toBe(1);
    });
  });
});