import type { Boat } from '@/lib/types'

export type BoatListingSortOption =
  | 'default'
  | 'newest'
  | 'price_asc'
  | 'price_desc'
  | 'year_desc'
  | 'length_desc'

export const BOAT_LISTING_SORT_OPTIONS: { value: BoatListingSortOption; label: string }[] = [
  { value: 'default', label: 'Promowane i najnowsze' },
  { value: 'newest', label: 'Najnowsze' },
  { value: 'price_asc', label: 'Cena: od najniższej' },
  { value: 'price_desc', label: 'Cena: od najwyższej' },
  { value: 'year_desc', label: 'Rok: od najnowszego' },
  { value: 'length_desc', label: 'Długość: od najdłuższej' },
]

function topRank(b: Boat): number {
  return b.isTopOfferDb ? 0 : 1
}

function publishedTs(b: Boat): number | null {
  if (!b.publishedAt) return null
  const t = Date.parse(b.publishedAt)
  return Number.isFinite(t) ? t : null
}

/** Cena do sortowania — pomija „na zapytanie” i brak ceny (typowe u importów OLX). */
function hasSortablePrice(b: Boat): boolean {
  return !b.priceOnRequest && b.price > 0
}

function hasSortableYear(b: Boat): boolean {
  return b.year > 0
}

function hasSortableLength(b: Boat): boolean {
  return b.length > 0
}

function cmpTop(a: Boat, b: Boat): number {
  return topRank(a) - topRank(b)
}

function cmpMissingLast(aMissing: boolean, bMissing: boolean): number | null {
  if (aMissing && bMissing) return 0
  if (aMissing) return 1
  if (bMissing) return -1
  return null
}

function cmpNum(a: number, b: number, dir: 1 | -1): number {
  if (a === b) return 0
  return a < b ? -dir : dir
}

function cmpSlug(a: Boat, b: Boat): number {
  return a.slug.localeCompare(b.slug, 'pl')
}

export function sortBoats(boats: readonly Boat[], sort: BoatListingSortOption): Boat[] {
  if (sort === 'default') return [...boats]

  const out = [...boats]
  out.sort((a, b) => {
    const top = cmpTop(a, b)
    if (top !== 0) return top

    let primary = 0

    switch (sort) {
      case 'newest': {
        const aMissing = publishedTs(a) == null
        const bMissing = publishedTs(b) == null
        const miss = cmpMissingLast(aMissing, bMissing)
        if (miss !== null) {
          primary = miss
          break
        }
        primary = cmpNum(publishedTs(b)!, publishedTs(a)!, 1)
        break
      }
      case 'price_asc': {
        const miss = cmpMissingLast(!hasSortablePrice(a), !hasSortablePrice(b))
        if (miss !== null) {
          primary = miss
          break
        }
        primary = cmpNum(a.price, b.price, 1)
        break
      }
      case 'price_desc': {
        const miss = cmpMissingLast(!hasSortablePrice(a), !hasSortablePrice(b))
        if (miss !== null) {
          primary = miss
          break
        }
        primary = cmpNum(b.price, a.price, 1)
        break
      }
      case 'year_desc': {
        const miss = cmpMissingLast(!hasSortableYear(a), !hasSortableYear(b))
        if (miss !== null) {
          primary = miss
          break
        }
        primary = cmpNum(b.year, a.year, 1)
        break
      }
      case 'length_desc': {
        const miss = cmpMissingLast(!hasSortableLength(a), !hasSortableLength(b))
        if (miss !== null) {
          primary = miss
          break
        }
        primary = cmpNum(b.length, a.length, 1)
        break
      }
      default:
        break
    }

    if (primary !== 0) return primary
    return cmpSlug(a, b)
  })

  return out
}
