/**
 * Klient publicznego API OLX (bez klucza OAuth).
 * Używany przez skrypt importu — respektuj rate limit (opóźnienia między requestami).
 */

const OLX_API = 'https://www.olx.pl/api/v1'
const USER_AGENT =
  'Mozilla/5.0 (compatible; TwojaLodkaImport/1.0; +https://twojalodka.pl) AppleWebKit/537.36'

export type OlxPhoto = {
  id: number
  link: string
  width?: number
  height?: number
}

export type OlxOfferListItem = {
  id: number
  url: string
  title: string
  description?: string
  created_time?: string
  last_refresh_time?: string
  valid_to_time?: string
  params?: OlxParam[]
  photos?: OlxPhoto[]
  location?: OlxLocation
  user?: { name?: string }
  category?: { id: number; type?: string }
  status?: string
}

export type OlxParam = {
  key: string
  name?: string
  type?: string
  value?: unknown
}

export type OlxLocation = {
  city?: { name?: string; normalized_name?: string }
  region?: { name?: string; normalized_name?: string }
}

export type OlxOffersResponse = {
  data?: OlxOfferListItem[]
  metadata?: {
    total_elements?: number
  }
}

export type OlxOfferDetailResponse = {
  data?: OlxOfferListItem
}

/** Domyślne kategorie łodzi na OLX (Sport i Hobby → Łodzie). */
export const DEFAULT_OLX_BOAT_CATEGORY_IDS = [
  5016, // Żaglowe
  5011, // Motorowe
  5010, // Pontony
  5013, // Silniki zaburtowe
  5012, // Silniki stacjonarne
  5014, // Deski / SUP
  5009, // Akcesoria
] as const

function sleep(ms: number): Promise<void> {
  return new Promise((r) => setTimeout(r, ms))
}

async function olxFetch<T>(path: string): Promise<T | null> {
  const url = path.startsWith('http') ? path : `${OLX_API}${path}`
  try {
    const res = await fetch(url, {
      headers: {
        'User-Agent': USER_AGENT,
        Accept: 'application/json',
        'Accept-Language': 'pl-PL,pl;q=0.9',
      },
      next: { revalidate: 0 },
    })
    if (!res.ok) {
      console.warn(`OLX API ${res.status}: ${url}`)
      return null
    }
    return (await res.json()) as T
  } catch (e) {
    console.warn('OLX fetch error', url, e)
    return null
  }
}

export function parseOlxCategoryIds(envValue?: string): number[] {
  const raw = envValue ?? process.env.OLX_CATEGORY_IDS ?? ''
  const fromEnv = raw
    .split(',')
    .map((s) => parseInt(s.trim(), 10))
    .filter((n) => Number.isFinite(n) && n > 0)
  return fromEnv.length > 0 ? fromEnv : [...DEFAULT_OLX_BOAT_CATEGORY_IDS]
}

/** Lista ofert w kategorii (paginacja offset/limit, max 50 na stronę). */
export async function fetchOlxOffersPage(
  categoryId: number,
  offset: number,
  limit = 40,
): Promise<OlxOfferListItem[]> {
  const q = new URLSearchParams({
    category_id: String(categoryId),
    offset: String(offset),
    limit: String(Math.min(limit, 50)),
  })
  const json = await olxFetch<OlxOffersResponse>(`/offers/?${q}`)
  return json?.data ?? []
}

/** Szczegóły pojedynczej oferty (pełniejszy opis). */
export async function fetchOlxOfferDetail(offerId: number | string): Promise<OlxOfferListItem | null> {
  const json = await olxFetch<OlxOfferDetailResponse>(`/offers/${offerId}/`)
  return json?.data ?? null
}

/** URL zdjęcia w stałym rozmiarze (OLX CDN). */
export function olxPhotoUrl(photo: OlxPhoto, width = 1200, height = 900): string {
  return photo.link.replace('{width}', String(width)).replace('{height}', String(height))
}

export async function downloadOlxPhoto(photo: OlxPhoto): Promise<Buffer | null> {
  const url = olxPhotoUrl(photo)
  try {
    const res = await fetch(url, {
      headers: { 'User-Agent': USER_AGENT },
    })
    if (!res.ok) return null
    const buf = Buffer.from(await res.arrayBuffer())
    return buf.length > 0 ? buf : null
  } catch {
    return null
  }
}

export function extractOlxPrice(params: OlxParam[] | undefined): {
  pricePln: number | null
  priceOnRequest: boolean
  offerType: 'fixed' | 'negotiable' | 'on_request'
} {
  if (!params) return { pricePln: null, priceOnRequest: false, offerType: 'fixed' }
  const priceParam = params.find((p) => p.key === 'price')
  const val = priceParam?.value as {
    value?: number
    type?: string
    arranged?: boolean
    negotiable?: boolean
  } | undefined
  if (!val) return { pricePln: null, priceOnRequest: false, offerType: 'fixed' }
  if (val.type === 'free') return { pricePln: 0, priceOnRequest: false, offerType: 'fixed' }

  const hasValue = typeof val.value === 'number' && val.value >= 0
  const isNegotiable = val.negotiable === true || val.type === 'arranged' || val.arranged === true

  // OLX: „do negocjacji” często ma type=arranged + konkretną kwotę w value
  if (isNegotiable && hasValue) {
    return { pricePln: val.value!, priceOnRequest: false, offerType: 'negotiable' }
  }
  if (isNegotiable && !hasValue) {
    return { pricePln: null, priceOnRequest: true, offerType: 'on_request' }
  }
  if (hasValue) {
    return { pricePln: val.value!, priceOnRequest: false, offerType: 'fixed' }
  }
  return { pricePln: null, priceOnRequest: false, offerType: 'fixed' }
}

export function extractOlxCondition(params: OlxParam[] | undefined): string | null {
  const state = params?.find((p) => p.key === 'state')
  const val = state?.value as { key?: string } | undefined
  if (val?.key === 'new') return 'new'
  if (val?.key === 'used') return 'used'
  return null
}

/** Opóźnienie między requestami (ms) — domyślnie 800. */
export function olxRequestDelayMs(): number {
  const n = Number(process.env.OLX_REQUEST_DELAY_MS ?? 800)
  return Number.isFinite(n) && n >= 0 ? n : 800
}

export async function olxThrottle(): Promise<void> {
  await sleep(olxRequestDelayMs())
}
