import { ArgumentsHost, Catch, ExceptionFilter, HttpStatus, Logger } from '@nestjs/common';
import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library';
import { Response } from 'express';

@Catch(PrismaClientKnownRequestError)
export class PrismaClientExceptionFilter implements ExceptionFilter {

  private readonly logger = new Logger(PrismaClientExceptionFilter.name);

  public catch(exception: PrismaClientKnownRequestError, host: ArgumentsHost) {
    this.logger.error(exception.message);
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();

    let status = HttpStatus.INTERNAL_SERVER_ERROR;
    let humanReadableMessage = 'An unexpected error occurred';

    switch (exception.code) {
      case 'P2002': {
        status = HttpStatus.CONFLICT;
        const meta = exception.meta as { target: string[] };
        const uniqueFields = meta?.target?.join(', ') || 'unique fields';
        humanReadableMessage = `A record with the same ${uniqueFields} already exists.`;
        break;
      }
      case 'P2003': {
        status = HttpStatus.BAD_REQUEST;
        humanReadableMessage = 'Foreign key constraint failed.';
        break;
      }
      case 'P2004': {
        status = HttpStatus.BAD_REQUEST;
        humanReadableMessage = 'A constraint failed on the database.';
        break;
      }
      case 'P2005': {
        status = HttpStatus.BAD_REQUEST;
        humanReadableMessage = 'Invalid value provided for a field.';
        break;
      }
      case 'P2006': {
        status = HttpStatus.BAD_REQUEST;
        humanReadableMessage = 'Provided value is too long for a field.';
        break;
      }
      case 'P2007': {
        status = HttpStatus.BAD_REQUEST;
        humanReadableMessage = 'Data validation error.';
        break;
      }
      case 'P2008': {
        status = HttpStatus.INTERNAL_SERVER_ERROR;
        humanReadableMessage = 'Database query error.';
        break;
      }
      case 'P2009': {
        status = HttpStatus.INTERNAL_SERVER_ERROR;
        humanReadableMessage = 'Database initialization error.';
        break;
      }
      default:
        status = HttpStatus.INTERNAL_SERVER_ERROR;
        humanReadableMessage = 'An unexpected error occurred.';
    }

    response.status(status).json({
      code: status,
      type: exception.code,
      message: humanReadableMessage,
    });
  }
}
