/**
 * 用户管理业务服务测试
 * 
 * 功能描述：
 * - 测试用户状态管理业务逻辑
 * - 测试批量用户操作功能
 * - 测试用户状态统计功能
 * - 测试状态变更审计功能
 * 
 * 职责分离：
 * - 单元测试覆盖所有公共方法
 * - 异常情况和边界情况测试
 * - Mock依赖服务的行为验证
 * 
 * 最近修改：
 * - 2026-01-07: 代码规范优化 - 创建完整的测试覆盖 (修改者: moyin)
 * 
 * @author moyin
 * @version 1.0.1
 * @since 2026-01-07
 * @lastModified 2026-01-07
 */

import { Test, TestingModule } from '@nestjs/testing';
import { Logger } from '@nestjs/common';
import { UserManagementService } from './user_management.service';
import { AdminService } from '../admin/admin.service';
import { UserStatusDto, BatchUserStatusDto } from './user_status.dto';
import { UserStatus } from './user_status.enum';
import { BATCH_OPERATION, ERROR_CODES, MESSAGES } from './user_mgmt.constants';

describe('UserManagementService', () => {
  let service: UserManagementService;
  let mockAdminService: jest.Mocked<AdminService>;

  beforeEach(async () => {
    const mockAdminServiceProvider = {
      updateUserStatus: jest.fn(),
      batchUpdateUserStatus: jest.fn(),
      getUserStatusStats: jest.fn(),
    };

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        UserManagementService,
        {
          provide: AdminService,
          useValue: mockAdminServiceProvider,
        },
      ],
    }).compile();

    service = module.get<UserManagementService>(UserManagementService);
    mockAdminService = module.get(AdminService);

    // Mock Logger to avoid console output during tests
    jest.spyOn(Logger.prototype, 'log').mockImplementation();
    jest.spyOn(Logger.prototype, 'warn').mockImplementation();
  });

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

  describe('updateUserStatus', () => {
    it('should update user status successfully', async () => {
      // Arrange
      const userId = BigInt(123);
      const userStatusDto: UserStatusDto = {
        status: UserStatus.ACTIVE,
        reason: '用户申诉通过'
      };
      const expectedResult = {
        success: true,
        data: {
          user: {
            id: '123',
            username: 'testuser',
            nickname: '测试用户',
            status: UserStatus.ACTIVE,
            status_description: '正常',
            updated_at: new Date()
          },
          reason: '用户申诉通过'
        },
        message: '用户状态修改成功'
      };

      mockAdminService.updateUserStatus.mockResolvedValue(expectedResult);

      // Act
      const result = await service.updateUserStatus(userId, userStatusDto);

      // Assert
      expect(result).toEqual(expectedResult);
      expect(mockAdminService.updateUserStatus).toHaveBeenCalledWith(userId, userStatusDto);
      expect(mockAdminService.updateUserStatus).toHaveBeenCalledTimes(1);
    });

    it('should handle update failure', async () => {
      // Arrange
      const userId = BigInt(999);
      const userStatusDto: UserStatusDto = {
        status: UserStatus.LOCKED,
        reason: '违规操作'
      };
      const expectedResult = {
        success: false,
        message: '用户不存在',
        error_code: 'USER_NOT_FOUND'
      };

      mockAdminService.updateUserStatus.mockResolvedValue(expectedResult);

      // Act
      const result = await service.updateUserStatus(userId, userStatusDto);

      // Assert
      expect(result).toEqual(expectedResult);
      expect(mockAdminService.updateUserStatus).toHaveBeenCalledWith(userId, userStatusDto);
    });

    it('should log success when update succeeds', async () => {
      // Arrange
      const userId = BigInt(123);
      const userStatusDto: UserStatusDto = {
        status: UserStatus.ACTIVE,
        reason: '测试'
      };
      const successResult = {
        success: true,
        data: {
          user: {
            id: '123',
            username: 'testuser',
            nickname: '测试用户',
            status: UserStatus.ACTIVE,
            status_description: '正常',
            updated_at: new Date()
          },
          reason: '测试'
        },
        message: '成功'
      };

      mockAdminService.updateUserStatus.mockResolvedValue(successResult);
      const logSpy = jest.spyOn(Logger.prototype, 'log');

      // Act
      await service.updateUserStatus(userId, userStatusDto);

      // Assert
      expect(logSpy).toHaveBeenCalledWith(
        '用户管理：用户状态修改成功',
        expect.objectContaining({
          operation: 'user_mgmt_update_status_success',
          userId: '123',
          newStatus: UserStatus.ACTIVE
        })
      );
    });
  });

  describe('batchUpdateUserStatus', () => {
    it('should batch update user status successfully', async () => {
      // Arrange
      const batchUserStatusDto: BatchUserStatusDto = {
        userIds: ['1', '2', '3'],
        status: UserStatus.LOCKED,
        reason: '批量锁定违规用户'
      };
      const expectedResult = {
        success: true,
        data: {
          result: {
            success_users: [],
            failed_users: [],
            success_count: 3,
            failed_count: 0,
            total_count: 3
          },
          reason: '批量锁定违规用户'
        },
        message: '批量用户状态修改完成'
      };

      mockAdminService.batchUpdateUserStatus.mockResolvedValue(expectedResult);

      // Act
      const result = await service.batchUpdateUserStatus(batchUserStatusDto);

      // Assert
      expect(result).toEqual(expectedResult);
      expect(mockAdminService.batchUpdateUserStatus).toHaveBeenCalledWith(batchUserStatusDto);
    });

    it('should reject batch operation when user count exceeds limit', async () => {
      // Arrange
      const userIds = Array.from({ length: BATCH_OPERATION.MAX_USER_COUNT + 1 }, (_, i) => i.toString());
      const batchUserStatusDto: BatchUserStatusDto = {
        userIds,
        status: UserStatus.LOCKED,
        reason: '超限测试'
      };

      // Act
      const result = await service.batchUpdateUserStatus(batchUserStatusDto);

      // Assert
      expect(result).toEqual({
        success: false,
        message: MESSAGES.BATCH_OPERATION_LIMIT_ERROR,
        error_code: ERROR_CODES.BATCH_OPERATION_LIMIT_EXCEEDED
      });
      expect(mockAdminService.batchUpdateUserStatus).not.toHaveBeenCalled();
    });

    it('should handle empty user list', async () => {
      // Arrange
      const batchUserStatusDto: BatchUserStatusDto = {
        userIds: [],
        status: UserStatus.ACTIVE,
        reason: '空列表测试'
      };
      const expectedResult = {
        success: true,
        data: {
          result: {
            success_users: [],
            failed_users: [],
            success_count: 0,
            failed_count: 0,
            total_count: 0
          }
        },
        message: '批量操作完成'
      };

      mockAdminService.batchUpdateUserStatus.mockResolvedValue(expectedResult);

      // Act
      const result = await service.batchUpdateUserStatus(batchUserStatusDto);

      // Assert
      expect(result).toEqual(expectedResult);
    });

    it('should log warning when batch operation exceeds limit', async () => {
      // Arrange
      const userIds = Array.from({ length: BATCH_OPERATION.MAX_USER_COUNT + 1 }, (_, i) => i.toString());
      const batchUserStatusDto: BatchUserStatusDto = {
        userIds,
        status: UserStatus.LOCKED,
        reason: '超限测试'
      };
      const warnSpy = jest.spyOn(Logger.prototype, 'warn');

      // Act
      await service.batchUpdateUserStatus(batchUserStatusDto);

      // Assert
      expect(warnSpy).toHaveBeenCalledWith(
        '用户管理：批量操作数量超限',
        expect.objectContaining({
          operation: 'user_mgmt_batch_update_limit_exceeded',
          requestCount: BATCH_OPERATION.MAX_USER_COUNT + 1,
          maxAllowed: BATCH_OPERATION.MAX_USER_COUNT
        })
      );
    });
  });

  describe('getUserStatusStats', () => {
    it('should get user status statistics successfully', async () => {
      // Arrange
      const expectedResult = {
        success: true,
        data: {
          stats: {
            active: 1250,
            inactive: 45,
            locked: 12,
            banned: 8,
            deleted: 3,
            pending: 15,
            total: 1333
          },
          timestamp: '2026-01-07T10:00:00.000Z'
        },
        message: '用户状态统计获取成功'
      };

      mockAdminService.getUserStatusStats.mockResolvedValue(expectedResult);

      // Act
      const result = await service.getUserStatusStats();

      // Assert
      expect(result).toEqual(expectedResult);
      expect(mockAdminService.getUserStatusStats).toHaveBeenCalledTimes(1);
    });

    it('should handle statistics retrieval failure', async () => {
      // Arrange
      const expectedResult = {
        success: false,
        message: '统计数据获取失败',
        error_code: 'STATS_RETRIEVAL_FAILED'
      };

      mockAdminService.getUserStatusStats.mockResolvedValue(expectedResult);

      // Act
      const result = await service.getUserStatusStats();

      // Assert
      expect(result).toEqual(expectedResult);
    });

    it('should calculate business metrics when stats are available', async () => {
      // Arrange
      const statsResult = {
        success: true,
        data: {
          stats: {
            active: 80,
            inactive: 10,
            locked: 5,
            banned: 3,
            deleted: 2,
            pending: 0,
            total: 100
          },
          timestamp: '2026-01-07T10:00:00.000Z'
        },
        message: '成功'
      };

      mockAdminService.getUserStatusStats.mockResolvedValue(statsResult);
      const logSpy = jest.spyOn(Logger.prototype, 'log');

      // Act
      await service.getUserStatusStats();

      // Assert
      expect(logSpy).toHaveBeenCalledWith(
        '用户管理：用户状态统计分析',
        expect.objectContaining({
          operation: 'user_mgmt_status_analysis',
          totalUsers: 100,
          activeUsers: 80,
          activeRate: '80.00%',
          problemUsers: 10 // locked + banned + deleted
        })
      );
    });

    it('should handle zero total users in statistics', async () => {
      // Arrange
      const statsResult = {
        success: true,
        data: {
          stats: {
            active: 0,
            inactive: 0,
            locked: 0,
            banned: 0,
            deleted: 0,
            pending: 0,
            total: 0
          },
          timestamp: '2026-01-07T10:00:00.000Z'
        },
        message: '成功'
      };

      mockAdminService.getUserStatusStats.mockResolvedValue(statsResult);
      const logSpy = jest.spyOn(Logger.prototype, 'log');

      // Act
      await service.getUserStatusStats();

      // Assert
      expect(logSpy).toHaveBeenCalledWith(
        '用户管理：用户状态统计分析',
        expect.objectContaining({
          activeRate: '0%'
        })
      );
    });
  });

  describe('getUserStatusHistory', () => {
    it('should return mock history data with default limit', async () => {
      // Arrange
      const userId = BigInt(123);

      // Act
      const result = await service.getUserStatusHistory(userId);

      // Assert
      expect(result).toEqual({
        success: true,
        data: {
          user_id: '123',
          history: [],
          total_count: 0
        },
        message: '状态变更历史获取成功（当前返回空数据，待实现完整功能）'
      });
    });

    it('should return mock history data with custom limit', async () => {
      // Arrange
      const userId = BigInt(456);
      const customLimit = 20;

      // Act
      const result = await service.getUserStatusHistory(userId, customLimit);

      // Assert
      expect(result).toEqual({
        success: true,
        data: {
          user_id: '456',
          history: [],
          total_count: 0
        },
        message: '状态变更历史获取成功（当前返回空数据，待实现完整功能）'
      });
    });

    it('should log history query operation', async () => {
      // Arrange
      const userId = BigInt(789);
      const limit = 15;
      const logSpy = jest.spyOn(Logger.prototype, 'log');

      // Act
      await service.getUserStatusHistory(userId, limit);

      // Assert
      expect(logSpy).toHaveBeenCalledWith(
        '用户管理：获取用户状态变更历史',
        expect.objectContaining({
          operation: 'user_mgmt_get_status_history',
          userId: '789',
          limit: 15
        })
      );
    });
  });
});