import {
  ExceptionFilter,
  Catch,
  ArgumentsHost,
  HttpException,
  HttpStatus,
  Logger,
} from "@nestjs/common";
import { Request, Response } from "express";
import { randomUUID } from "node:crypto";

const SAFE_SERVER_MESSAGES = new Set([
  "city_search_unavailable",
  "google_auth_not_configured",
  "maintenance_mode",
  "chat_disabled",
]);

@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  private readonly logger = new Logger(AllExceptionsFilter.name);

  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;

    const rawResponse =
      exception instanceof HttpException ? exception.getResponse() : null;

    const publicMessage =
      typeof rawResponse === "string"
        ? rawResponse
        : (rawResponse as { message?: string | string[] } | null)?.message
          ? Array.isArray((rawResponse as { message: string[] }).message)
            ? (rawResponse as { message: string[] }).message.join(", ")
            : ((rawResponse as { message: string }).message as string)
          : "internal_server_error";
    const message = status >= 500 && !SAFE_SERVER_MESSAGES.has(publicMessage)
      ? "internal_server_error"
      : publicMessage;
    const requestId = randomUUID();

    const summary = `${requestId} ${request.method} ${request.url} -> ${status}`;
    if (status >= 500 && !SAFE_SERVER_MESSAGES.has(publicMessage)) {
      this.logger.error(summary, exception instanceof Error ? exception.stack : String(exception));
    } else {
      this.logger.warn(`${summary} ${message}`);
    }

    response.setHeader("Cache-Control", "no-store");
    response.status(status).json({
      data: null,
      error: { message },
      requestId,
    });
  }
}
