import {
  CallHandler,
  ExecutionContext,
  Injectable,
  NestInterceptor,
} from '@nestjs/common';
import { map, Observable } from 'rxjs';
import { MESSAGES } from './messages.js';

/**
 * 全局响应拦截器：将所有成功响应统一包装为 { code, msg, data }。
 */
@Injectable()
export class ResponseEnvelopeInterceptor implements NestInterceptor {
  intercept(
    _context: ExecutionContext,
    next: CallHandler,
  ): Observable<{ code: number; msg: string; data: unknown }> {
    return next.handle().pipe(
      map((data: unknown) => {
        // 若业务已返回统一结构，直接透传，避免二次包裹。
        if (this.isEnveloped(data)) {
          return data;
        }

        return {
          code: 0,
          msg: MESSAGES.SUCCESS,
          data,
        };
      }),
    );
  }

  /**
   * 判断当前对象是否已经是统一响应结构。
   */
  private isEnveloped(data: unknown): data is {
    code: number;
    msg: string;
    data: unknown;
  } {
    if (!data || typeof data !== 'object') {
      return false;
    }

    const target = data as Record<string, unknown>;
    return (
      typeof target.code === 'number' &&
      typeof target.msg === 'string' &&
      Object.prototype.hasOwnProperty.call(target, 'data')
    );
  }
}
