/**
 * Error normalisation utilities for all services.
 *
 * Convention for new services:
 *
 *   async myMethod(): Promise<ListResponse<Foo>> {
 *     try {
 *       const data = await provider.getAll()
 *       return { data, meta: { total: data.length, page: 1, pageSize: data.length, hasMore: false } }
 *     } catch (err) {
 *       throwServiceError(err)
 *     }
 *   }
 *
 * React Query catches the thrown AppError, sets isError = true, and exposes
 * error.message so pages can render <ErrorState message={error.message} />.
 */

// Re-export so call sites have one import point.
export type { ServiceError } from './types'
export { ServiceErrorCode } from './types'
import type { ServiceError } from './types'
import { ServiceErrorCode } from './types'

// ── AppError ──────────────────────────────────────────────────────────────────

/** A structured error thrown by services. React Query treats it as any Error. */
export class AppError extends Error {
  readonly code: ServiceErrorCode

  constructor(serviceError: ServiceError) {
    super(serviceError.message)
    this.name = 'AppError'
    this.code = serviceError.code
  }
}

// ── Helpers ───────────────────────────────────────────────────────────────────

/** Map an unknown catch value to a structured ServiceError. */
export function normalizeError(err: unknown): ServiceError {
  if (err instanceof AppError) {
    return { code: err.code, message: err.message }
  }
  if (err instanceof Error) {
    return { code: ServiceErrorCode.NETWORK_ERROR, message: err.message }
  }
  if (typeof err === 'string' && err.length > 0) {
    return { code: ServiceErrorCode.NETWORK_ERROR, message: err }
  }
  return { code: ServiceErrorCode.BACKEND_UNAVAILABLE, message: 'Unbekannter Fehler' }
}

/**
 * Normalise and rethrow as AppError.
 * Use in every service catch block instead of plain `throw err`.
 * Return type `never` lets TypeScript understand the function always throws.
 */
export function throwServiceError(err: unknown): never {
  throw new AppError(normalizeError(err))
}
