const API_BASE =
  (typeof window === 'undefined' ? process.env.API_INTERNAL_URL : process.env.NEXT_PUBLIC_API_URL)
  ?? process.env.NEXT_PUBLIC_API_URL
  ?? 'http://localhost:4000/api/v1'

export class StorefrontApiError extends Error {
  status: number
  code?: string
  nextAvailableAt?: string | null

  constructor(message: string, status: number, code?: string, nextAvailableAt?: string | null) {
    super(message)
    this.name = 'StorefrontApiError'
    this.status = status
    this.code = code
    this.nextAvailableAt = nextAvailableAt
  }
}

export async function storefrontFetch<T>(path: string, init?: RequestInit): Promise<T> {
  const res = await fetch(`${API_BASE}${path}`, {
    cache: 'no-store',
    credentials: 'include',
    ...init,
  })
  const json = await res.json().catch(() => null)
  if (!res.ok) throw new StorefrontApiError(json?.message ?? 'Request failed', res.status, json?.error, json?.nextAvailableAt)
  return json.data as T
}

export async function storefrontFetchOrDefault<T>(path: string, fallback: T): Promise<T> {
  try {
    return await storefrontFetch<T>(path)
  } catch {
    return fallback
  }
}

export async function storefrontPost<T>(path: string, body: unknown): Promise<T> {
  const base = process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:4000/api/v1'
  const res = await fetch(`${base}${path}`, {
    method: 'POST',
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
  const json = await res.json().catch(() => null)
  if (!res.ok) throw new StorefrontApiError(json?.message ?? 'Request failed', res.status, json?.error, json?.nextAvailableAt)
  return json.data as T
}
