/**
 * 维护模式中间件
 *
 * 功能描述：
 * - 检查系统是否处于维护模式
 * - 在维护期间阻止用户访问API
 * - 提供维护状态和预计恢复时间信息
 *
 * 职责分离：
 * - 维护模式状态检查逻辑
 * - 维护配置信息的读取和管理
 * - 维护响应的统一格式化处理
 *
 * 主要方法：
 * - use() - 中间件处理入口方法
 * - isMaintenanceEnabled() - 维护模式状态检查
 * - getMaintenanceInfo() - 维护信息获取
 *
 * 使用场景：
 * - 系统升级维护
 * - 数据库迁移
 * - 紧急故障修复
 * - 定期维护窗口
 *
 * 最近修改：
 * - 2026-01-07: 代码规范优化 - 更新注释规范，完善中间件说明
 *
 * @author moyin
 * @version 1.0.1
 * @since 2025-12-24
 * @lastModified 2026-01-07
 */

import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { ConfigService } from '@nestjs/config';
import { Logger } from '@nestjs/common';

/**
 * 维护模式响应接口
 */
interface MaintenanceResponse {
  /** 请求是否成功 */
  success: boolean;
  /** 响应消息 */
  message: string;
  /** 错误代码 */
  error_code: string;
  /** 维护信息 */
  maintenance_info?: {
    /** 维护开始时间 */
    start_time: string;
    /** 预计结束时间 */
    estimated_end_time?: string;
    /** 重试间隔（秒） */
    retry_after: number;
    /** 维护原因 */
    reason?: string;
  };
}

@Injectable()
export class MaintenanceMiddleware implements NestMiddleware {
  private readonly logger = new Logger(MaintenanceMiddleware.name);

  constructor(private readonly configService: ConfigService) {}

  /**
   * 中间件处理函数
   *
   * 业务逻辑：
   * 1. 检查维护模式环境变量
   * 2. 如果处于维护模式，返回503状态码
   * 3. 提供维护信息和重试建议
   * 4. 记录维护期间的访问尝试
   *
   * @param req HTTP请求对象
   * @param res HTTP响应对象
   * @param next 下一个中间件函数
   */
  use(req: Request, res: Response, next: NextFunction) {
    // 1. 检查维护模式状态
    const isMaintenanceMode = this.configService.get<string>('MAINTENANCE_MODE') === 'true';

    if (!isMaintenanceMode) {
      // 非维护模式，继续处理请求
      next();
      return;
    }

    // 2. 记录维护期间的访问尝试
    this.logger.warn('维护模式：拒绝访问请求', {
      operation: 'maintenance_check',
      method: req.method,
      url: req.url,
      userAgent: req.get('User-Agent'),
      ip: req.ip,
      timestamp: new Date().toISOString()
    });

    // 3. 获取维护配置信息
    const maintenanceStartTime = this.configService.get<string>('MAINTENANCE_START_TIME') || new Date().toISOString();
    const maintenanceEndTime = this.configService.get<string>('MAINTENANCE_END_TIME');
    const maintenanceReason = this.configService.get<string>('MAINTENANCE_REASON') || '系统维护升级';
    const retryAfter = this.configService.get<number>('MAINTENANCE_RETRY_AFTER') || 1800; // 默认30分钟

    // 4. 构建维护模式响应
    const maintenanceResponse: MaintenanceResponse = {
      success: false,
      message: '系统正在维护中，请稍后再试',
      error_code: 'SERVICE_UNAVAILABLE',
      maintenance_info: {
        start_time: maintenanceStartTime,
        estimated_end_time: maintenanceEndTime,
        retry_after: retryAfter,
        reason: maintenanceReason
      }
    };

    // 5. 设置HTTP响应头
    res.setHeader('Retry-After', retryAfter.toString());
    res.setHeader('Content-Type', 'application/json');

    // 6. 返回503服务不可用状态
    res.status(503).json(maintenanceResponse);
  }

  /**
   * 检查维护模式是否启用
   *
   * @returns 是否处于维护模式
   */
  isMaintenanceEnabled(): boolean {
    return this.configService.get<string>('MAINTENANCE_MODE') === 'true';
  }

  /**
   * 获取维护信息
   *
   * @returns 维护配置信息
   */
  getMaintenanceInfo() {
    return {
      enabled: this.isMaintenanceEnabled(),
      startTime: this.configService.get<string>('MAINTENANCE_START_TIME'),
      endTime: this.configService.get<string>('MAINTENANCE_END_TIME'),
      reason: this.configService.get<string>('MAINTENANCE_REASON'),
      retryAfter: this.configService.get<number>('MAINTENANCE_RETRY_AFTER')
    };
  }
}