import { getAccessToken } from './auth'
import type { CategoryNode, Product, ProductListResponse } from './types'

const API_BASE =
  import.meta.env.VITE_API_BASE_URL?.replace(/\/$/, '') ||
  'http://localhost:3100/api/v1'

export type ListProductsParams = {
  q?: string
  categoryId?: string
  categorySlug?: string
  minPrice?: number
  maxPrice?: number
  page?: number
  pageSize?: number
}

export type UserAddress = {
  id: string
  name: string
  district: string
  address: string
  landline: string
}

export type Branch = {
  id: string
  name: string
  district: string
  address: string
  landline: string
  cellNumber: string
}

export type ShippingException = {
  id: string
  district: string
  price: number
}

export type Discount = {
  id: string
  code: string
  percent: number
  maxValue: number
  minOrderAmount: number
  expiresAt: string
  active: boolean
  expired?: boolean
  categoryId?: string | null
}

export type CreateMyOrderPayload = {
  deliveryType: 'pickup' | 'shipping'
  branchId?: string
  shippingAddressId?: string
  note?: string
  discountCode?: string
  items: Array<{
    productId: string
    quantity: number
    optionIds?: string[]
  }>
}

async function parseError(response: Response) {
  const text = await response.text().catch(() => '')
  try {
    const json = JSON.parse(text) as { message?: string | string[] }
    if (Array.isArray(json.message)) return json.message.join('، ')
    if (typeof json.message === 'string') return json.message
  } catch {
    // plain text
  }
  return text || `Request failed (${response.status})`
}

async function apiGet<T>(path: string, auth = false): Promise<T> {
  const headers: HeadersInit = {}
  if (auth) {
    const token = getAccessToken()
    if (!token) throw new Error('لطفاً وارد حساب کاربری شوید')
    headers.Authorization = `Bearer ${token}`
  }
  const response = await fetch(`${API_BASE}${path}`, { headers })
  if (!response.ok) throw new Error(await parseError(response))
  return response.json() as Promise<T>
}

async function apiSend<T>(
  path: string,
  method: 'POST' | 'PATCH' | 'PUT' | 'DELETE',
  body?: unknown,
): Promise<T> {
  const token = getAccessToken()
  if (!token) throw new Error('لطفاً وارد حساب کاربری شوید')
  const response = await fetch(`${API_BASE}${path}`, {
    method,
    headers: {
      Authorization: `Bearer ${token}`,
      'Content-Type': 'application/json',
    },
    body: body !== undefined ? JSON.stringify(body) : undefined,
  })
  if (!response.ok) throw new Error(await parseError(response))
  if (response.status === 204) return undefined as T
  return response.json() as Promise<T>
}

function buildQuery(params: ListProductsParams) {
  const search = new URLSearchParams()
  if (params.q?.trim()) search.set('q', params.q.trim())
  if (params.categoryId) search.set('categoryId', params.categoryId)
  if (params.categorySlug) search.set('categorySlug', params.categorySlug)
  if (params.minPrice !== undefined) search.set('minPrice', String(params.minPrice))
  if (params.maxPrice !== undefined) search.set('maxPrice', String(params.maxPrice))
  if (params.page) search.set('page', String(params.page))
  if (params.pageSize) search.set('pageSize', String(params.pageSize))
  const qs = search.toString()
  return qs ? `?${qs}` : ''
}

export function listProducts(params: ListProductsParams = {}) {
  return apiGet<ProductListResponse>(`/products${buildQuery(params)}`)
}

export function getProduct(id: string) {
  return apiGet<Product>(`/products/${id}`)
}

export function listCategories() {
  return apiGet<CategoryNode[]>('/categories')
}

export function listMyAddresses() {
  return apiGet<UserAddress[]>('/users/me/addresses', true)
}

export function createMyAddress(payload: {
  name: string
  district: string
  address: string
  landline: string
}) {
  return apiSend<UserAddress>('/users/me/addresses', 'POST', payload)
}

export function listBranches() {
  return apiGet<Branch[]>('/settings/branches', true)
}

export function listDistricts() {
  return apiGet<string[]>('/settings/districts', true)
}

export function listShipping() {
  return apiGet<ShippingException[]>('/settings/shipping', true)
}

export function listMyDiscounts(pageSize = 50) {
  return apiGet<{ items: Discount[] }>(`/discounts/mine?pageSize=${pageSize}`, true)
}

export function createMyOrder(payload: CreateMyOrderPayload) {
  return apiSend<{ id: string; code: string; totalPrice: number }>(
    '/orders/mine',
    'POST',
    payload,
  )
}
