import {
  CallHandler,
  ExecutionContext,
  Injectable,
  NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable()
export class NullToZeroInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(map((data) => this.transform(data)));
  }

  private transform(data: any): any {
    // If it's a Date object, leave it alone so it serializes to a string correctly
    if (data instanceof Date) {
      return data;
    }

    if (data === null || data === undefined) {
      return 0;
    }

    if (Array.isArray(data)) {
      return data.map((item) => this.transform(item));
    }

    if (typeof data === 'object' && data !== null) {
      const transformed = {};
      for (const key in data) {
        if (Object.prototype.hasOwnProperty.call(data, key)) {
          transformed[key] = this.transform(data[key]);
        }
      }
      return transformed;
    }

    // Replace NaN with 0
    if (typeof data === 'number' && isNaN(data)) {
      return 0;
    }

    return data;
  }
}
