/**
 * Clase DomainValidationError
 * Representa un error de validación de dominio.
 *
 * Esta clase extiende la clase Error de JavaScript y se utiliza para manejar errores
 * específicos de validación dentro del dominio de la aplicación. Permite identificar
 * el código de error, el campo afectado y un detalle descriptivo del error.
 *
 * @class DomainValidationError
 * @extends {Error}
 * @property {string} code - Código del error de validación.
 * @property {string} field - Campo afectado por el error de validación.
 * @property {string} detail - Detalle descriptivo del error de validación.
 *
 * @example
 * const error = new DomainValidationError("INVALID_EMAIL", "email", "El email no es válido");
 * console.error(error);
 */

import { DomainError } from "./domain-error";

export class DomainValidationError extends DomainError {
  // Discriminante estable para mapeo/telemetría
  public readonly kind = "VALIDATION" as const;

  constructor(
    public readonly code: string, // id de regla del negocio (ej. 'INVALID_FORMAT')
    public readonly field: string, // path: 'number' | 'date' | 'lines[0].quantity'
    public readonly detail: string, // mensaje legible del negocio
    options?: ErrorOptions
  ) {
    super(`[${field}] ${detail}`, options);
    this.name = "DomainValidationError";
    Object.freeze(this);
  }

  // Constructores rápidos
  static requiredValue(field: string, options?: ErrorOptions) {
    return new DomainValidationError("REQUIRED_VALUE", field, "cannot be empty", options);
  }
  static invalidFormat(field: string, detail = "invalid format", options?: ErrorOptions) {
    return new DomainValidationError("INVALID_FORMAT", field, detail, options);
  }
  static invalidValue(
    field: string,
    value: unknown,
    detail = "invalid value",
    options?: ErrorOptions
  ) {
    return new DomainValidationError("INVALID_VALUE", field, detail, { ...options, cause: value });
  }

  // Proyección útil para Problem+JSON o colecciones
  toDetail() {
    return { path: this.field, message: this.detail, rule: this.code };
  }
}

export const isDomainValidationError = (e: unknown): e is DomainValidationError =>
  e instanceof DomainValidationError;
