import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { SKIP_TRANSFORM_KEY } from '../decorators/skip-transform.decorator';

/**
 * 统一响应格式
 */
export interface ApiResponse<T> {
  success: boolean;
  data: T;
  message?: string;
  timestamp: string;
  path?: string;
}

/**
 * 响应转换拦截器
 * 
 * 将所有成功的响应统一包装成标准格式：
 * {
 *   success: true,
 *   data: T,
 *   message?: string,
 *   timestamp: string,
 *   path?: string
 * }
 * 
 * 使用方式：
 * 1. 全局应用（推荐）：在 main.ts 中 app.useGlobalInterceptors(new TransformInterceptor())
 * 2. Controller 级别：@UseInterceptors(TransformInterceptor)
 * 3. Route 级别：@UseInterceptors(TransformInterceptor)
 */
@Injectable()
export class TransformInterceptor<T>
  implements NestInterceptor<T, ApiResponse<T> | T>
{
  constructor(private readonly reflector: Reflector = new Reflector()) {}

  intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Observable<ApiResponse<T> | T> {
    const request = context.switchToHttp().getRequest();
    const skipTransform = this.reflector.getAllAndOverride<boolean>(SKIP_TRANSFORM_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);
    
    // ⚠️ SSE 端点特殊处理：不转换响应格式
    const isSSE = request.headers.accept?.includes('text/event-stream');
    if (isSSE || skipTransform) {
      // SSE 请求直接返回原始数据流，不进行转换
      return next.handle();
    }

    return next.handle().pipe(
      map((data) => {
        // 如果返回的数据已经包含 data 和 message 字段，说明 Controller 手动构造了响应
        // 例如: return { data: user, message: '创建成功' }
        // 注意：必须同时包含 data 和 message，避免与业务对象中的 data 字段混淆
        if (data && typeof data === 'object' && 'data' in data && 'message' in data) {
          return {
            success: true,
            data: data.data,
            message: data.message ?? 'success',
            timestamp: new Date().toISOString(),
            path: request.url,
          };
        }

        // 否则，将整个返回值作为 data
        return {
          success: true,
          data: data,
          message: 'success',
          timestamp: new Date().toISOString(),
          path: request.url,
        };
      }),
    );
  }
}
