export const PUBLIC_ERROR_CODES = [
  'UNAUTHENTICATED', 'NOT_FOUND', 'OUT_OF_CREDITS', 'CREDIT_DEFICIT', 'INVALID_CREDIT_QUANTITY',
  'INVALID_PDF', 'UPLOAD_REJECTED', 'CONVERSION_FAILED', 'ARTIFACT_EXPIRED', 'PAYMENT_UNAVAILABLE', 'PAYMENT_RECONCILIATION_REQUIRED',
] as const
export type PublicErrorCode = (typeof PUBLIC_ERROR_CODES)[number]

export class PublicDomainError extends Error {
  readonly name = 'PublicDomainError'
  constructor(
    readonly code: PublicErrorCode,
    message: string,
    readonly status: number,
    readonly retryable = false,
  ) {
    super(message)
  }

  toJSON(): PublicErrorDto {
    return { code: this.code, message: this.message, retryable: this.retryable }
  }
}

export type PublicErrorDto = Readonly<{ code: PublicErrorCode; message: string; retryable: boolean }>

export const publicErrors = {
  unauthenticated: () => new PublicDomainError('UNAUTHENTICATED', 'Sign in to continue.', 401),
  notFound: () => new PublicDomainError('NOT_FOUND', 'Conversion not found.', 404),
  outOfCredits: () => new PublicDomainError('OUT_OF_CREDITS', "You're out of credits.", 409),
  creditDeficit: () => new PublicDomainError('CREDIT_DEFICIT', 'Your account balance must be resolved before converting.', 409),
  artifactExpired: () => new PublicDomainError('ARTIFACT_EXPIRED', 'This download has expired.', 410),
} as const

export function ownerScopedNotFound(): PublicDomainError {
  return publicErrors.notFound()
}
