/**
 * MaintenanceMiddleware 单元测试
 * 
 * @author moyin
 * @version 1.0.0
 * @since 2026-01-07
 */

import { Test, TestingModule } from '@nestjs/testing';
import { ConfigService } from '@nestjs/config';
import { Request, Response, NextFunction } from 'express';
import { MaintenanceMiddleware } from './maintenance.middleware';

describe('MaintenanceMiddleware', () => {
  let middleware: MaintenanceMiddleware;
  let configService: jest.Mocked<ConfigService>;
  let mockRequest: Partial<Request>;
  let mockResponse: Partial<Response>;
  let mockNext: NextFunction;

  beforeEach(async () => {
    const mockConfigService = {
      get: jest.fn(),
    };

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        MaintenanceMiddleware,
        { provide: ConfigService, useValue: mockConfigService },
      ],
    }).compile();

    middleware = module.get<MaintenanceMiddleware>(MaintenanceMiddleware);
    configService = module.get(ConfigService);

    mockRequest = {
      method: 'GET',
      url: '/api/test',
      get: jest.fn(),
      ip: '127.0.0.1',
    };

    mockResponse = {
      status: jest.fn().mockReturnThis(),
      json: jest.fn().mockReturnThis(),
      setHeader: jest.fn().mockReturnThis(),
    };

    mockNext = jest.fn();
  });

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

  describe('use', () => {
    it('should call next() when maintenance mode is disabled', () => {
      // Arrange
      configService.get.mockReturnValue('false');

      // Act
      middleware.use(mockRequest as Request, mockResponse as Response, mockNext);

      // Assert
      expect(mockNext).toHaveBeenCalled();
      expect(mockResponse.status).not.toHaveBeenCalled();
    });

    it('should return 503 when maintenance mode is enabled', () => {
      // Arrange
      configService.get.mockImplementation((key) => {
        switch (key) {
          case 'MAINTENANCE_MODE': return 'true';
          case 'MAINTENANCE_RETRY_AFTER': return 3600;
          default: return undefined;
        }
      });

      // Act
      middleware.use(mockRequest as Request, mockResponse as Response, mockNext);

      // Assert
      expect(mockResponse.status).toHaveBeenCalledWith(503);
      expect(mockNext).not.toHaveBeenCalled();
    });
  });

  describe('isMaintenanceEnabled', () => {
    it('should return true when maintenance mode is enabled', () => {
      // Arrange
      configService.get.mockReturnValue('true');

      // Act
      const result = middleware.isMaintenanceEnabled();

      // Assert
      expect(result).toBe(true);
    });

    it('should return false when maintenance mode is disabled', () => {
      // Arrange
      configService.get.mockReturnValue('false');

      // Act
      const result = middleware.isMaintenanceEnabled();

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

  describe('getMaintenanceInfo', () => {
    it('should return maintenance info', () => {
      // Arrange
      configService.get.mockImplementation((key) => {
        switch (key) {
          case 'MAINTENANCE_MODE': return 'true';
          case 'MAINTENANCE_START_TIME': return '2026-01-07T10:00:00.000Z';
          default: return undefined;
        }
      });

      // Act
      const info = middleware.getMaintenanceInfo();

      // Assert
      expect(info).toBeDefined();
      expect(info.enabled).toBe(true);
      expect(info.startTime).toBe('2026-01-07T10:00:00.000Z');
    });
  });
});