/**
 * 健康检查控制器单元测试
 * 
 * 功能描述：
 * - 测试健康检查控制器的所有功能
 * - 验证各种健康检查接口的正确性
 * - 确保组件状态检查和性能监控正常
 * - 提供完整的测试覆盖率
 * 
 * 测试范围：
 * - 基础健康检查接口
 * - 详细健康报告接口
 * - 性能指标接口
 * - 就绪和存活检查
 * 
 * @author moyin
 * @version 1.0.0
 * @since 2026-01-08
 * @lastModified 2026-01-08
 */

import { Test, TestingModule } from '@nestjs/testing';
import { HttpStatus } from '@nestjs/common';
import { HealthController } from './health.controller';
import { PerformanceMonitorMiddleware } from './performance_monitor.middleware';
import { RateLimitMiddleware } from './rate_limit.middleware';

describe('HealthController', () => {
  let controller: HealthController;
  let mockLocationBroadcastCore: any;
  let mockPerformanceMonitor: any;
  let mockRateLimitMiddleware: any;

  beforeEach(async () => {
    // 创建Mock对象
    mockLocationBroadcastCore = {
      getSessionUsers: jest.fn(),
      getUserPosition: jest.fn(),
    };

    mockPerformanceMonitor = {
      getSystemPerformance: jest.fn().mockReturnValue({
        activeConnections: 10,
        totalEvents: 1000,
        avgResponseTime: 150,
        errorRate: 2,
        throughput: 50,
        memoryUsage: {
          used: 100 * 1024 * 1024,
          total: 512 * 1024 * 1024,
          percentage: 19.5,
        },
      }),
      getEventStats: jest.fn().mockReturnValue([
        { event: 'position_update', count: 500, avgTime: 120 },
        { event: 'join_session', count: 200, avgTime: 200 },
      ]),
    };

    mockRateLimitMiddleware = {
      getStats: jest.fn().mockReturnValue({
        limitRate: 5,
        activeUsers: 25,
        totalRequests: 2000,
        blockedRequests: 100,
      }),
    };

    const module: TestingModule = await Test.createTestingModule({
      controllers: [HealthController],
      providers: [
        {
          provide: 'ILocationBroadcastCore',
          useValue: mockLocationBroadcastCore,
        },
        {
          provide: PerformanceMonitorMiddleware,
          useValue: mockPerformanceMonitor,
        },
        {
          provide: RateLimitMiddleware,
          useValue: mockRateLimitMiddleware,
        },
      ],
    }).compile();

    controller = module.get<HealthController>(HealthController);
  });

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

  describe('基础健康检查', () => {
    it('应该返回健康状态', async () => {
      const result = await controller.getHealth();
      
      expect(result).toHaveProperty('status');
      expect(result).toHaveProperty('timestamp');
      expect(result).toHaveProperty('uptime');
      expect(result).toHaveProperty('components');
      expect(result.components).toBeInstanceOf(Array);
      expect(result.components.length).toBeGreaterThan(0);
    });

    it('应该使用缓存机制', async () => {
      // 第一次调用
      const result1 = await controller.getHealth();
      
      // 第二次调用（应该使用缓存）
      const result2 = await controller.getHealth();
      
      expect(result1.timestamp).toBe(result2.timestamp);
    });

    it('应该在组件不健康时返回不健康状态', async () => {
      // 模拟核心服务不可用
      Object.defineProperty(controller, 'locationBroadcastCore', {
        value: null,
        writable: true,
        configurable: true
      });
      
      const result = await controller.getHealth();
      
      expect(result.status).toBe('unhealthy');
    });

    it('应该处理健康检查异常', async () => {
      // 模拟检查过程中的异常
      const originalCheckComponents = controller['checkComponents'];
      controller['checkComponents'] = jest.fn().mockRejectedValue(new Error('检查失败'));
      
      const result = await controller.getHealth();
      
      expect(result.status).toBe('unhealthy');
      expect(result.components).toBeInstanceOf(Array);
      expect(result.components[0].error).toBe('检查失败');
      
      // 恢复原方法
      controller['checkComponents'] = originalCheckComponents;
    });
  });

  describe('详细健康检查', () => {
    it('应该返回详细健康报告', async () => {
      const result = await controller.getDetailedHealth();
      
      expect(result).toHaveProperty('status');
      expect(result).toHaveProperty('system');
      expect(result).toHaveProperty('performance');
      expect(result).toHaveProperty('configuration');
      expect(result.system).toHaveProperty('nodeVersion');
      expect(result.system).toHaveProperty('platform');
      expect(result.system).toHaveProperty('arch');
      expect(result.system).toHaveProperty('pid');
      expect(result.performance).toHaveProperty('eventStats');
      expect(result.performance).toHaveProperty('rateLimitStats');
      expect(result.performance).toHaveProperty('systemPerformance');
      expect(result.configuration).toHaveProperty('environment');
      expect(result.configuration).toHaveProperty('features');
    });

    it('应该包含正确的系统信息', async () => {
      const result = await controller.getDetailedHealth();
      
      expect(result.system.nodeVersion).toBe(process.version);
      expect(result.system.platform).toBe(process.platform);
      expect(result.system.arch).toBe(process.arch);
      expect(result.system.pid).toBe(process.pid);
    });

    it('应该包含性能统计信息', async () => {
      const result = await controller.getDetailedHealth();
      
      expect(result.performance.eventStats).toBeInstanceOf(Array);
      expect(result.performance.rateLimitStats).toHaveProperty('limitRate');
      expect(result.performance.systemPerformance).toHaveProperty('avgResponseTime');
    });

    it('应该处理详细检查异常', async () => {
      mockPerformanceMonitor.getSystemPerformance.mockImplementation(() => {
        throw new Error('性能监控失败');
      });
      
      await expect(controller.getDetailedHealth()).rejects.toThrow('性能监控失败');
    });
  });

  describe('性能指标接口', () => {
    it('应该返回性能指标', async () => {
      const result = await controller.getMetrics();
      
      expect(result).toHaveProperty('timestamp');
      expect(result).toHaveProperty('system');
      expect(result).toHaveProperty('events');
      expect(result).toHaveProperty('rateLimit');
      expect(result).toHaveProperty('uptime');
      expect(result.system).toHaveProperty('avgResponseTime');
      expect(result.events).toBeInstanceOf(Array);
      expect(result.rateLimit).toHaveProperty('limitRate');
    });

    it('应该包含正确的时间戳', async () => {
      const beforeTime = Date.now();
      const result = await controller.getMetrics();
      const afterTime = Date.now();
      
      expect(result.timestamp).toBeGreaterThanOrEqual(beforeTime);
      expect(result.timestamp).toBeLessThanOrEqual(afterTime);
    });

    it('应该处理指标获取异常', async () => {
      mockPerformanceMonitor.getEventStats.mockImplementation(() => {
        throw new Error('获取事件统计失败');
      });
      
      await expect(controller.getMetrics()).rejects.toThrow('获取事件统计失败');
    });
  });

  describe('就绪检查', () => {
    it('应该在关键组件健康时返回就绪状态', async () => {
      const result = await controller.getReadiness();
      
      expect(result).toHaveProperty('status');
      expect(result).toHaveProperty('timestamp');
      expect(result).toHaveProperty('components');
      expect(result.status).toBe('healthy');
    });

    it('应该在关键组件不健康时返回未就绪状态', async () => {
      // 模拟核心服务不可用
      Object.defineProperty(controller, 'locationBroadcastCore', {
        value: null,
        writable: true,
        configurable: true
      });
      
      const result = await controller.getReadiness();
      
      // 当返回503状态码时，结果是Response对象
      if (result instanceof Response) {
        expect(result.status).toBe(503);
      } else {
        expect(result.status).toBe('unhealthy');
      }
    });

    it('应该只检查关键组件', async () => {
      const result = await controller.getReadiness();
      
      const componentNames = result.components.map((c: any) => c.name);
      expect(componentNames.some((c: any) => c === 'redis')).toBe(true);
      expect(componentNames.some((c: any) => c === 'database')).toBe(true);
      expect(componentNames.some((c: any) => c === 'core_service')).toBe(true);
    });

    it('应该处理就绪检查异常', async () => {
      const originalCheckComponents = controller['checkComponents'];
      controller['checkComponents'] = jest.fn().mockRejectedValue(new Error('组件检查失败'));
      
      const result = await controller.getReadiness();
      
      // 当返回503状态码时，结果是Response对象
      if (result instanceof Response) {
        expect(result.status).toBe(503);
      } else {
        expect(result.status).toBe('unhealthy');
      }
      
      // 恢复原方法
      controller['checkComponents'] = originalCheckComponents;
    });
  });

  describe('存活检查', () => {
    it('应该返回存活状态', async () => {
      const result = await controller.getLiveness();
      
      expect(result).toHaveProperty('status', 'alive');
      expect(result).toHaveProperty('timestamp');
      expect(result).toHaveProperty('uptime');
      expect(result).toHaveProperty('pid');
      expect(result.pid).toBe(process.pid);
    });

    it('应该返回正确的运行时间', async () => {
      const result = await controller.getLiveness();
      
      expect(result.uptime).toBeGreaterThanOrEqual(0);
      expect(typeof result.uptime).toBe('number');
    });
  });

  describe('组件健康检查', () => {
    it('应该检查Redis连接状态', async () => {
      const result = await controller['checkRedis']();
      
      expect(result).toHaveProperty('name', 'redis');
      expect(result).toHaveProperty('status');
      expect(result).toHaveProperty('timestamp');
      expect(result.status).toBe('healthy');
    });

    it('应该检查数据库连接状态', async () => {
      const result = await controller['checkDatabase']();
      
      expect(result).toHaveProperty('name', 'database');
      expect(result).toHaveProperty('status');
      expect(result).toHaveProperty('timestamp');
      expect(result.status).toBe('healthy');
    });

    it('应该检查核心服务状态', async () => {
      const result = await controller['checkCoreService']();
      
      expect(result).toHaveProperty('name', 'core_service');
      expect(result).toHaveProperty('status');
      expect(result).toHaveProperty('timestamp');
      expect(result.status).toBe('healthy');
    });

    it('应该在核心服务不可用时返回不健康状态', async () => {
      Object.defineProperty(controller, 'locationBroadcastCore', {
        value: null,
        writable: true,
        configurable: true
      });
      
      const result = await controller['checkCoreService']();
      
      expect(result.status).toBe('unhealthy');
      expect(result.error).toBe('Core service not available');
    });

    it('应该检查性能监控状态', () => {
      const result = controller['checkPerformanceMonitor']();
      
      expect(result).toHaveProperty('name', 'performance_monitor');
      expect(result).toHaveProperty('status');
      expect(result).toHaveProperty('details');
      expect(result.details).toHaveProperty('avgResponseTime');
      expect(result.details).toHaveProperty('errorRate');
    });

    it('应该根据性能指标判断监控状态', () => {
      // 模拟高错误率
      mockPerformanceMonitor.getSystemPerformance.mockReturnValue({
        avgResponseTime: 3000,
        errorRate: 30,
        throughput: 10,
      });
      
      const result = controller['checkPerformanceMonitor']();
      
      expect(result.status).toBe('unhealthy');
    });

    it('应该检查限流中间件状态', () => {
      const result = controller['checkRateLimitMiddleware']();
      
      expect(result).toHaveProperty('name', 'rate_limit');
      expect(result).toHaveProperty('status');
      expect(result).toHaveProperty('details');
      expect(result.details).toHaveProperty('limitRate');
      expect(result.details).toHaveProperty('activeUsers');
    });

    it('应该根据限流统计判断中间件状态', () => {
      // 模拟高限流率
      mockRateLimitMiddleware.getStats.mockReturnValue({
        limitRate: 60,
        activeUsers: 100,
        totalRequests: 5000,
        blockedRequests: 3000,
      });
      
      const result = controller['checkRateLimitMiddleware']();
      
      expect(result.status).toBe('unhealthy');
    });
  });

  describe('缓存机制', () => {
    it('应该在缓存有效期内使用缓存', async () => {
      // 第一次调用
      await controller.getHealth();
      
      // 模拟组件检查方法被调用的次数
      const checkComponentsSpy = jest.spyOn(controller as any, 'checkComponents');
      
      // 第二次调用（应该使用缓存）
      await controller.getHealth();
      
      expect(checkComponentsSpy).not.toHaveBeenCalled();
    });

    it('应该在缓存过期后重新检查', async () => {
      // 第一次调用
      await controller.getHealth();
      
      // 手动过期缓存
      controller['cacheExpiry'] = Date.now() - 1000;
      
      const checkComponentsSpy = jest.spyOn(controller as any, 'checkComponents');
      
      // 第二次调用（缓存已过期）
      await controller.getHealth();
      
      expect(checkComponentsSpy).toHaveBeenCalled();
    });
  });

  describe('状态判断逻辑', () => {
    it('应该在所有组件健康时返回健康状态', async () => {
      const result = await controller['performHealthCheck']();
      
      expect(result.status).toBe('healthy');
    });

    it('应该在有降级组件时返回降级状态', async () => {
      // 模拟性能监控降级
      mockPerformanceMonitor.getSystemPerformance.mockReturnValue({
        avgResponseTime: 1500,
        errorRate: 15,
        throughput: 20,
        activeConnections: 5,
        totalEvents: 500,
        memoryUsage: { used: 200, total: 512, percentage: 39 },
      });
      
      const result = await controller['performHealthCheck']();
      
      expect(result.status).toBe('degraded');
    });

    it('应该在有不健康组件时返回不健康状态', async () => {
      // 模拟核心服务不健康
      Object.defineProperty(controller, 'locationBroadcastCore', {
        value: null,
        writable: true,
        configurable: true
      });
      
      const result = await controller['performHealthCheck']();
      
      expect(result.status).toBe('unhealthy');
    });
  });

  describe('错误处理', () => {
    it('应该处理组件检查异常', async () => {
      const originalCheckRedis = controller['checkRedis'];
      controller['checkRedis'] = jest.fn().mockResolvedValue({
        name: 'redis',
        status: 'unhealthy',
        error: 'Redis连接失败',
        timestamp: Date.now(),
      });
      
      const components = await controller['checkComponents']();
      
      expect(components.some((c: any) => c.name === 'redis' && c.status === 'unhealthy')).toBe(true);
      
      // 恢复原方法
      controller['checkRedis'] = originalCheckRedis;
    });

    it('应该处理性能监控异常', () => {
      mockPerformanceMonitor.getSystemPerformance.mockImplementation(() => {
        throw new Error('性能监控异常');
      });
      
      const result = controller['checkPerformanceMonitor']();
      
      expect(result.status).toBe('unhealthy');
      expect(result.error).toBe('性能监控异常');
    });

    it('应该处理限流中间件异常', () => {
      mockRateLimitMiddleware.getStats.mockImplementation(() => {
        throw new Error('限流统计异常');
      });
      
      const result = controller['checkRateLimitMiddleware']();
      
      expect(result.status).toBe('unhealthy');
      expect(result.error).toBe('限流统计异常');
    });
  });

  describe('响应格式化', () => {
    it('应该正确格式化健康响应', () => {
      const healthData = {
        status: 'healthy',
        timestamp: Date.now(),
        components: [],
      };
      
      const result = controller['formatHealthResponse'](healthData);
      
      expect(result).toEqual(healthData);
    });

    it('应该处理服务不可用状态码', () => {
      const healthData = {
        status: 'unhealthy',
        timestamp: Date.now(),
        components: [],
      };
      
      const result = controller['formatHealthResponse'](healthData, HttpStatus.SERVICE_UNAVAILABLE);
      
      expect(result).toBeInstanceOf(Response);
    });
  });
});