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

// Fields that must NEVER appear in any API response
const SENSITIVE_FIELDS = [
  "passwordHash",
  "password",
  "passwordSalt",
  "secret",
  "token",
  "refreshToken",
  "resetToken",
  "twoFactorSecret",
  "internalNotes",
];

function sanitizeObject(obj: unknown): unknown {
  if (obj === null || obj === undefined) return obj;
  if (Array.isArray(obj)) return obj.map(sanitizeObject);

  if (typeof obj === "object" && obj !== null) {
    // Preserve Date objects as ISO strings
    if (obj instanceof Date) {
      return obj.toISOString();
    }

    // Convert Prisma Decimal objects ({ s, e, d }) to primitive numbers
    if ("s" in obj && "e" in obj && "d" in obj) {
      return Number(obj.toString());
    }

    const result: Record<string, unknown> = {};
    for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {
      if (SENSITIVE_FIELDS.includes(key)) continue;
      result[key] = sanitizeObject(value);
    }
    return result;
  }
  return obj;
}

@Injectable()
export class ResponseSanitizerInterceptor implements NestInterceptor {
  intercept(_context: ExecutionContext, next: CallHandler): Observable<unknown> {
    return next.handle().pipe(map((data) => sanitizeObject(data)));
  }
}
