interface AppErrorOptions {
  code: string
  statusCode?: number
  cause?: unknown
}

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

  constructor(message: string, options: AppErrorOptions) {
    super(message, options.cause !== undefined ? { cause: options.cause } : undefined)
    this.name = 'AppError'
    this.code = options.code
    this.statusCode = options.statusCode ?? 500
  }
}

export const notFound = (resource: string) =>
  new AppError(`${resource} not found`, { code: 'NOT_FOUND', statusCode: 404 })

export const validationError = (message: string) =>
  new AppError(message, { code: 'VALIDATION_ERROR', statusCode: 400 })

export const unauthorized = (message = 'Unauthorized') =>
  new AppError(message, { code: 'UNAUTHORIZED', statusCode: 401 })

export const forbidden = (message = 'Forbidden') =>
  new AppError(message, { code: 'FORBIDDEN', statusCode: 403 })

export const conflict = (message: string) =>
  new AppError(message, { code: 'CONFLICT', statusCode: 409 })
