import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  HttpException,
  HttpStatus,
  Inject,
  Logger,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import {
  SYSTEM_MAINTENANCE_REPOSITORY,
  ISystemMaintenanceRepository,
} from '../../domain/repositories/system-maintenance.repository';

/**
 * 系统维护拦截器
 * 在维护期间，拦截移动端的业务 API 请求，返回 503 状态码
 */
@Injectable()
export class MaintenanceInterceptor implements NestInterceptor {
  private readonly logger = new Logger(MaintenanceInterceptor.name);

  constructor(
    @Inject(SYSTEM_MAINTENANCE_REPOSITORY)
    private readonly maintenanceRepo: ISystemMaintenanceRepository,
  ) {}

  async intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Promise<Observable<any>> {
    try {
      const request = context.switchToHttp().getRequest();
      // 获取请求路径，优先使用 url（去除查询参数）
      const path = (request.url?.split('?')[0] || request.path) as string;

      // 白名单路径 - 这些路径在维护期间也可以访问
      // 支持带 /api/v1 前缀和不带前缀的两种情况
      const whitelist = [
        '/api/v1/mobile/system/maintenance-status',
        '/mobile/system/maintenance-status',
        '/api/v1/health',
        '/health',
      ];

      // 检查是否是移动端 API（需要同时检查带前缀和不带前缀的路径）
      const isMobileApi =
        path.includes('/mobile/') ||
        path.startsWith('/mobile');

      // 非移动端 API，直接放行
      if (!isMobileApi) {
        return next.handle();
      }

      // 检查是否在白名单中
      if (whitelist.some((p) => path === p || path.startsWith(p + '/'))) {
        return next.handle();
      }

      // 检查是否在维护中
      const activeMaintenance = await this.maintenanceRepo.findActiveMaintenance();

      if (activeMaintenance) {
        this.logger.warn(`系统维护中，阻断请求: ${path}`);
        throw new HttpException(
          {
            statusCode: HttpStatus.SERVICE_UNAVAILABLE,
            error: 'Service Unavailable',
            message: '系统维护中',
            maintenance: {
              inMaintenance: true,
              title: activeMaintenance.title,
              message: activeMaintenance.message,
              endTime: activeMaintenance.endTime,
            },
          },
          HttpStatus.SERVICE_UNAVAILABLE,
        );
      }

      return next.handle();
    } catch (error) {
      // 如果是我们抛出的 HttpException，直接重新抛出
      if (error instanceof HttpException) {
        throw error;
      }
      // 其他错误（如数据库错误），记录日志但不阻断请求
      this.logger.error(`维护状态检查失败，放行请求: ${error.message}`);
      return next.handle();
    }
  }
}
