export class AppError extends Error {
  public readonly statusCode: number;
  public readonly code: string;

  constructor(message: string, statusCode: number = 500, code: string = 'INTERNAL_ERROR') {
    super(message);
    this.name = this.constructor.name;
    this.statusCode = statusCode;
    this.code = code;
    Error.captureStackTrace(this, this.constructor);
  }

  toJSON() {
    return { error: this.message, code: this.code };
  }
}

export class ValidationError extends AppError {
  public readonly fields?: Record<string, string[]>;

  constructor(message: string, fields?: Record<string, string[]>) {
    super(message, 400, 'VALIDATION_ERROR');
    this.fields = fields;
  }

  toJSON() {
    return { error: this.message, code: this.code, fields: this.fields };
  }
}

export class AuthError extends AppError {
  constructor(message: string = 'Authentication required') {
    super(message, 401, 'AUTH_ERROR');
  }
}

export class ForbiddenError extends AppError {
  constructor(message: string = 'You do not have permission to perform this action') {
    super(message, 403, 'FORBIDDEN');
  }
}

export class NotFoundError extends AppError {
  constructor(resource: string = 'Resource') {
    super(`${resource} not found`, 404, 'NOT_FOUND');
  }
}

export class ConflictError extends AppError {
  /**
   * Optional caller-safe message. `message` may include staff-only details
   * (e.g. another guest's name, a booking ID); `publicMessage` is the
   * sanitized version that AI/voice/chat surfaces should expose to external
   * callers. Defaults to `message` when not provided.
   */
  public readonly publicMessage: string;

  constructor(message: string, publicMessage?: string) {
    super(message, 409, 'CONFLICT');
    this.publicMessage = publicMessage ?? message;
  }
}
