// src/services/processingErrors.ts

/**
 * Base class for all flyer processing errors.
 * This allows for catching all processing-related errors with a single `catch` block.
 * Each custom error should define its own `errorCode` and a user-friendly `message`.
 */
export class FlyerProcessingError extends Error {
  public errorCode: string;
  public userMessage: string;

  constructor(message: string, errorCode: string = 'UNKNOWN_ERROR', userMessage?: string) {
    super(message); // The 'message' property of Error is for internal/developer use.
    this.name = this.constructor.name;
    this.errorCode = errorCode;
    this.userMessage = userMessage || message; // User-friendly message for UI
    Object.setPrototypeOf(this, new.target.prototype);
  }

  toErrorPayload(): { errorCode: string; message: string; [key: string]: any } {
    return { errorCode: this.errorCode, message: this.userMessage };
  }
}

/**
 * Error thrown when PDF to image conversion fails (e.g., pdftocairo produces no output).
 */
export class PdfConversionError extends FlyerProcessingError {
  public stderr?: string;
  constructor(message: string, stderr?: string) {
    super(
      message,
      'PDF_CONVERSION_FAILED',
      'The uploaded PDF could not be processed. It might be blank, corrupt, or password-protected.',
    );
    this.stderr = stderr;
  }

  toErrorPayload(): { errorCode: string; message: string; [key: string]: any } {
    return { ...super.toErrorPayload(), stderr: this.stderr };
  }
}

/**
 * Error thrown when the data returned from the AI service fails Zod validation.
 */
export class AiDataValidationError extends FlyerProcessingError {
  constructor(
    message: string,
    public validationErrors: object,
    public rawData: unknown,
  ) {
    super(
      message,
      'AI_VALIDATION_FAILED',
      "The AI couldn't read the flyer's format. Please try a clearer image or a different flyer.",
    );
  }

  toErrorPayload(): { errorCode: string; message: string; [key: string]: any } {
    return { ...super.toErrorPayload(), validationErrors: this.validationErrors, rawData: this.rawData };
  }
}

/**
 * Error thrown when an image conversion fails (e.g., using sharp).
 */
export class ImageConversionError extends FlyerProcessingError {
  constructor(message: string) {
    super(
      message,
      'IMAGE_CONVERSION_FAILED',
      'The uploaded image could not be processed. It might be corrupt or in an unsupported format.',
    );
  }
}
/**
 * Error thrown when all geocoding providers fail to find coordinates for an address.
 */
export class GeocodingFailedError extends FlyerProcessingError {
  constructor(message: string) {
    super(message, 'GEOCODING_FAILED', 'Failed to geocode the address.');
  }
}

/**
 * Error thrown when an uploaded file is of an unsupported type (e.g., .gif, .tiff).
 */
export class UnsupportedFileTypeError extends FlyerProcessingError {
  constructor(message: string) {
    super(message, 'UNSUPPORTED_FILE_TYPE', message); // The message is already user-friendly.
  }
}
