import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
  HttpStatus,
  Logger,
} from '@nestjs/common';
import { Request, Response } from 'express';

/**
 * Renders every thrown error into the platform's standard envelope:
 * { success, message, errors?, meta }
 */
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  private readonly logger = new Logger('ExceptionFilter');

  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    const status =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;

    let message = 'Internal server error';
    let errors: unknown = undefined;

    if (exception instanceof HttpException) {
      const body = exception.getResponse();
      if (typeof body === 'string') {
        message = body;
      } else if (body && typeof body === 'object') {
        const payload = body as Record<string, any>;
        // ValidationPipe returns { message: string[] , error, statusCode }
        if (Array.isArray(payload.message)) {
          message = 'Validation failed';
          errors = payload.message;
        } else {
          message = payload.message || exception.message;
        }
      }
    } else if (exception instanceof Error) {
      message = exception.message;
    }

    if (status >= HttpStatus.INTERNAL_SERVER_ERROR) {
      this.logger.error(
        `${request.method} ${request.url} -> ${status}: ${message}`,
        exception instanceof Error ? exception.stack : undefined,
      );
      // Never leak internals of an unexpected failure to the client.
      if (!(exception instanceof HttpException)) {
        message = 'Internal server error';
      }
    }

    response.status(status).json({
      success: false,
      message,
      ...(errors ? { errors } : {}),
      meta: {
        path: request.url,
        timestamp: new Date().toISOString(),
      },
    });
  }
}
