import { useAuthStore } from '@/stores/auth.store'
import { usePOSStore } from '@/stores/pos.store'

class ApiError extends Error {
  statusCode: number
  details?: unknown

  constructor(message: string, statusCode: number, details?: unknown) {
    super(message)
    this.name = 'ApiError'
    this.statusCode = statusCode
    this.details = details
  }
}

async function request<T>(method: string, path: string, body?: unknown): Promise<T> {
  // Use POS token if available (POS screen), otherwise admin token
  const token = usePOSStore.getState().token ?? useAuthStore.getState().token

  const headers: Record<string, string> = {}

  if (body) {
    headers['Content-Type'] = 'application/json'
  }

  if (token) {
    headers['Authorization'] = `Bearer ${token}`
  }

  const res = await fetch(path, {
    method,
    headers,
    body: body ? JSON.stringify(body) : undefined,
  })

  if (res.status === 401) {
    // On POS, lock the screen instead of logging out admin
    if (usePOSStore.getState().token) {
      usePOSStore.getState().lock()
    } else {
      useAuthStore.getState().logout()
    }
    throw new ApiError('Unauthorized', 401)
  }

  const json = await res.json()

  if (!res.ok) {
    throw new ApiError(
      json.error?.message ?? 'Request failed',
      res.status,
      json.error?.details,
    )
  }

  return json as T
}

function buildQueryString(params?: Record<string, unknown>): string {
  if (!params) return ''
  const searchParams = new URLSearchParams()
  for (const [key, value] of Object.entries(params)) {
    if (value !== undefined && value !== null && value !== '') {
      searchParams.set(key, String(value))
    }
  }
  const qs = searchParams.toString()
  return qs ? `?${qs}` : ''
}

export const api = {
  get: <T>(path: string, params?: Record<string, unknown>) =>
    request<T>('GET', `${path}${buildQueryString(params)}`),

  post: <T>(path: string, body: unknown) =>
    request<T>('POST', path, body),

  patch: <T>(path: string, body: unknown) =>
    request<T>('PATCH', path, body),

  del: <T>(path: string) =>
    request<T>('DELETE', path),
}

export { ApiError }
