<script setup>
import { AnimatePresence, motion } from 'motion-v'
import {
  Calendar,
  ChevronDown,
  Cog,
  CloudRain,
  Fuel,
  ListFilter,
  MapPin,
  Search,
  Settings2,
  ShieldCheck,
  Sparkles,
  Tag,
  Users,
  Wand2,
  Flame,
  X,
} from 'lucide-vue-next'
import { format } from 'date-fns'
import { useHomeContent } from '~/content/home'
import { loadResolvedVehicleDetail } from '~/content/vehicles'
import { resolvePublicApiError } from '~/content/utils'
import { resolvePublicUiValue } from '~/i18n/public-ui'
import AppCalendar from '~/components/shared/AppCalendar.vue'
import { buildRentTripQuery } from '~/utils/public-routes'
import SimpleCarListCard from '~/components/home/simple-car-list/SimpleCarListCard.vue'
import SimpleCarListCompareDock from '~/components/home/simple-car-list/SimpleCarListCompareDock.vue'
import SimpleCarListQuickViewModal from '~/components/home/simple-car-list/SimpleCarListQuickViewModal.vue'
import SimpleCarListGamificationModal from '~/components/home/simple-car-list/SimpleCarListGamificationModal.vue'

const homeContent = useHomeContent()
const { locale } = usePublicLocale()
const { currency } = usePublicPreferences()
const ui = usePublicUi()
const { buildCatalogPayload, fetchCatalog, parseSearchQuery } = useSearchCatalog()

const homeFleetSection = computed(() => homeContent.homeFleetSection.value || {})
const homeFleetVehicles = computed(() => homeContent.homeFleetVehicles.value || [])
const homeInsuranceOptions = computed(() => homeContent.homeInsuranceOptions.value || [])
const homeContentPending = computed(() => Boolean(homeContent.homeContentPending?.value))
const showMoreLabel = computed(() => resolvePublicUiValue(locale.value, 'loadMore', 'Load More'))
const selectDateLabel = computed(() => resolvePublicUiValue(locale.value, 'search.selectDateLabel', 'Select Date'))
const calendarDoneLabel = computed(() => resolvePublicUiValue(locale.value, 'search.calendarDoneLabel', 'Done'))
const sortByLabel = computed(() => ui.value.search?.sortByLabel || 'Sort By')
const featuredLabel = computed(() => ui.value.search?.featuredLabel || 'Featured')
const bestValueLabel = computed(() => ui.value.search?.bestValueLabel || 'Best Value')
const sortRecommendedLabel = computed(() => ui.value.search?.sortRecommendedLabel || 'Recommended')
const sortPriceLowLabel = computed(() => ui.value.search?.sortPriceLowLabel || 'Price: Low to High')
const sortPriceHighLabel = computed(() => ui.value.search?.sortPriceHighLabel || 'Price: High to Low')
const sortRatingLabel = computed(() => ui.value.search?.sortRatingLabel || 'Top Rated')
const noCarsLabel = computed(() => ui.value.search?.soldOutSelectedDatesLabel || 'No cars available for these dates.')
const route = useRoute()
const router = useRouter()
const runtimeConfig = useRuntimeConfig()
const activeCategory = ref('all')
const sortMode = ref('recommended')
const aiMode = ref(false)
const aiQuery = ref('')
const isExpanded = ref(false)
const activeDropdown = ref(null)
const isLoading = ref(false)
const filters = reactive({ transmission: [], deposit: [], engine: [], payment: [], options: [] })
const appliedFilters = reactive({ transmission: [], deposit: [], engine: [], payment: [], options: [] })
const compareList = ref([])
const compareSelectedCars = ref([])
const showCompareSummary = ref(false)
const aiCompareResult = ref(null)
const aiCompareLoading = ref(false)
const aiCompareError = ref('')
const showGamification = ref(false)
const gamificationCar = ref(null)
const isScrolled = ref(false)
const quickViewCar = ref(null)
const liveBookingMessage = ref(null)
const visibleCount = ref(40)
const searchBarRef = ref(null)
const { baseDay, buildDate } = usePublicDateDefaults()
const dateRange = ref({
  from: buildDate(3),
  to: buildDate(10),
})
const pickupTime = ref('12:30')
const dropoffTime = ref('08:30')
const { locations: publicSiteLocations } = usePublicSiteLocations()
const whereLocations = computed(() => publicSiteLocations.value || [])
const pickupLocation = ref(null)
const dropoffLocation = ref(null)
const returnToSameLocation = ref(true)
const weatherForecast = ref(null)
const weatherLoading = ref(false)
const weatherError = ref('')
const liveAvailabilityByGroupId = ref({})
const liveCatalogExtras = ref([])
const uiStateSyncingFromRoute = ref(false)
const hasUserChangedSearchState = ref(false)
const hasExplicitTripQuery = computed(() => ['pickupLocationId', 'dropoffLocationId', 'returnToSameLocation', 'pickupAt', 'dropoffAt']
  .some((key) => Object.prototype.hasOwnProperty.call(route.query, key)))
const canShowWeatherForecast = computed(() => hasExplicitTripQuery.value || hasUserChangedSearchState.value)
const hasInitializedDateState = ref(false)
const canSyncSearchStateToUrl = ref(false)
const isCommittingDateSelection = ref(false)
const isApplyingCatalogFilters = ref(false)
const aiSearchResults = ref([])
const aiSearchExplanation = ref('')
const aiSearchLoading = ref(false)
const aiSearchError = ref('')
const aiSearchActive = ref(false)
const aiSearchAutoRunPending = ref(false)
let weatherTimer = null
let weatherRequestId = 0
let ghostTimer = null
let loadingTimer = null
let syncedFilterQuerySignature = ''
let hasSyncedInitialFiltersFromRoute = false

const aiPromptKey = ref('')
const AI_DEVICE_FINGERPRINT_KEY = 'bent.public.ai.device-fingerprint'

const aiQuickPromptKeys = [
  'tripToKazbegi',
  'airportPickupTbilisi',
  'familySuvFor5',
  'budgetCityCar',
]

const aiQuickPromptItems = computed(() => [
  {
    key: 'tripToKazbegi',
    icon: '🏔️',
    label: resolvePublicUiValue(locale.value, 'search.aiPrompts.tripToKazbegi', 'Trip to Kazbegi'),
  },
  {
    key: 'airportPickupTbilisi',
    icon: '✈️',
    label: resolvePublicUiValue(locale.value, 'search.aiPrompts.airportPickupTbilisi', 'Airport pickup in Tbilisi'),
  },
  {
    key: 'familySuvFor5',
    icon: '👨‍👩‍👧‍👦',
    label: resolvePublicUiValue(locale.value, 'search.aiPrompts.familySuvFor5', 'Family SUV for 5'),
  },
  {
    key: 'budgetCityCar',
    icon: '🏙️',
    label: resolvePublicUiValue(locale.value, 'search.aiPrompts.budgetCityCar', 'Budget car for city'),
  },
])

const CARS = [
  {
    id: 100,
    name: 'Kazbegi Winter Package',
    category: 'Experience',
    price: 150,
    tags: ['BUNDLE'],
    fomo: 'Perfect for couples',
    specs: { seats: 5, transmission: 'Automatic', fuel: 'Diesel' },
    trunk: '🧳 2 large suitcases + 🏂 2 snowaboards',
    image: 'https://api.hub.bent.ge/media/legacy-vehicles/mitsubishi-outlander-sport-2020-red.webp',
    images: [
      'https://api.hub.bent.ge/media/legacy-vehicles/mitsubishi-outlander-sport-2020-red.webp',
      'https://api.hub.bent.ge/media/legacy-vehicles/hyundai-creta-2020-silver.webp',
    ],
    interiorImages: ['https://api.hub.bent.ge/media/legacy-vehicles/picture-68712f55aef6d.webp'],
    bundleFeatures: ['4x4 SUV', 'Snow Chains', 'Full Premium Insurance', 'Local Guide'],
  },
  {
    id: 1,
    name: 'Ford Fusion',
    category: 'Sedan',
    price: 40,
    tags: ['POPULAR'],
    fomo: '2 people looking',
    specs: { seats: 5, transmission: 'Automatic', fuel: 'Petrol' },
    trunk: '🧳 2 suitcases + 🎒 2 backpacks',
    image: 'https://api.hub.bent.ge/media/legacy-vehicles/nissan-sentra-2020-white.webp',
    images: [
      'https://api.hub.bent.ge/media/legacy-vehicles/nissan-sentra-2020-white.webp',
      'https://api.hub.bent.ge/media/legacy-vehicles/chevrolet-sonic-2020-white.webp',
      'https://api.hub.bent.ge/media/legacy-vehicles/kia-cerato-2020-white.webp',
    ],
    interiorImages: ['https://api.hub.bent.ge/media/legacy-vehicles/picture-68712f55aef6d.webp', 'https://api.hub.bent.ge/media/legacy-vehicles/picture-675851479ed03.webp'],
  },
  {
    id: 9,
    name: 'Toyota Prius',
    category: 'Economy',
    price: 25,
    tags: ['ECO'],
    fomo: 'In high demand',
    specs: { seats: 5, transmission: 'Automatic', fuel: 'Hybrid' },
    trunk: '🧳 2 suitcases + 🛍 2 bags',
    image: 'https://api.hub.bent.ge/media/legacy-vehicles/toyota-vitz-2020-silver.webp',
    images: [
      'https://api.hub.bent.ge/media/legacy-vehicles/toyota-vitz-2020-silver.webp',
      'https://api.hub.bent.ge/media/legacy-vehicles/hyundai-solaris-2020-silver.webp',
    ],
    interiorImages: ['https://api.hub.bent.ge/media/legacy-vehicles/667f2d8345862.webp'],
  },
  {
    id: 4,
    name: 'Hyundai Santa Fe',
    category: 'SUV',
    price: 55,
    tags: ['POPULAR'],
    specs: { seats: 5, transmission: 'Automatic', fuel: 'Diesel' },
    trunk: '🧳 2 large suitcases + 🏂 1 snowboard',
    image: 'https://api.hub.bent.ge/media/legacy-vehicles/mitsubishi-outlander-sport-2020-red.webp',
    images: ['https://api.hub.bent.ge/media/legacy-vehicles/mitsubishi-outlander-sport-2020-red.webp', 'https://api.hub.bent.ge/media/legacy-vehicles/hyundai-creta-2020-silver.webp'],
    interiorImages: ['https://api.hub.bent.ge/media/legacy-vehicles/picture-68712f55aef6d.webp'],
  },
  {
    id: 2,
    name: 'Kia K5',
    category: 'Sedan',
    price: 45,
    tags: ['PREMIUM'],
    fomo: 'Just booked',
    specs: { seats: 5, transmission: 'Automatic', fuel: 'Petrol' },
    trunk: '🧳 3 med suitcases + 🎒 backpack',
    image: 'https://api.hub.bent.ge/media/legacy-vehicles/kia-cerato-2020-white.webp',
    images: ['https://api.hub.bent.ge/media/legacy-vehicles/kia-cerato-2020-white.webp', 'https://api.hub.bent.ge/media/legacy-vehicles/skoda-rapid-2020-gray.webp'],
    interiorImages: ['https://api.hub.bent.ge/media/legacy-vehicles/picture-675851479ed03.webp'],
  },
  {
    id: 6,
    name: 'Hyundai Tucson',
    category: 'SUV',
    price: 45,
    tags: [],
    specs: { seats: 5, transmission: 'Automatic', fuel: 'Petrol' },
    trunk: '🧳 4 suitcases + 🛒 groceries',
    image: 'https://api.hub.bent.ge/media/legacy-vehicles/hyundai-creta-2020-silver.webp',
    images: ['https://api.hub.bent.ge/media/legacy-vehicles/hyundai-creta-2020-silver.webp', 'https://api.hub.bent.ge/media/legacy-vehicles/mitsubishi-outlander-sport-2020-red.webp'],
    interiorImages: ['https://api.hub.bent.ge/media/legacy-vehicles/667f2d8345862.webp'],
  },
  {
    id: 7,
    name: 'Jeep Compass',
    category: 'SUV',
    price: 44,
    tags: ['AWD'],
    specs: { seats: 5, transmission: 'Automatic', fuel: 'Petrol' },
    trunk: '🧳 2 large suitcases + 🏕 tent',
    image: 'https://api.hub.bent.ge/media/legacy-vehicles/suzuki-baleno-2020-blue.webp',
    images: ['https://api.hub.bent.ge/media/legacy-vehicles/suzuki-baleno-2020-blue.webp', 'https://api.hub.bent.ge/media/legacy-vehicles/chevrolet-sonic-2020-white.webp'],
    interiorImages: ['https://api.hub.bent.ge/media/legacy-vehicles/picture-68712f55aef6d.webp'],
  },
  {
    id: 8,
    name: 'Range Rover Velar',
    category: 'Premium',
    price: 140,
    tags: ['VIP'],
    fomo: '1 left',
    specs: { seats: 5, transmission: 'Automatic', fuel: 'Petrol' },
    trunk: '🧳 4 luxury cases + ⛷ skis',
    image: 'https://api.hub.bent.ge/media/legacy-vehicles/skoda-rapid-2020-gray.webp',
    images: ['https://api.hub.bent.ge/media/legacy-vehicles/skoda-rapid-2020-gray.webp', 'https://api.hub.bent.ge/media/legacy-vehicles/kia-cerato-2020-white.webp'],
    interiorImages: ['https://api.hub.bent.ge/media/legacy-vehicles/picture-675851479ed03.webp'],
  },
  {
    id: 11,
    name: 'Toyota Camry',
    category: 'Sedan',
    price: 50,
    tags: ['POPULAR'],
    specs: { seats: 5, transmission: 'Automatic', fuel: 'Petrol' },
    trunk: '🧳 3 large suitcases',
    image: 'https://api.hub.bent.ge/media/legacy-vehicles/hyundai-solaris-2020-silver.webp',
    images: ['https://api.hub.bent.ge/media/legacy-vehicles/hyundai-solaris-2020-silver.webp', 'https://api.hub.bent.ge/media/legacy-vehicles/toyota-vitz-2020-silver.webp'],
    interiorImages: ['https://api.hub.bent.ge/media/legacy-vehicles/667f2d8345862.webp'],
  },
]

function resolveCatalogVehicleKey(car) {
  return String(car?.id || '').trim()
}

function resolveCompareSelectionKey(car) {
  const contentKey = String(car?.contentKey || car?.content_key || car?.entityId || car?.entity_id || '').trim()

  if (contentKey) {
    return contentKey
  }

  const vehicleGroupId = Number(car?.vehicleGroupId || 0)
  return vehicleGroupId > 0 ? String(vehicleGroupId) : ''
}

function normalizeTextKey(value) {
  return String(value || '').trim().toLowerCase()
}

function normalizeTransmissionKey(value) {
  const normalized = normalizeTextKey(value)

  if (!normalized) {
    return null
  }

  if (normalized.includes('manual')) {
    return 'manual'
  }

  if (normalized.includes('auto')) {
    return 'auto'
  }

  return normalized
}

function normalizeFuelKey(value) {
  const normalized = normalizeTextKey(value)

  if (!normalized) {
    return null
  }

  if (normalized.includes('petrol') || normalized.includes('gasoline') || normalized.includes('gas')) {
    return 'petrol'
  }

  if (normalized.includes('diesel')) {
    return 'diesel'
  }

  if (normalized.includes('hybrid') || normalized.includes('ev') || normalized.includes('electric')) {
    return 'ev'
  }

  return normalized
}

function normalizeDriveKey(value) {
  const normalized = normalizeTextKey(value)

  if (!normalized) {
    return null
  }

  if (normalized.includes('awd') || normalized.includes('4x4') || normalized.includes('all wheel')) {
    return 'awd'
  }

  if (normalized.includes('fwd') || normalized.includes('front')) {
    return 'fwd'
  }

  if (normalized.includes('rwd') || normalized.includes('rear')) {
    return 'rwd'
  }

  return normalized
}

function hasAwdCapability(car) {
  const driveKey = normalizeDriveKey(car?.specs?.driveType)
  const tags = Array.isArray(car?.tags) ? car.tags.map((value) => normalizeTextKey(value)) : []

  return driveKey === 'awd' || tags.includes('awd') || tags.includes('4x4') || tags.includes('all wheel drive')
}

function normalizeCatalogVehicle(car) {
  if (!car) {
    return null
  }

  const filterMeta = car?.filterMeta || {}
  const filterFlags = filterMeta?.filterFlags || car?.filterFlags || {}
  const specs = filterMeta?.specs || car?.specs || {}
  const paymentMethods = uniqueValues([
    ...(Array.isArray(car?.paymentMethods) ? car.paymentMethods : []),
    ...(Array.isArray(filterMeta?.paymentMethods) ? filterMeta.paymentMethods : []),
    ...(Array.isArray(filterMeta?.paymentMethodKeys) ? filterMeta.paymentMethodKeys : []),
  ].map((value) => normalizeTextKey(value)))
  const featureKeys = uniqueValues([
    ...(Array.isArray(car?.featureKeys) ? car.featureKeys : []),
    ...(Array.isArray(filterMeta?.featureKeys) ? filterMeta.featureKeys : []),
  ].map((value) => normalizeTextKey(value)))
  const includedInPrice = Array.isArray(car?.includedInPrice) ? car.includedInPrice : []
  const price = Number(car?.price ?? car?.displayPriceFrom ?? car?.priceFrom ?? car?.baseDailyRate ?? 0)
  const depositStatus = normalizeTextKey(filterMeta?.deposit?.status || filterMeta?.deposit?.mode || (Number(filterMeta?.deposit?.amount || car?.deposit || 0) > 0 ? 'deposit' : 'no_deposit'))
  const paidNoDeposit = Boolean(filterFlags?.paidNoDeposit || filterMeta?.deposit?.paidNoDepositAvailable)

  return {
    ...car,
    id: resolveCatalogVehicleKey(car),
    key: resolveCatalogVehicleKey(car),
    vehicleGroupId: Number(car?.vehicleGroupId || 0) || null,
    price,
    displayPrice: price,
    rating: Number(car?.rating || car?.reviewAggregate?.rating || 0) || null,
    paymentMethods,
    featureKeys,
    includedInPrice,
    filterMeta: {
      ...filterMeta,
      paymentMethods,
      paymentMethodKeys: paymentMethods,
      featureKeys,
      deposit: {
        ...(filterMeta?.deposit || {}),
        status: depositStatus || 'no_deposit',
      },
      specs: {
        ...(filterMeta?.specs || {}),
        seats: Number(specs?.seats || car?.seats || car?.specs?.seats || 0) || null,
        transmission: specs?.transmission || car?.transmission || car?.specs?.transmission || null,
        fuelType: specs?.fuelType || specs?.fuel || car?.fuelType || car?.specs?.fuel || null,
        driveType: specs?.driveType || car?.driveType || car?.specs?.driveType || null,
      },
    },
    filterFlags: {
      popular: Boolean(filterFlags?.popular || (Array.isArray(car?.tags) && car.tags.some((tag) => normalizeTextKey(tag) === 'popular'))),
      topModel: Boolean(filterFlags?.topModel),
      realPhotos: Boolean(filterFlags?.realPhotos || Number(filterMeta?.photosCount || car?.photosCount || 0) > 0),
      guaranteedModel: Boolean(filterFlags?.guaranteedModel),
      cityDelivery: Boolean(filterFlags?.cityDelivery),
      unlimitedMileage: Boolean(filterFlags?.unlimitedMileage),
      paidNoDeposit,
    },
    specs: {
      seats: Number(specs?.seats || car?.seats || car?.specs?.seats || 0) || null,
      transmission: normalizeTransmissionKey(specs?.transmission || car?.transmission || car?.specs?.transmission) || null,
      fuel: normalizeFuelKey(specs?.fuelType || specs?.fuel || car?.fuelType || car?.specs?.fuel) || null,
      power: specs?.power || car?.power || car?.specs?.power || null,
      engine: specs?.engine || car?.engine || car?.specs?.engine || null,
      luggage: specs?.luggage || car?.luggage || car?.specs?.luggage || null,
      driveType: normalizeDriveKey(specs?.driveType || car?.driveType || car?.specs?.driveType) || null,
    },
  }
}

function normalizeAiSearchVehicle(result) {
  if (!result) {
    return null
  }

  const vehicleGroupId = Number(result?.vehicleGroupId || 0)

  if (!vehicleGroupId) {
    return null
  }

  return {
    id: vehicleGroupId,
    key: String(vehicleGroupId),
    vehicleGroupId,
    name: String(result?.name || ''),
    category: String(result?.category || ''),
    price: Number(result?.pricePerDay || 0),
    image: String(result?.image || ''),
    paymentMethods: Array.isArray(result?.paymentMethods) ? result.paymentMethods : [],
    featureKeys: Array.isArray(result?.featureKeys) ? result.featureKeys : [],
    photosCount: Number(result?.photosCount || 0) || null,
    deposit: result?.deposit ?? null,
    specs: {
      seats: Number(result?.seats || 0) || null,
      transmission: String(result?.transmission || ''),
      fuel: String(result?.fuel || ''),
      driveType: String(result?.driveType || ''),
    },
  }
}

const normalizedAiSearchExplanation = computed(() => String(aiSearchExplanation.value || '').trim())

async function hydrateQuickViewCar(car) {
  if (!car) {
    return null
  }

  if (Number(car?.vehicleGroupId || 0) > 0) {
    return car
  }

  const contentKey = String(car?.contentKey || car?.content_key || car?.entityId || car?.entity_id || car?.id || '').trim()

  if (!contentKey) {
    return car
  }

  const resolvedCar = await loadResolvedVehicleDetail(contentKey, locale.value)

  if (!resolvedCar) {
    return car
  }

  return {
    ...car,
    ...resolvedCar,
    vehicleGroupId: Number(resolvedCar.vehicleGroupId || car?.vehicleGroupId || 0) || null,
    id: resolvedCar.id || car.id,
    key: resolvedCar.contentKey || resolvedCar.entityId || car.key || car.id,
  }
}

function uniqueValues(values = []) {
  return [...new Set((values || []).map((value) => String(value || '').trim()).filter(Boolean))]
}

function normalizeUiQueryValue(value) {
  if (Array.isArray(value)) {
    return normalizeUiQueryValue(value[0] || '')
  }

  return String(value || '').trim()
}

function parseCsvQuery(value) {
  return uniqueValues(
    normalizeUiQueryValue(value)
      .split(',')
      .map((item) => item.trim())
      .filter(Boolean),
  )
}

function resolveAllowedAiPromptKey(value) {
  const normalized = normalizeUiQueryValue(value)
  return aiQuickPromptKeys.includes(normalized) ? normalized : ''
}

function resolveAiPromptLabel(key) {
  return aiQuickPromptItems.value.find((item) => item.key === key)?.label || ''
}

function hashString(value = '') {
  let hash = 0
  const input = String(value || '')

  for (let index = 0; index < input.length; index += 1) {
    hash = Math.imul(31, hash) + input.charCodeAt(index)
    hash |= 0
  }

  return hash >>> 0
}

function resolveSortModeFromQuery(value) {
  const normalized = normalizeUiQueryValue(value)

  if (['recommended', 'price-low', 'price-high', 'rating'].includes(normalized)) {
    return normalized
  }

  return 'recommended'
}

function resolveAiDeviceFingerprint() {
  if (!import.meta.client) {
    return ''
  }

  const storage = window.sessionStorage
  const existing = storage.getItem(AI_DEVICE_FINGERPRINT_KEY)

  if (existing) {
    return existing
  }

  const generated = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
    ? crypto.randomUUID()
    : `${Date.now()}-${Math.random().toString(36).slice(2, 12)}`

  storage.setItem(AI_DEVICE_FINGERPRINT_KEY, generated)
  return generated
}

function buildCsvQueryValue(values = []) {
  return uniqueValues(values).join(',')
}

function copyCatalogFilters(source, target) {
  target.transmission = [...(source?.transmission || [])]
  target.deposit = [...(source?.deposit || [])]
  target.engine = [...(source?.engine || [])]
  target.payment = [...(source?.payment || [])]
  target.options = [...(source?.options || [])]
}

function buildFilterQuerySignature(query = route.query) {
  return JSON.stringify({
    scTrans: normalizeUiQueryValue(query.scTrans),
    scDep: normalizeUiQueryValue(query.scDep),
    scEng: normalizeUiQueryValue(query.scEng),
    scPay: normalizeUiQueryValue(query.scPay),
    scOpt: normalizeUiQueryValue(query.scOpt),
  })
}

function buildSmartCarQuery(car = quickViewCar.value) {
  const nextQuery = { ...route.query }

  if (car) {
    nextQuery.scCar = resolveCatalogVehicleKey(car)
  } else {
    delete nextQuery.scCar
  }

  nextQuery.scCat = activeCategory.value || 'all'

  if (sortMode.value !== 'recommended') {
    nextQuery.scSort = sortMode.value
  } else {
    delete nextQuery.scSort
  }

  const filterQuery = {
    scTrans: buildCsvQueryValue(appliedFilters.transmission),
    scDep: buildCsvQueryValue(appliedFilters.deposit),
    scEng: buildCsvQueryValue(appliedFilters.engine),
    scPay: buildCsvQueryValue(appliedFilters.payment),
    scOpt: buildCsvQueryValue(appliedFilters.options),
  }

  Object.entries(filterQuery).forEach(([key, value]) => {
    if (value) {
      nextQuery[key] = value
    } else {
      delete nextQuery[key]
    }
  })

  if (dateRange.value?.from instanceof Date && dateRange.value?.to instanceof Date) {
    const nextPickup = selectedPickupLocation.value || defaultTbilisiLocation.value || whereDropdownLocations.value[0] || null
    const nextDropoff = returnToSameLocation.value ? nextPickup : (selectedDropoffLocation.value || nextPickup)

    Object.assign(nextQuery, buildRentTripQuery({
      pickupLocationId: nextPickup?.backendId || undefined,
      dropoffLocationId: nextDropoff?.backendId || nextPickup?.backendId || undefined,
      pickupAt: buildIsoDateTime(dateRange.value.from, pickupTime.value),
      dropoffAt: buildIsoDateTime(dateRange.value.to, dropoffTime.value),
      returnToSameLocation: Number(nextPickup?.backendId || 0) === Number(nextDropoff?.backendId || 0) ? '1' : '0',
    }))
  }

  return nextQuery
}

async function replaceQueryWithoutScroll(nextQuery) {
  if (!import.meta.client) {
    await router.replace({
      path: route.path,
      query: nextQuery,
    })
    return
  }

  const scrollX = window.scrollX
  const scrollY = window.scrollY

  await router.replace({
    path: route.path,
    query: nextQuery,
  })

  await new Promise((resolve) => window.requestAnimationFrame(resolve))
  window.scrollTo(scrollX, scrollY)
}

function isTruthyQueryValue(value) {
  return ['1', 'true', 'yes', 'on'].includes(normalizeUiQueryValue(value).toLowerCase())
}

function resolveActiveCategoryFromQuery(value) {
  const normalized = normalizeUiQueryValue(value)

  if (['all', 'ai', 'surprise', 'suv', 'luxury', 'family', 'budget'].includes(normalized)) {
    return normalized
  }

  return 'all'
}

function handleMouseLeave(event) {
  if (event.clientY > 0 || showGamification.value) {
    return
  }

  const nextGamificationCar = gamificationCar.value || visibleCars.value[0] || catalogCars.value[0] || null

  if (!nextGamificationCar) {
    return
  }

  gamificationCar.value = nextGamificationCar
  showGamification.value = true
  void replaceQueryWithoutScroll(buildSmartCarQuery(nextGamificationCar))
}

function handleScroll() {
  isScrolled.value = window.scrollY > 300
}

function triggerGhostMessage() {
  const ghostMessages = [
    'Someone just booked Toyota Prius for May 12-14!',
    '3 people are viewing Range Rover right now',
    'Ford Fusion was booked by a user from Dubai',
    'Only 1 Kia K5 left for your dates!',
  ]

  const msg = ghostMessages[Math.floor(Math.random() * ghostMessages.length)]
  liveBookingMessage.value = msg
  window.setTimeout(() => {
    liveBookingMessage.value = null
  }, 5000)
  ghostTimer = window.setTimeout(triggerGhostMessage, Math.random() * 15000 + 15000)
}

function normalizeWeatherText(value) {
  return String(value || '').replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim()
}

function resolveWeatherSummaryText(value) {
  if (!value) {
    return ''
  }

  if (typeof value === 'string') {
    return normalizeWeatherText(value)
  }

  if (Array.isArray(value)) {
    return value
      .map((entry) => resolveWeatherSummaryText(entry))
      .filter(Boolean)
      .join(' · ')
  }

  if (typeof value === 'object') {
    const direct = [
      value.summary,
      value.title,
      value.message,
      value.text,
      value.label,
      value.description,
      value.note,
      value.type,
    ]
      .map((entry) => resolveWeatherSummaryText(entry))
      .find(Boolean)

    if (direct) {
      return direct
    }

    return Object.values(value)
      .map((entry) => resolveWeatherSummaryText(entry))
      .filter(Boolean)
      .join(' · ')
  }

  return ''
}

function formatWeatherWarningLabel(warning) {
  if (!warning) {
    return ''
  }

  if (typeof warning === 'string') {
    return normalizeWeatherText(warning)
  }

  if (typeof warning === 'object') {
    return normalizeWeatherText(warning.label || warning.title || warning.message || warning.text || warning.type)
  }

  return ''
}

function collectWeatherWarnings(payload) {
  const sources = [
    payload?.warnings,
    payload?.warning,
    payload?.forecast?.warnings,
    payload?.forecast?.warning,
  ]

  return sources
    .flatMap((source) => {
      if (!source) {
        return []
      }

      if (Array.isArray(source)) {
        return source
      }

      if (typeof source === 'object') {
        return Object.values(source)
      }

      return [source]
    })
    .map((item) => formatWeatherWarningLabel(item))
    .filter(Boolean)
}

function getWeatherLocationLabel(location) {
  return normalizeWeatherText(location?.city || location?.cityName || location?.name || location?.code || '')
}

function getWeatherForecastLabel(payload) {
  return resolveWeatherSummaryText(payload?.forecast?.summary || payload?.summary || payload?.forecast || payload)
}

const weatherInsightTitle = computed(() => {
  if (weatherLoading.value) {
    return 'Checking your trip conditions...'
  }

  if (weatherForecast.value?.awdRecommended) {
    return 'Good to know before you choose'
  }

  return 'Trip check ready'
})

const weatherInsightText = computed(() => {
  if (weatherLoading.value) {
    return 'While you compare cars, we are checking the forecast for your selected dates.'
  }

  const summary = weatherError.value || getWeatherForecastLabel(weatherForecast.value)

  if (!summary) {
    return 'We checked the selected dates so you can pick the right car without guessing.'
  }

  return `While you compare cars, we checked the forecast: ${summary}`
})

const hasWeatherForecast = computed(() => Boolean(
  weatherForecast.value
  && !weatherForecast.value?.coverage?.isUnavailable
  && (
    getWeatherForecastLabel(weatherForecast.value)
    || weatherForecast.value?.coverage?.isPartial
    || weatherForecast.value?.awdRecommended
    || collectWeatherWarnings(weatherForecast.value).length
  ),
))

const weatherBadges = computed(() => {
  const badges = []

  if (weatherForecast.value?.coverage?.isPartial) {
    badges.push({ key: 'partial', label: 'Partial coverage', className: 'bg-amber-50 text-amber-700' })
  }

  if (weatherForecast.value?.coverage?.isUnavailable) {
    badges.push({ key: 'unavailable', label: 'No coverage', className: 'bg-slate-100 text-slate-500' })
  }

  if (weatherForecast.value?.awdRecommended) {
    badges.push({ key: 'awd', label: 'AWD recommended', className: 'bg-cyan-50 text-cyan-700' })
  }

  collectWeatherWarnings(weatherForecast.value).slice(0, 2).forEach((warning) => {
    badges.push({ key: warning, label: warning, className: 'bg-slate-100 text-slate-600' })
  })

  return badges
})

async function fetchWeatherForecast() {
  if (!import.meta.client) {
    return
  }

  const location = selectedPickupLocation.value
  const from = dateRange.value?.from
  const to = dateRange.value?.to

  if (!canShowWeatherForecast.value || !location || !(from instanceof Date) || !(to instanceof Date)) {
    weatherForecast.value = null
    weatherError.value = ''
    weatherLoading.value = false
    return
  }

  const params = {
    location_id: location.backendId || undefined,
    location_code: location.code || location.rawCode || undefined,
    location_name: location.name || undefined,
    city: location.city || location.cityName || undefined,
    latitude: location.latitude || location.lat || undefined,
    longitude: location.longitude || location.lng || undefined,
    start_date: format(from, 'yyyy-MM-dd'),
    end_date: format(to, 'yyyy-MM-dd'),
  }

  const requestId = ++weatherRequestId

  weatherLoading.value = true
  weatherError.value = ''

  try {
    const response = await $fetch(`${runtimeConfig.public.apiBaseUrl}/weather/forecast`, {
      method: 'GET',
      params,
    })

    if (requestId !== weatherRequestId) {
      return
    }

    const nextWeatherForecast = response?.data || response || null
    if (!getWeatherForecastLabel(nextWeatherForecast) && !nextWeatherForecast?.coverage?.isPartial && !nextWeatherForecast?.awdRecommended && !collectWeatherWarnings(nextWeatherForecast).length) {
      weatherForecast.value = null
      return
    }

    weatherForecast.value = nextWeatherForecast
  } catch (error) {
    if (requestId !== weatherRequestId) {
      return
    }

    weatherForecast.value = null
      weatherError.value = ''
  } finally {
    if (requestId === weatherRequestId) {
      weatherLoading.value = false
    }
  }
}

function scheduleWeatherForecastFetch() {
  if (!import.meta.client) {
    return
  }

  if (!canShowWeatherForecast.value) {
    weatherForecast.value = null
    weatherError.value = ''
    weatherLoading.value = false
    return
  }

  if (weatherTimer) {
    clearTimeout(weatherTimer)
  }

  weatherTimer = window.setTimeout(() => {
    void fetchWeatherForecast()
  }, 450)
}

async function fetchLiveAvailability() {
  if (!import.meta.client || !canShowWeatherForecast.value) {
    liveAvailabilityByGroupId.value = {}
    return
  }

  const pickup = selectedPickupLocation.value
  const dropoff = selectedDropoffLocation.value
  const from = dateRange.value?.from
  const to = dateRange.value?.to

  if (!pickup?.backendId || !dropoff?.backendId || !(from instanceof Date) || !(to instanceof Date)) {
    liveAvailabilityByGroupId.value = {}
    return
  }

  try {
    const payload = buildCatalogPayload({
      pickupLocationId: pickup.backendId,
      dropoffLocationId: dropoff.backendId,
      pickupDate: from,
      dropoffDate: to,
      pickupTime: pickupTime.value,
      dropoffTime: dropoffTime.value,
      currency: currency.value,
    })
    const catalog = await fetchCatalog(payload)
    const nextAvailability = {}
    liveCatalogExtras.value = Array.isArray(catalog.extras) ? catalog.extras : []

    ;(catalog.items || []).forEach((item) => {
      const groupId = Number(item?.vehicleGroupId || item?.id || 0)
      if (groupId && item?.availability) {
        nextAvailability[groupId] = item.availability
      }
    })

    liveAvailabilityByGroupId.value = nextAvailability
  } catch {
    liveAvailabilityByGroupId.value = {}
    liveCatalogExtras.value = []
  }
}

const categories = computed(() => [
  { id: 'all', label: homeFleetSection.value.allCategoryLabel || 'All Cars', icon: Cog },
  { id: 'ai', label: 'Ask AI', icon: Sparkles, tone: 'orange' },
  { id: 'surprise', label: 'Magic Pick', icon: Wand2, tone: 'purple' },
  { id: 'suv', label: 'SUV & 4x4', icon: ShieldCheck },
  { id: 'luxury', label: 'Premium', icon: Settings2 },
  { id: 'family', label: 'Family', icon: Users },
  { id: 'budget', label: 'Budget', icon: Fuel },
])

function sortCatalogVehicles(vehicles = []) {
  const nextVehicles = [...vehicles]

  if (activeCategory.value === 'surprise' && sortMode.value === 'recommended') {
    const seed = buildSearchSignature()

    return nextVehicles.sort((left, right) => (
      hashString(`${seed}::${resolveCatalogVehicleKey(left)}`) - hashString(`${seed}::${resolveCatalogVehicleKey(right)}`)
    ))
  }

  switch (sortMode.value) {
    case 'price-low':
      return nextVehicles.sort((left, right) => {
        const leftPrice = Number(left?.price || 0)
        const rightPrice = Number(right?.price || 0)

        if (leftPrice !== rightPrice) {
          return leftPrice - rightPrice
        }

        return String(left?.name || '').localeCompare(String(right?.name || ''))
      })
    case 'price-high':
      return nextVehicles.sort((left, right) => {
        const leftPrice = Number(left?.price || 0)
        const rightPrice = Number(right?.price || 0)

        if (leftPrice !== rightPrice) {
          return rightPrice - leftPrice
        }

        return String(left?.name || '').localeCompare(String(right?.name || ''))
      })
    case 'rating':
      return nextVehicles.sort((left, right) => {
        const leftRating = Number(left?.rating || 0)
        const rightRating = Number(right?.rating || 0)

        if (leftRating !== rightRating) {
          return rightRating - leftRating
        }

        const leftPrice = Number(left?.price || 0)
        const rightPrice = Number(right?.price || 0)

        if (leftPrice !== rightPrice) {
          return leftPrice - rightPrice
        }

        return String(left?.name || '').localeCompare(String(right?.name || ''))
      })
    default:
      return nextVehicles
  }
}

const filteredCars = computed(() => {
  const aiVehicles = activeCategory.value === 'ai' && aiSearchActive.value
    ? aiSearchCards.value
    : null
  const vehicles = aiVehicles !== null
    ? aiVehicles
    : catalogCars.value

  if (activeCategory.value === 'all' || activeCategory.value === 'ai' || activeCategory.value === 'surprise') {
    return sortCatalogVehicles(vehicles.filter((car) => matchesAllCatalogFilters(car)))
  }

  return sortCatalogVehicles(vehicles.filter((car) => {
    if (!matchesAllCatalogFilters(car)) {
      return false
    }

    const category = String(car.category || '').toLowerCase()
    const homeTypes = Array.isArray(car.homeTypes) ? car.homeTypes.map((value) => String(value || '').toLowerCase()) : []
    const price = Number(car.price || 0)

    switch (activeCategory.value) {
      case 'suv':
        return category.includes('suv') || category.includes('4x4') || homeTypes.some((value) => value.includes('suv') || value.includes('4x4'))
      case 'luxury':
        return category.includes('premium') || homeTypes.some((value) => value.includes('premium') || value.includes('luxury'))
      case 'family':
        return price <= 80 || homeTypes.some((value) => value.includes('family')) || Number(car.specs?.seats || 0) >= 5
      case 'budget':
        return price <= 50 || category.includes('budget') || homeTypes.some((value) => value.includes('budget'))
      default:
        return true
    }
  }))
})

const catalogCars = computed(() => {
    const sourceCars = Array.isArray(homeFleetVehicles.value) ? homeFleetVehicles.value : []

  return sourceCars
    .map((car, index) => {
      const normalized = normalizeCatalogVehicle(car, index)
      const groupId = Number(normalized?.vehicleGroupId || normalized?.id || 0)
      const availability = liveAvailabilityByGroupId.value[groupId] || null

      return normalized && availability ? { ...normalized, availability } : normalized
    })
    .filter(Boolean)
})

const quickViewCarWithLiveAvailability = computed(() => {
  if (!quickViewCar.value) {
    return null
  }

  const groupId = Number(quickViewCar.value.vehicleGroupId || quickViewCar.value.id || 0)
  const availability = liveAvailabilityByGroupId.value[groupId] || null

  return availability ? { ...quickViewCar.value, availability } : quickViewCar.value
})

function countCatalogCars(predicate) {
  return catalogCars.value.reduce((count, car) => count + (predicate(car) ? 1 : 0), 0)
}

function matchesAllCatalogFilters(car) {
  return matchesCatalogFilters(car, appliedFilters)
}

function matchesCatalogFilters(car, sourceFilters = appliedFilters) {
  const selectedTransmission = sourceFilters.transmission
  const selectedDeposit = sourceFilters.deposit
  const selectedEngine = sourceFilters.engine
  const selectedPayment = sourceFilters.payment
  const selectedOptions = sourceFilters.options
  const transmissionKey = normalizeTransmissionKey(car?.specs?.transmission)
  const fuelKey = normalizeFuelKey(car?.specs?.fuel)
  const driveKey = normalizeDriveKey(car?.specs?.driveType)
  const paymentMethods = Array.isArray(car?.paymentMethods) ? car.paymentMethods : []
  const featureKeys = Array.isArray(car?.featureKeys) ? car.featureKeys : []
  const depositStatus = String(car?.filterMeta?.deposit?.status || '').toLowerCase()
  const depositAmount = Number(car?.filterMeta?.deposit?.amount || 0)
  const hasNoDeposit = depositStatus === 'no_deposit' || !depositAmount
  const hasPaidNoDeposit = depositStatus === 'no_deposit_paid' || Boolean(car?.filterFlags?.paidNoDeposit || car?.filterMeta?.deposit?.paidNoDepositAvailable)

  const selectedFuelKeys = selectedEngine.filter((key) => ['petrol', 'diesel', 'ev'].includes(key))
  const selectedDriveKeys = selectedEngine.filter((key) => ['fwd', 'awd', 'rwd'].includes(key))

  const matchesTransmission = !selectedTransmission.length || selectedTransmission.includes(transmissionKey)
  const matchesDeposit = !selectedDeposit.length
    || selectedDeposit.some((key) => (
      (key === 'none' && hasNoDeposit)
      || (key === 'none_paid' && hasPaidNoDeposit)
    ))
  const matchesFuel = !selectedFuelKeys.length || selectedFuelKeys.includes(fuelKey)
  const matchesDrive = !selectedDriveKeys.length || selectedDriveKeys.some((key) => {
    if (key === 'awd') {
      return hasAwdCapability(car)
    }

    return driveKey === key
  })
  const matchesPayment = !selectedPayment.length || selectedPayment.some((key) => paymentMethods.includes(key))
  const matchesOptions = !selectedOptions.length || selectedOptions.every((key) => {
    switch (key) {
      case 'popular':
        return Boolean(car?.filterFlags?.popular)
      case 'topModel':
        return Boolean(car?.filterFlags?.topModel)
      case 'realPhotos':
        return Boolean(car?.filterFlags?.realPhotos)
      case 'unlimitedMileage':
        return Boolean(car?.filterFlags?.unlimitedMileage)
      case 'cityDelivery':
        return Boolean(car?.filterFlags?.cityDelivery)
      case 'guaranteedModel':
        return Boolean(car?.filterFlags?.guaranteedModel)
      case 'parking_sensors':
      case 'navigation_system':
      case 'heated_seats':
      case 'leather_interior':
      case 'premium_audio_system':
      case 'bluetooth_audio':
      case 'apple_carplay_android_auto':
      case 'third_row_seating':
        return featureKeys.includes(key)
      default:
        return false
    }
  })

  return matchesTransmission && matchesDeposit && matchesFuel && matchesDrive && matchesPayment && matchesOptions
}

const transmissionFilterItems = computed(() => [
  { key: 'auto', label: 'Automatic', count: countCatalogCars((car) => normalizeTransmissionKey(car?.specs?.transmission) === 'auto') },
  { key: 'manual', label: 'Manual', count: countCatalogCars((car) => normalizeTransmissionKey(car?.specs?.transmission) === 'manual') },
])

const depositFilterItems = computed(() => [
  { key: 'none', label: 'No deposit', count: countCatalogCars((car) => String(car?.filterMeta?.deposit?.status || '').toLowerCase() === 'no_deposit' || !Number(car?.filterMeta?.deposit?.amount || 0)) },
  { key: 'none_paid', label: 'No deposit (paid)', count: countCatalogCars((car) => Boolean(car?.filterFlags?.paidNoDeposit || car?.filterMeta?.deposit?.paidNoDepositAvailable || String(car?.filterMeta?.deposit?.status || '').toLowerCase() === 'no_deposit_paid')) },
])

const engineFuelFilterItems = computed(() => [
  { key: 'petrol', label: 'Petrol', count: countCatalogCars((car) => normalizeFuelKey(car?.specs?.fuel) === 'petrol') },
  { key: 'diesel', label: 'Diesel', count: countCatalogCars((car) => normalizeFuelKey(car?.specs?.fuel) === 'diesel') },
  { key: 'ev', label: 'EV/Hybrid', count: countCatalogCars((car) => normalizeFuelKey(car?.specs?.fuel) === 'ev') },
])

const engineDriveFilterItems = computed(() => [
  { key: 'fwd', filterKey: 'fwd', label: 'FWD', count: countCatalogCars((car) => normalizeDriveKey(car?.specs?.driveType) === 'fwd') },
  { key: 'awd', filterKey: 'awd', label: 'AWD', count: countCatalogCars((car) => hasAwdCapability(car)) },
  { key: '4x4', filterKey: 'awd', label: '4x4', count: countCatalogCars((car) => hasAwdCapability(car)) },
])

const paymentFilterItems = computed(() => [
  { key: 'cash', label: 'Cash', count: countCatalogCars((car) => Array.isArray(car?.paymentMethods) && car.paymentMethods.includes('cash')) },
  { key: 'card', label: 'Card', count: countCatalogCars((car) => Array.isArray(car?.paymentMethods) && car.paymentMethods.includes('card')) },
  { key: 'transfer', label: 'Transfer', count: countCatalogCars((car) => Array.isArray(car?.paymentMethods) && car.paymentMethods.includes('transfer')) },
])

const smartOptionItems = computed(() => [
  { key: 'popular', label: 'Popular', count: countCatalogCars((car) => Boolean(car?.filterFlags?.popular)) },
  { key: 'topModel', label: 'Top models', count: countCatalogCars((car) => Boolean(car?.filterFlags?.topModel)) },
  { key: 'realPhotos', label: 'Real photos', count: countCatalogCars((car) => Boolean(car?.filterFlags?.realPhotos)) },
  { key: 'unlimitedMileage', label: 'Unlimited mileage', count: countCatalogCars((car) => Boolean(car?.filterFlags?.unlimitedMileage)) },
  { key: 'cityDelivery', label: 'City delivery', count: countCatalogCars((car) => Boolean(car?.filterFlags?.cityDelivery)) },
  { key: 'guaranteedModel', label: 'Guaranteed model', count: countCatalogCars((car) => Boolean(car?.filterFlags?.guaranteedModel)) },
])

const wowFeatureItems = computed(() => [
  { key: 'parking_sensors', label: 'Parking Sensors', count: countCatalogCars((car) => Array.isArray(car?.featureKeys) && car.featureKeys.includes('parking_sensors')) },
  { key: 'navigation_system', label: 'Navigation System', count: countCatalogCars((car) => Array.isArray(car?.featureKeys) && car.featureKeys.includes('navigation_system')) },
  { key: 'heated_seats', label: 'Heated Seats', count: countCatalogCars((car) => Array.isArray(car?.featureKeys) && car.featureKeys.includes('heated_seats')) },
  { key: 'leather_interior', label: 'Leather Interior', count: countCatalogCars((car) => Array.isArray(car?.featureKeys) && car.featureKeys.includes('leather_interior')) },
  { key: 'premium_audio_system', label: 'Premium Audio', count: countCatalogCars((car) => Array.isArray(car?.featureKeys) && car.featureKeys.includes('premium_audio_system')) },
  { key: 'bluetooth_audio', label: 'Bluetooth Audio', count: countCatalogCars((car) => Array.isArray(car?.featureKeys) && car.featureKeys.includes('bluetooth_audio')) },
  { key: 'apple_carplay_android_auto', label: 'CarPlay / Android Auto', count: countCatalogCars((car) => Array.isArray(car?.featureKeys) && car.featureKeys.includes('apple_carplay_android_auto')) },
  { key: 'third_row_seating', label: 'Third Row Seating', count: countCatalogCars((car) => Array.isArray(car?.featureKeys) && car.featureKeys.includes('third_row_seating')) },
].filter((item) => item.count > 0))

function resolveCategoryBadgeLabel(id) {
  if (id === 'ai') {
    return 'Ask AI'
  }

  if (id === 'surprise') {
    return 'Magic Pick'
  }

  return categories.value.find((item) => item.id === id)?.label || id
}

function removeFilterValue(category, value) {
    filters[category] = (filters[category] || []).filter((item) => item !== value)
    appliedFilters[category] = (appliedFilters[category] || []).filter((item) => item !== value)
    applyCatalogFilters()
}

function clearCategoryBadge() {
  activeCategory.value = 'all'
}

function clearAiBadge() {
  aiMode.value = false
  aiPromptKey.value = ''
  aiQuery.value = ''
  aiSearchResults.value = []
  aiSearchError.value = ''
  aiSearchActive.value = false
  if (activeCategory.value === 'ai') {
    activeCategory.value = 'all'
  }
}

function clearAllFilterBadges() {
  hasUserChangedSearchState.value = true
  activeCategory.value = 'all'
  aiMode.value = false
  aiPromptKey.value = ''
  aiQuery.value = ''
  aiSearchResults.value = []
  aiSearchError.value = ''
  aiSearchActive.value = false
  copyCatalogFilters({ transmission: [], deposit: [], engine: [], payment: [], options: [] }, filters)
  copyCatalogFilters(filters, appliedFilters)

  const nextQuery = { ...route.query }
  ;['scCat', 'scAi', 'scQ', 'scTrans', 'scDep', 'scEng', 'scPay', 'scOpt', 'scDd', 'scMore'].forEach((key) => {
    delete nextQuery[key]
  })

  syncedFilterQuerySignature = buildFilterQuerySignature(nextQuery)
  hasSyncedInitialFiltersFromRoute = true
  isApplyingCatalogFilters.value = true

  void (async () => {
    try {
      await replaceQueryWithoutScroll(nextQuery)
    } finally {
      queueMicrotask(() => {
        isApplyingCatalogFilters.value = false
      })
    }
  })()
}

function buildBadgeItems(selectedKeys, sourceItems, removeCategory) {
  return uniqueValues(selectedKeys).map((key) => {
    const matchedItem = sourceItems.find((item) => item.key === key || item.filterKey === key)

    if (!matchedItem) {
      return null
    }

    return {
      key,
      label: matchedItem?.label || key,
      onRemove: () => removeFilterValue(removeCategory, key),
    }
  }).filter(Boolean)
}

function buildEngineDriveBadgeItems(selectedKeys) {
  const badges = []

  uniqueValues(selectedKeys).forEach((key) => {
    if (key === 'awd') {
      badges.push(
        { key: 'awd', label: 'AWD', onRemove: () => removeFilterValue('engine', 'awd') },
        { key: '4x4', label: '4x4', onRemove: () => removeFilterValue('engine', 'awd') },
      )
      return
    }

    const matchedItem = engineDriveFilterItems.value.find((item) => item.filterKey === key || item.key === key)

    if (!matchedItem) {
      return
    }

    badges.push({
      key: matchedItem.key,
      label: matchedItem.label,
      onRemove: () => removeFilterValue('engine', matchedItem.filterKey || matchedItem.key),
    })
  })

  return badges
}

const activeFilterBadgeGroups = computed(() => {
  const groups = []

  if (activeCategory.value !== 'all') {
    groups.push({
      key: 'category',
      label: 'Category',
      items: [{
        key: activeCategory.value,
        label: resolveCategoryBadgeLabel(activeCategory.value),
        onRemove: clearCategoryBadge,
      }],
    })
  }

  if (aiMode.value || aiQuery.value) {
    groups.push({
      key: 'ai',
      label: 'AI Search',
      items: [{
        key: aiQuery.value || 'ai',
        label: aiQuery.value || 'Ask AI',
        onRemove: clearAiBadge,
      }],
    })
  }

  const transmissionItems = buildBadgeItems(appliedFilters.transmission, transmissionFilterItems.value, 'transmission')
  const depositItems = buildBadgeItems(appliedFilters.deposit, depositFilterItems.value, 'deposit')
  const engineItems = [
    ...buildBadgeItems(appliedFilters.engine.filter((key) => ['petrol', 'diesel', 'ev'].includes(key)), engineFuelFilterItems.value, 'engine'),
    ...buildEngineDriveBadgeItems(appliedFilters.engine.filter((key) => ['fwd', 'awd', 'rwd'].includes(key))),
  ]
  const paymentItems = buildBadgeItems(appliedFilters.payment, paymentFilterItems.value, 'payment')
  const smartItems = buildBadgeItems(appliedFilters.options, smartOptionItems.value, 'options')
  const wowItems = buildBadgeItems(appliedFilters.options, wowFeatureItems.value, 'options')

  if (transmissionItems.length) {
    groups.push({ key: 'transmission', label: 'Transmission', items: transmissionItems })
  }

  if (depositItems.length) {
    groups.push({ key: 'deposit', label: 'Deposit', items: depositItems })
  }

  if (engineItems.length) {
    groups.push({ key: 'engine', label: 'Engine & Drive', items: engineItems })
  }

  if (paymentItems.length) {
    groups.push({ key: 'payment', label: 'Payment Method', items: paymentItems })
  }

  if (smartItems.length) {
    groups.push({ key: 'smart', label: 'Smart Options', items: smartItems })
  }

  if (wowItems.length) {
    groups.push({ key: 'wow', label: 'Wow-Features', items: wowItems })
  }

  return groups
})

const visibleCars = computed(() => filteredCars.value.slice(0, visibleCount.value))
const hasMoreCars = computed(() => visibleCount.value < filteredCars.value.length)
const isCatalogLoading = computed(() => isLoading.value || homeContentPending.value)
const isSearchBusy = computed(() => (
  isLoading.value
  || aiSearchLoading.value
  || isCommittingDateSelection.value
  || isApplyingCatalogFilters.value
  || uiStateSyncingFromRoute.value
  || aiSearchAutoRunPending.value
))
const showNoCarsState = computed(() => (
  hasUserChangedSearchState.value
  && !isSearchBusy.value
  && !aiSearchError.value
  && !visibleCars.value.length
))
const compareSourceIsAi = computed(() => activeCategory.value === 'ai' && aiSearchActive.value)
const compareLookupCars = computed(() => {
  const items = compareSourceIsAi.value
    ? [...aiSearchCards.value, ...catalogCars.value]
    : [...catalogCars.value, ...aiSearchCards.value]

  const seen = new Set()

  return items.filter((car) => {
    const key = String(car?.id || '').trim()

    if (!key || seen.has(key)) {
      return false
    }

    seen.add(key)
    return true
  })
})
const compareCars = computed(() => compareSelectedCars.value)
const compareRequestKeys = computed(() => compareList.value.slice(0, 3))
const canRunCompare = computed(() => compareRequestKeys.value.length >= 2)
const compareSummary = computed(() => aiCompareResult.value?.recommendation || aiCompareResult.value?.summary || generateCompareSummary(compareCars.value))
const draftFilteredCarsCount = computed(() => catalogCars.value.filter((car) => matchesCatalogFilters(car, filters)).length)
const showVehiclesLabel = computed(() => `Show ${draftFilteredCarsCount.value} vehicles`)
const aiSearchCards = computed(() => (
  Array.isArray(aiSearchResults.value)
    ? aiSearchResults.value.map((result) => normalizeAiSearchVehicle(result)).filter(Boolean)
    : []
))

const whereTypeOrder = {
  airport: 10,
  office: 20,
  delivery: 30,
  city: 40,
}

const whereDropdownLocations = computed(() => [...whereLocations.value].sort(sortWhereLocation))
function resolveDefaultWhereLocation() {
  const matchDowntownOffice = whereDropdownLocations.value.find((location) => {
    const city = normalizeTextKey(location?.city || location?.cityName)
    const name = normalizeTextKey(location?.name)
    const code = normalizeTextKey(location?.code || location?.rawCode)
    const haystack = `${name} ${city} ${code}`

    return haystack.includes('tbilisi') && haystack.includes('downtown') && haystack.includes('office')
  })

  const matchDowntown = whereDropdownLocations.value.find((location) => {
    const city = normalizeTextKey(location?.city || location?.cityName)
    const name = normalizeTextKey(location?.name)
    const code = normalizeTextKey(location?.code || location?.rawCode)
    const haystack = `${name} ${city} ${code}`

    return haystack.includes('downtown') && (haystack.includes('tbilisi') || location?.type === 'office')
  })

  const matchOffice = whereDropdownLocations.value.find((location) => {
    const city = normalizeTextKey(location?.city || location?.cityName)
    const name = normalizeTextKey(location?.name)
    const code = normalizeTextKey(location?.code || location?.rawCode)
    const haystack = `${name} ${city} ${code}`

    return location?.type === 'office' && haystack.includes('tbilisi')
  })

  const matchAnyTbilisi = whereDropdownLocations.value.find((location) => {
    const city = normalizeTextKey(location?.city || location?.cityName)
    const name = normalizeTextKey(location?.name)

    return city.includes('tbilisi') || name.includes('tbilisi')
  })

  return matchDowntownOffice || matchDowntown || matchOffice || matchAnyTbilisi || whereDropdownLocations.value[0] || null
}

const defaultTbilisiLocation = computed(() => resolveDefaultWhereLocation())
const whereTypeLabels = computed(() => ({
  airport: resolvePublicUiValue(locale.value, 'locationsPage.typeAirport', 'Airport'),
  office: resolvePublicUiValue(locale.value, 'locationsPage.typeOffice', 'Office'),
  delivery: resolvePublicUiValue(locale.value, 'locationsPage.typeDelivery', 'Delivery'),
}))
const whereDropdownGroups = computed(() => (['airport', 'office', 'delivery']).map((key) => ({
  key,
  label: whereTypeLabels.value[key],
  items: whereDropdownLocations.value.filter((item) => resolveWhereType(item) === key),
})).filter((group) => group.items.length))
const selectedPickupLocation = computed(() => pickupLocation.value || defaultTbilisiLocation.value || whereDropdownLocations.value[0] || null)
const selectedDropoffLocation = computed(() => (
  returnToSameLocation.value
    ? selectedPickupLocation.value
    : (dropoffLocation.value || whereDropdownLocations.value[1] || selectedPickupLocation.value || null)
))
const pickupLocationLabel = computed(() => selectedPickupLocation.value?.city || selectedPickupLocation.value?.cityName || selectedPickupLocation.value?.name || '')
const quickViewBookingPayload = computed(() => {
  const pickup = selectedPickupLocation.value
  const dropoff = selectedDropoffLocation.value
  const from = dateRange.value?.from
  const to = dateRange.value?.to

  if (!pickup?.backendId || !dropoff?.backendId || !(from instanceof Date) || !(to instanceof Date)) {
    return null
  }

  return buildCatalogPayload({
    pickupLocationId: pickup.backendId,
    dropoffLocationId: dropoff.backendId,
    pickupDate: from,
    dropoffDate: to,
    pickupTime: pickupTime.value,
    dropoffTime: dropoffTime.value,
    currency: currency.value,
  })
})
const dropoffLocationLabel = computed(() => selectedDropoffLocation.value?.city || selectedDropoffLocation.value?.cityName || selectedDropoffLocation.value?.name || pickupLocationLabel.value)
const whereSummaryLabel = computed(() => {
  if (!selectedPickupLocation.value) {
    return ''
  }

  if (returnToSameLocation.value || Number(selectedPickupLocation.value.backendId || 0) === Number(selectedDropoffLocation.value?.backendId || 0)) {
    return pickupLocationLabel.value
  }

  return `${pickupLocationLabel.value} → ${dropoffLocationLabel.value}`
})
const dateRangeLabel = computed(() => {
  if (!dateRange.value?.from || !dateRange.value?.to) {
    return selectDateLabel.value
  }

  return `${format(dateRange.value.from, 'MMM d')} - ${format(dateRange.value.to, 'MMM d')}`
})

watch(activeCategory, () => {
  visibleCount.value = 40
  isLoading.value = true
  if (loadingTimer) {
    clearTimeout(loadingTimer)
  }
  loadingTimer = window.setTimeout(() => {
    isLoading.value = false
  }, 600)
})

watch(
  () => [
    filters.transmission.join('|'),
    filters.deposit.join('|'),
    filters.engine.join('|'),
    filters.payment.join('|'),
    filters.options.join('|'),
  ].join('::'),
  () => {
    visibleCount.value = 40
  },
)

watch(
  () => sortMode.value,
  () => {
    visibleCount.value = 40
  },
)

watch(
  () => compareSourceIsAi.value ? 'ai' : 'catalog',
  (nextSource, previousSource) => {
    if (previousSource && nextSource !== previousSource) {
      compareList.value = []
      compareSelectedCars.value = []
      showCompareSummary.value = false
      aiCompareResult.value = null
      aiCompareError.value = ''
    }
  },
  { immediate: true },
)

watch(
  () => [
    whereLocations.value.length,
    route.query.pickupLocationId,
    route.query.dropoffLocationId,
    route.query.returnToSameLocation,
    route.query.pickupAt,
    route.query.dropoffAt,
  ],
  () => {
    syncWhereStateFromRoute()
    syncDateStateFromRoute()
  },
  { immediate: true },
)

watch(
  () => [
    selectedPickupLocation.value?.backendId || 0,
    selectedDropoffLocation.value?.backendId || 0,
    returnToSameLocation.value ? '1' : '0',
    dateRange.value?.from instanceof Date ? dateRange.value.from.getTime() : 0,
    dateRange.value?.to instanceof Date ? dateRange.value.to.getTime() : 0,
    pickupTime.value,
    dropoffTime.value,
    sortMode.value,
  ].join('::'),
  () => {
    if (uiStateSyncingFromRoute.value || isCommittingDateSelection.value || !canSyncSearchStateToUrl.value) {
      return
    }

    if (!(dateRange.value?.from instanceof Date) || !(dateRange.value?.to instanceof Date)) {
      return
    }

    const nextPickup = selectedPickupLocation.value || defaultTbilisiLocation.value || whereDropdownLocations.value[0] || null
    const nextDropoff = returnToSameLocation.value
      ? nextPickup
      : (selectedDropoffLocation.value || nextPickup)

    const nextQuery = {
      ...route.query,
      ...buildRentTripQuery({
        pickupLocationId: nextPickup?.backendId || undefined,
        dropoffLocationId: nextDropoff?.backendId || nextPickup?.backendId || undefined,
        pickupAt: buildIsoDateTime(dateRange.value.from, pickupTime.value),
        dropoffAt: buildIsoDateTime(dateRange.value.to, dropoffTime.value),
        returnToSameLocation: Number(nextPickup?.backendId || 0) === Number(nextDropoff?.backendId || 0) ? '1' : '0',
      }),
    }

    if (sortMode.value !== 'recommended') {
      nextQuery.scSort = sortMode.value
    } else {
      delete nextQuery.scSort
    }

    const nextQueryString = JSON.stringify(nextQuery)
    const currentQueryString = JSON.stringify(route.query)

    if (nextQueryString === currentQueryString) {
      return
    }

    void replaceQueryWithoutScroll(nextQuery)
  },
  { immediate: true },
)

watch(
  () => route.query,
  async () => {
    if (uiStateSyncingFromRoute.value) {
      return
    }

    uiStateSyncingFromRoute.value = true
    const hasAiQueryParam = Object.prototype.hasOwnProperty.call(route.query, 'scQ')
    const nextAiPromptKey = resolveAllowedAiPromptKey(route.query.scQ)

    activeCategory.value = resolveActiveCategoryFromQuery(route.query.scCat)
    sortMode.value = resolveSortModeFromQuery(route.query.scSort)
    aiMode.value = isTruthyQueryValue(route.query.scAi) || activeCategory.value === 'ai'

    if (nextAiPromptKey) {
      aiPromptKey.value = nextAiPromptKey
      aiQuery.value = resolveAiPromptLabel(nextAiPromptKey)
      aiSearchAutoRunPending.value = true
    } else if (hasAiQueryParam) {
      aiPromptKey.value = ''
      aiQuery.value = ''
      aiSearchAutoRunPending.value = false
    }

    isExpanded.value = isTruthyQueryValue(route.query.scMore)
    activeDropdown.value = ['where', 'when', 'more'].includes(normalizeUiQueryValue(route.query.scDd))
      ? normalizeUiQueryValue(route.query.scDd)
      : null
    const nextFilterQuerySignature = buildFilterQuerySignature(route.query)
    const hasFilterQueryParams = ['scTrans', 'scDep', 'scEng', 'scPay', 'scOpt'].some((key) => Object.prototype.hasOwnProperty.call(route.query, key))

    if (!hasSyncedInitialFiltersFromRoute || (hasFilterQueryParams && nextFilterQuerySignature !== syncedFilterQuerySignature)) {
      hasSyncedInitialFiltersFromRoute = true
      syncedFilterQuerySignature = nextFilterQuerySignature
      const nextAppliedFilters = {
        transmission: parseCsvQuery(route.query.scTrans),
        deposit: parseCsvQuery(route.query.scDep),
        engine: parseCsvQuery(route.query.scEng),
        payment: parseCsvQuery(route.query.scPay),
        options: parseCsvQuery(route.query.scOpt),
      }
      copyCatalogFilters(nextAppliedFilters, appliedFilters)
      copyCatalogFilters(nextAppliedFilters, filters)
    }

    compareList.value = parseCsvQuery(route.query.scCmp)
    syncCompareSelectionFromIds(compareList.value)

    quickViewCar.value = null

    queueMicrotask(() => {
      uiStateSyncingFromRoute.value = false
    })
  },
  { immediate: true, deep: true },
)

watch(
  () => [normalizeUiQueryValue(route.query.scCar), catalogCars.value],
  ([nextGamificationKey, cars]) => {
    const nextGamificationCar = nextGamificationKey
      ? cars.find((car) => resolveCatalogVehicleKey(car) === nextGamificationKey) || null
      : null

    if (!nextGamificationKey) {
      showGamification.value = false
      gamificationCar.value = null
      return
    }

    gamificationCar.value = nextGamificationCar
    showGamification.value = Boolean(nextGamificationCar)
  },
  { immediate: true },
)

watch(
  () => [locale.value, aiPromptKey.value],
  () => {
    if (!aiPromptKey.value) {
      return
    }

    aiQuery.value = resolveAiPromptLabel(aiPromptKey.value)
  },
  { immediate: true },
)

watch(
  () => [
    aiSearchAutoRunPending.value,
    aiPromptKey.value,
    aiMode.value,
    selectedPickupLocation.value?.backendId,
    selectedDropoffLocation.value?.backendId,
    dateRange.value?.from instanceof Date ? dateRange.value.from.getTime() : 0,
    dateRange.value?.to instanceof Date ? dateRange.value.to.getTime() : 0,
  ].join('::'),
  () => {
    if (!aiSearchAutoRunPending.value || aiSearchLoading.value) {
      return
    }

    if (!aiMode.value || !aiPromptKey.value) {
      return
    }

    if (!selectedPickupLocation.value || !selectedDropoffLocation.value) {
      return
    }

    aiSearchAutoRunPending.value = false
    void runAiSearch()
  },
  { immediate: true },
)

watch(
  () => [
    activeCategory.value,
    aiMode.value,
    aiQuery.value,
    aiPromptKey.value,
    isExpanded.value,
    activeDropdown.value || '',
    compareList.value.join('|'),
    sortMode.value,
  ].join('::'),
  () => {
    if (uiStateSyncingFromRoute.value || isApplyingCatalogFilters.value) {
      return
    }

    const nextUiQuery = {
      scCat: activeCategory.value !== 'all' ? activeCategory.value : undefined,
      scAi: aiMode.value ? '1' : undefined,
      scQ: aiPromptKey.value || undefined,
      scMore: isExpanded.value ? '1' : undefined,
      scDd: activeDropdown.value || undefined,
      scCmp: buildCsvQueryValue(compareList.value),
      scSort: sortMode.value !== 'recommended' ? sortMode.value : undefined,
    }

    const nextQuery = { ...route.query }

    Object.keys(nextUiQuery).forEach((key) => {
      if (nextUiQuery[key]) {
        nextQuery[key] = nextUiQuery[key]
      } else {
        delete nextQuery[key]
      }
    })

    if (JSON.stringify(nextQuery) === JSON.stringify(route.query)) {
      return
    }

    void replaceQueryWithoutScroll(nextQuery)
  },
)

watch(
  () => [
    selectedPickupLocation.value?.backendId,
    selectedPickupLocation.value?.code,
    dateRange.value?.from instanceof Date ? dateRange.value.from.getTime() : 0,
    dateRange.value?.to instanceof Date ? dateRange.value.to.getTime() : 0,
  ],
  () => {
    scheduleWeatherForecastFetch()
  },
  { immediate: true },
)

watch(
  () => [
    canShowWeatherForecast.value ? '1' : '0',
    selectedPickupLocation.value?.backendId || 0,
    selectedDropoffLocation.value?.backendId || 0,
    dateRange.value?.from instanceof Date ? dateRange.value.from.getTime() : 0,
    dateRange.value?.to instanceof Date ? dateRange.value.to.getTime() : 0,
    pickupTime.value,
    dropoffTime.value,
    currency.value,
  ].join('::'),
  () => {
    void fetchLiveAvailability()
  },
  { immediate: true },
)

watch(
  () => [
    dateRange.value?.from instanceof Date ? dateRange.value.from.getTime() : 0,
    dateRange.value?.to instanceof Date ? dateRange.value.to.getTime() : 0,
  ].join('::'),
  () => {
    if (uiStateSyncingFromRoute.value || isCommittingDateSelection.value || !canSyncSearchStateToUrl.value) {
      return
    }

    if (!(dateRange.value?.from instanceof Date) || !(dateRange.value?.to instanceof Date)) {
      return
    }

    void syncDateSelectionToUrl(dateRange.value)
  },
)

function selectCategory(id) {
  hasUserChangedSearchState.value = true
  if (id === 'ai') {
    aiMode.value = !aiMode.value
    activeCategory.value = aiMode.value ? 'ai' : 'all'

    if (!aiMode.value) {
      aiPromptKey.value = ''
      aiQuery.value = ''
      aiSearchResults.value = []
      aiSearchExplanation.value = ''
      aiSearchError.value = ''
      aiSearchActive.value = false
    }
    return
  }

  if (id === 'surprise') {
    aiMode.value = false
    aiPromptKey.value = ''
    aiQuery.value = ''
    aiSearchResults.value = []
    aiSearchExplanation.value = ''
    aiSearchError.value = ''
    aiSearchActive.value = false
    activeCategory.value = 'surprise'
    return
  }

  aiMode.value = false
  aiPromptKey.value = ''
  aiQuery.value = ''
  aiSearchResults.value = []
  aiSearchExplanation.value = ''
  aiSearchError.value = ''
  aiSearchActive.value = false
  activeCategory.value = id
}

function toggleDropdown(name) {
  hasUserChangedSearchState.value = true
  const nextDropdown = activeDropdown.value === name ? null : name

  if (nextDropdown === 'more') {
    copyCatalogFilters(appliedFilters, filters)
  }

  activeDropdown.value = nextDropdown
  isExpanded.value = false
}

function toggleFilter(category, value) {
  hasUserChangedSearchState.value = true
  const current = filters[category] || []
  filters[category] = current.includes(value)
    ? current.filter((item) => item !== value)
    : [...current, value]
}

function closeDropdown() {
  activeDropdown.value = null
}

function applyCatalogFilters() {
  hasUserChangedSearchState.value = true
  visibleCount.value = Math.min(40, filteredCars.value.length || 40)
  isExpanded.value = false
  isLoading.value = true

  if (loadingTimer) {
    clearTimeout(loadingTimer)
  }

  copyCatalogFilters(filters, appliedFilters)

  const nextQuery = { ...route.query }
  const selectedFilters = {
    scTrans: buildCsvQueryValue(filters.transmission),
    scDep: buildCsvQueryValue(filters.deposit),
    scEng: buildCsvQueryValue(filters.engine),
    scPay: buildCsvQueryValue(filters.payment),
    scOpt: buildCsvQueryValue(filters.options),
  }

  Object.entries(selectedFilters).forEach(([key, value]) => {
    if (value) {
      nextQuery[key] = value
    } else {
      delete nextQuery[key]
    }
  })

  delete nextQuery.scDd
  delete nextQuery.scMore

  isApplyingCatalogFilters.value = true

  void (async () => {
    try {
      syncedFilterQuerySignature = buildFilterQuerySignature(nextQuery)
      hasSyncedInitialFiltersFromRoute = true
      activeDropdown.value = null
      await replaceQueryWithoutScroll(nextQuery)
    } finally {
      queueMicrotask(() => {
        isApplyingCatalogFilters.value = false
      })
    }
  })()

  loadingTimer = window.setTimeout(() => {
    isLoading.value = false
  }, 320)
}

function handleAwdQuickAction() {
  hasUserChangedSearchState.value = true
  toggleFilter('engine', 'awd')
  applyCatalogFilters()
}

function handleAiPrompt(prompt) {
  hasUserChangedSearchState.value = true
  const allowedPromptKey = resolveAllowedAiPromptKey(prompt)
  if (!allowedPromptKey) {
    return
  }
  aiMode.value = true
  activeCategory.value = 'ai'
  aiPromptKey.value = allowedPromptKey
  aiQuery.value = resolveAiPromptLabel(allowedPromptKey) || ''
  aiSearchResults.value = []
  aiSearchExplanation.value = ''
  aiSearchError.value = ''
  aiSearchActive.value = false
}

function handleAiQueryInput() {
  hasUserChangedSearchState.value = true
  if (!aiPromptKey.value) {
    aiSearchResults.value = []
    aiSearchExplanation.value = ''
    aiSearchError.value = ''
    aiSearchActive.value = false
    return
  }

  aiPromptKey.value = ''
  aiSearchResults.value = []
  aiSearchExplanation.value = ''
  aiSearchError.value = ''
  aiSearchActive.value = false
}

async function runAiSearch() {
  hasUserChangedSearchState.value = true
  const query = normalizeUiQueryValue(aiQuery.value)

  if (!query || aiSearchLoading.value) {
    return
  }

  const pickup = selectedPickupLocation.value
  const dropoff = selectedDropoffLocation.value || pickup
  const pickupAt = buildIsoDateTime(dateRange.value?.from, pickupTime.value)
  const dropoffAt = buildIsoDateTime(dateRange.value?.to, dropoffTime.value)

  if (!pickup?.backendId || !dropoff?.backendId || !pickupAt || !dropoffAt) {
    aiSearchError.value = 'Missing trip details.'
    return
  }

  aiMode.value = true
  activeCategory.value = 'ai'
  aiSearchActive.value = true
  aiSearchLoading.value = true
  aiSearchError.value = ''
  aiSearchExplanation.value = ''
  isLoading.value = true

  if (loadingTimer) {
    clearTimeout(loadingTimer)
  }

  try {
    const response = await $fetch(`${runtimeConfig.public.apiBaseUrl}/ai-search/vehicles`, {
      method: 'POST',
      body: {
        query,
        pickup_location_id: pickup.backendId,
        dropoff_location_id: dropoff.backendId,
        location_name: pickup.name || undefined,
        location_code: pickup.code || undefined,
        city: pickup.city || pickup.cityName || undefined,
        latitude: pickup.latitude || pickup.lat || undefined,
        longitude: pickup.longitude || pickup.lng || undefined,
        pickup_at: pickupAt,
        dropoff_at: dropoffAt,
        currency: currency.value,
        fingerprint: resolveAiDeviceFingerprint() || undefined,
        device_fingerprint: resolveAiDeviceFingerprint() || undefined,
        limit: 12,
      },
    })

    const payload = response?.data || response || {}
    aiSearchResults.value = Array.isArray(payload.results) ? payload.results : []
    aiSearchExplanation.value = String(payload.explanation || '').trim()

    visibleCount.value = 40
  } catch (error) {
    aiSearchResults.value = []
    aiSearchExplanation.value = ''
    aiSearchActive.value = false
    aiSearchError.value = resolvePublicApiError(error, 'AI search failed. Try again.')
  } finally {
    aiSearchLoading.value = false

    loadingTimer = window.setTimeout(() => {
      isLoading.value = false
    }, 240)
  }
}

function buildIsoDateTime(dateValue, timeValue) {
  if (!(dateValue instanceof Date) || Number.isNaN(dateValue.getTime())) {
    return undefined
  }

  const [hours, minutes] = String(timeValue || '00:00').split(':').map((item) => Number(item))
  const nextDate = new Date(dateValue)
  nextDate.setHours(hours || 0, minutes || 0, 0, 0)
  return nextDate.toISOString()
}

function handleOutsideClick(event) {
  if (typeof document === 'undefined') {
    return
  }

  const root = searchBarRef.value
  const target = event?.target

  if (!root || !target || root.contains(target)) {
    return
  }

  closeDropdown()
  isExpanded.value = false
}

function applyRoute() {
  hasUserChangedSearchState.value = true
  const nextPickup = selectedPickupLocation.value || whereDropdownLocations.value[0] || null
  const nextDropoff = returnToSameLocation.value
    ? nextPickup
    : (selectedDropoffLocation.value || whereDropdownLocations.value[1] || nextPickup)
  commitSearchRoute(nextPickup, nextDropoff)
}

function applyDates() {
  hasUserChangedSearchState.value = true
  void commitSearchRoute()
}

async function commitSearchRoute(
  nextPickup = selectedPickupLocation.value || whereDropdownLocations.value[0] || null,
  nextDropoff = selectedDropoffLocation.value || whereDropdownLocations.value[1] || nextPickup,
  nextDateRange = dateRange.value,
) {
  isLoading.value = true
  if (loadingTimer) {
    clearTimeout(loadingTimer)
  }
  const resolvedPickup = nextPickup || defaultTbilisiLocation.value || whereDropdownLocations.value[0] || null
  const resolvedDropoff = returnToSameLocation.value
    ? resolvedPickup
    : (nextDropoff || resolvedPickup)
  const nextQuery = buildRentTripQuery({
    pickupLocationId: resolvedPickup?.backendId || undefined,
    dropoffLocationId: resolvedDropoff?.backendId || resolvedPickup?.backendId || undefined,
    pickupAt: buildIsoDateTime(nextDateRange?.from, pickupTime.value),
    dropoffAt: buildIsoDateTime(nextDateRange?.to, dropoffTime.value),
    returnToSameLocation: Number(resolvedPickup?.backendId || 0) === Number(resolvedDropoff?.backendId || 0) ? '1' : '0',
  })

  if (sortMode.value !== 'recommended') {
    nextQuery.scSort = sortMode.value
  }

  await replaceQueryWithoutScroll({
    ...route.query,
    ...nextQuery,
  })

  closeDropdown()

  loadingTimer = window.setTimeout(() => {
    isLoading.value = false
  }, 600)
}

async function syncDateSelectionToUrl(nextDateRange) {
  if (!nextDateRange?.from || !nextDateRange?.to) {
    return
  }
  isCommittingDateSelection.value = true
  try {
    const nextPickup = selectedPickupLocation.value || defaultTbilisiLocation.value || whereDropdownLocations.value[0] || null
    const nextDropoff = returnToSameLocation.value
      ? nextPickup
      : (selectedDropoffLocation.value || nextPickup)

    const nextQuery = buildRentTripQuery({
      pickupLocationId: nextPickup?.backendId || route.query.pickupLocationId || undefined,
      dropoffLocationId: nextDropoff?.backendId || route.query.dropoffLocationId || route.query.pickupLocationId || undefined,
      pickupAt: buildIsoDateTime(nextDateRange.from, pickupTime.value),
      dropoffAt: buildIsoDateTime(nextDateRange.to, dropoffTime.value),
      returnToSameLocation: nextPickup?.backendId && nextDropoff?.backendId
        ? (Number(nextPickup.backendId || 0) === Number(nextDropoff.backendId || 0) ? '1' : '0')
        : route.query.returnToSameLocation || undefined,
    })

    if (sortMode.value !== 'recommended') {
      nextQuery.scSort = sortMode.value
    }

    await replaceQueryWithoutScroll({
      ...route.query,
      ...nextQuery,
    })
  } finally {
    queueMicrotask(() => {
      isCommittingDateSelection.value = false
    })
  }
}

function resolveWhereType(location) {
  const rawType = String(location?.type || '').toLowerCase()

  if (whereTypeOrder[rawType]) {
    return rawType
  }

  const rawCode = String(location?.rawCode || location?.code || '').toUpperCase()

  if (rawCode.includes('AIRPORT')) {
    return 'airport'
  }

  if (rawCode.includes('OFFICE')) {
    return 'office'
  }

  if (rawCode.includes('DELIVERY')) {
    return 'delivery'
  }

  return 'city'
}

function sortWhereLocation(left, right) {
  const leftType = whereTypeOrder[resolveWhereType(left)] ?? 99
  const rightType = whereTypeOrder[resolveWhereType(right)] ?? 99

  if (leftType !== rightType) {
    return leftType - rightType
  }

  return String(left.name || '').localeCompare(String(right.name || ''))
}

function resolveLocationByBackendId(id, fallbackIndex = 0) {
  const numericId = Number(id || 0)

  if (numericId > 0) {
    const matched = whereLocations.value.find((location) => Number(location.backendId) === numericId)

    if (matched) {
      return matched
    }
  }

  return whereLocations.value[fallbackIndex] || null
}

function setPickupLocation(location) {
  if (!location) {
    return
  }

  hasUserChangedSearchState.value = true
  pickupLocation.value = location

  if (returnToSameLocation.value || !dropoffLocation.value) {
    dropoffLocation.value = location
  }

  if (Number(dropoffLocation.value?.backendId || 0) === Number(location.backendId || 0)) {
    returnToSameLocation.value = true
  }
}

function setDropoffLocation(location) {
  if (!location) {
    return
  }

  hasUserChangedSearchState.value = true
  dropoffLocation.value = location
  returnToSameLocation.value = Number(location.backendId || 0) === Number(pickupLocation.value?.backendId || 0)
}

function setSameAsPickup() {
  if (!pickupLocation.value) {
    return
  }

  hasUserChangedSearchState.value = true
  dropoffLocation.value = pickupLocation.value
  returnToSameLocation.value = true
}

function syncWhereStateFromRoute() {
  if (!whereLocations.value.length) {
    return
  }

  const hasRouteWhere = Boolean(route.query.pickupLocationId || route.query.dropoffLocationId)
  const fallbackPickup = defaultTbilisiLocation.value || whereLocations.value[0] || null
  const pickup = resolveLocationByBackendId(route.query.pickupLocationId, 0) || fallbackPickup
  const dropoff = hasRouteWhere
    ? (resolveLocationByBackendId(route.query.dropoffLocationId || route.query.pickupLocationId, 1) || pickup)
    : pickup
  const nextPickupId = Number(pickup?.backendId || fallbackPickup?.backendId || 0)
  const nextDropoffId = Number(dropoff?.backendId || nextPickupId || 0)
  const nextSameLocation = String(route.query.returnToSameLocation || '') === '1'
    || nextPickupId === nextDropoffId

  if (
    Number(pickupLocation.value?.backendId || 0) === nextPickupId
    && Number(dropoffLocation.value?.backendId || 0) === nextDropoffId
    && returnToSameLocation.value === nextSameLocation
  ) {
    return
  }

  pickupLocation.value = pickup || fallbackPickup || null
  dropoffLocation.value = dropoff || pickupLocation.value
  returnToSameLocation.value = nextSameLocation
}

function syncDateStateFromRoute() {
  if (isCommittingDateSelection.value) {
    return
  }
  const hasRouteDate = Boolean(route.query.pickupAt || route.query.dropoffAt)
  const parsed = hasRouteDate ? parseSearchQuery(route.query) : null

  if (!hasRouteDate) {
    hasInitializedDateState.value = true
    return
  }

  const nextFrom = parsed?.pickupDate || buildDate(3)
  const nextTo = parsed?.dropoffDate || buildDate(10)
  const nextPickupTime = parsed?.pickupTime || '12:30'
  const nextDropoffTime = parsed?.dropoffTime || '08:30'

  const currentFromTime = dateRange.value?.from instanceof Date ? dateRange.value.from.getTime() : 0
  const currentToTime = dateRange.value?.to instanceof Date ? dateRange.value.to.getTime() : 0
  const nextFromTime = nextFrom instanceof Date ? nextFrom.getTime() : 0
  const nextToTime = nextTo instanceof Date ? nextTo.getTime() : 0

  if (
    currentFromTime === nextFromTime
    && currentToTime === nextToTime
    && pickupTime.value === nextPickupTime
    && dropoffTime.value === nextDropoffTime
  ) {
    return
  }

  dateRange.value = {
    from: nextFrom,
    to: nextTo,
  }
  pickupTime.value = nextPickupTime
  dropoffTime.value = nextDropoffTime
  hasInitializedDateState.value = true
}

function handleDateSelect(range) {
  hasUserChangedSearchState.value = true

  const nextRange = Array.isArray(range)
    ? { from: range[0] || null, to: range[1] || null }
    : {
        from: range?.from || range?.start || range?.startDate || null,
        to: range?.to || range?.end || range?.endDate || null,
      }

  dateRange.value = nextRange

  if (nextRange.from && nextRange.to) {
    void (async () => {
      await syncDateSelectionToUrl(nextRange)
      closeDropdown()
    })()
  }
}

function loadMoreCars() {
  visibleCount.value = Math.min(visibleCount.value + 40, filteredCars.value.length)
}

function toggleCompare(car) {
  const compareKey = resolveCompareSelectionKey(car)

  if (!compareKey) {
    console.log('[home compare] missing compare key for card', {
      rawId: car?.id,
      contentKey: car?.contentKey || car?.content_key || car?.entityId || car?.entity_id || null,
      vehicleGroupId: car?.vehicleGroupId || null,
      name: car?.name,
    })
    return
  }

  console.log('[home compare] compare key:', compareKey, 'rawId:', car?.id, 'name:', car?.name)

  const exactCompareCar = normalizeCompareCar(car, compareKey)

  const compareLimitMessage = ui.value.search?.compareLimitMessage || 'Compare up to 3 cars max.'

  if (compareList.value.includes(compareKey)) {
    compareList.value = compareList.value.filter((value) => value !== compareKey)
    compareSelectedCars.value = compareSelectedCars.value.filter((item) => resolveCompareSelectionKey(item) !== compareKey)
    if (aiCompareError.value === compareLimitMessage && compareList.value.length < 3) {
      aiCompareError.value = ''
    }
    return
  }

  if (compareList.value.length >= 3) {
    aiCompareError.value = compareLimitMessage
    return
  }

  compareList.value = [...compareList.value, compareKey]
  compareSelectedCars.value = [...compareSelectedCars.value, exactCompareCar].filter(Boolean)
  if (aiCompareError.value === compareLimitMessage && compareList.value.length < 3) {
    aiCompareError.value = ''
  }
}

function syncCompareSelectionFromIds(ids = []) {
  const nextSelectedCars = []
  const seen = new Set()

  ids.slice(0, 3).forEach((id) => {
    const matched = compareLookupCars.value.find((car) => resolveCompareSelectionKey(car) === String(id))
    const key = resolveCompareSelectionKey(matched)

    if (!matched || !key || seen.has(key)) {
      return
    }

    seen.add(key)
    nextSelectedCars.push(normalizeCompareCar(matched, key))
  })

  compareSelectedCars.value = nextSelectedCars
  if (compareList.value.length < 3) {
    const compareLimitMessage = ui.value.search?.compareLimitMessage || 'Compare up to 3 cars max.'
    if (aiCompareError.value === compareLimitMessage) {
      aiCompareError.value = ''
    }
  }
}

function openQuickView(car) {
  gamificationCar.value = car
  quickViewCar.value = null
  showGamification.value = true
  void replaceQueryWithoutScroll(buildSmartCarQuery(car))
}

function closeGamificationModal() {
  showGamification.value = false
  gamificationCar.value = null
  void replaceQueryWithoutScroll(buildSmartCarQuery(null))
}

async function closeQuickView() {
  quickViewCar.value = null
  if (Object.prototype.hasOwnProperty.call(route.query, 'scCar')) {
    const nextQuery = { ...route.query }
    delete nextQuery.scCar
    await replaceQueryWithoutScroll(nextQuery)
  }
}

function clearCompare() {
  compareList.value = []
  compareSelectedCars.value = []
  showCompareSummary.value = false
  aiCompareResult.value = null
  aiCompareError.value = ''
}

async function openCompareSummary() {
  if (!canRunCompare.value) {
    aiCompareError.value = ui.value.search?.compareLimitMessage || 'Select at least 2 cars to compare.'
    showCompareSummary.value = true
    return
  }

  console.log('[home compare] smart compare ids:', {
    compareList: [...compareList.value],
    compareCars: compareCars.value.map((car) => ({
      id: car?.id,
      compareKey: car?.compareKey,
      vehicleGroupId: car?.vehicleGroupId,
      name: car?.name,
    })),
    requestKeys: [...compareRequestKeys.value],
  })
  showCompareSummary.value = true
  await runAiCompare()
}

function closeCompareSummary() {
  showCompareSummary.value = false
}

function buildAiComparePayload() {
  const pickup = selectedPickupLocation.value
  const dropoff = selectedDropoffLocation.value || pickup
  const pickupAt = buildIsoDateTime(dateRange.value?.from, pickupTime.value)
  const dropoffAt = buildIsoDateTime(dateRange.value?.to, dropoffTime.value)

  const requestKeys = compareRequestKeys.value.slice(0, 3)

  return {
    compare_keys: requestKeys,
    pickup_location_id: pickup?.backendId || undefined,
    dropoff_location_id: dropoff?.backendId || pickup?.backendId || undefined,
    location_name: pickup?.name || undefined,
    location_code: pickup?.code || undefined,
    city: pickup?.city || pickup?.cityName || undefined,
    latitude: pickup?.latitude || pickup?.lat || undefined,
    longitude: pickup?.longitude || pickup?.lng || undefined,
    pickup_at: pickupAt,
    dropoff_at: dropoffAt,
    currency: currency.value,
    active_category: activeCategory.value !== 'all' ? activeCategory.value : undefined,
    return_to_same_location: returnToSameLocation.value,
    one_way: !returnToSameLocation.value,
    filters: {
      transmission: appliedFilters.transmission,
      deposit: appliedFilters.deposit,
      engine: appliedFilters.engine,
      payment: appliedFilters.payment,
      options: appliedFilters.options,
    },
    locale: locale.value,
  }
}

function normalizeCompareCar(car, compareKey = null, exactVehicleGroupId = null) {
  const resolvedVehicleGroupId = Number(exactVehicleGroupId || car?.vehicleGroupId || 0) || null

  return {
    id: compareKey ? String(compareKey) : (resolvedVehicleGroupId ? String(resolvedVehicleGroupId) : null),
    compareKey: compareKey ? String(compareKey) : null,
    vehicleGroupId: resolvedVehicleGroupId,
    name: car?.name || '',
    category: car?.category || '',
    price: Number(car?.price || 0) || 0,
    image: car?.image || '',
    rating: Number(car?.rating || 0) || 0,
    deposit: car?.deposit ?? null,
    paymentMethods: Array.isArray(car?.paymentMethods) ? [...car.paymentMethods] : [],
    featureKeys: Array.isArray(car?.featureKeys) ? [...car.featureKeys] : [],
    photosCount: Number(car?.photosCount || 0) || 0,
    specs: {
      seats: Number(car?.specs?.seats || 0) || null,
      transmission: car?.specs?.transmission || '',
      fuel: car?.specs?.fuel || '',
      driveType: car?.specs?.driveType || '',
    },
  }
}

async function runAiCompare() {
  if (!canRunCompare.value || aiCompareLoading.value) {
    return
  }

  const payload = buildAiComparePayload()

  console.log('[home compare] smart compare payload compare_keys:', payload.compare_keys)

  aiCompareLoading.value = true
  aiCompareError.value = ''

  try {
    const response = await $fetch(`${runtimeConfig.public.apiBaseUrl}/ai-compare/vehicles`, {
      method: 'POST',
      body: payload,
    })

    aiCompareResult.value = response?.data || response || null
  } catch (error) {
    aiCompareResult.value = null
    aiCompareError.value = resolvePublicApiError(error, 'AI compare failed. Try again.')
  } finally {
    aiCompareLoading.value = false
  }
}

function scrollToTop() {
  window.scrollTo({ top: 0, behavior: 'smooth' })
}

function generateCompareSummary(cars) {
  if (!Array.isArray(cars) || cars.length < 2) return ''
  const names = cars.map((car) => car.name)

  if (names.some((name) => name.includes('Range Rover')) && names.some((name) => name.includes('Fusion'))) {
    return 'Range Rover is cooler for status and mountains, but Fusion scales $100 for the weekend.'
  }

  if (names.some((name) => name.includes('Prius')) && names.some((name) => name.includes('Santa Fe'))) {
    return 'Santa Fe is ideal for large family and luggage, but Prius saves a ton of money on fuel and is easier to park in the city.'
  }

  return `${cars[0]?.name} is an excellent choice for comfort, but ${cars[1]?.name} has its advantages. Compare the price and decide what is more important!`
}

onMounted(() => {
  isLoading.value = false
  canSyncSearchStateToUrl.value = true

  document.addEventListener('mouseleave', handleMouseLeave)
  document.addEventListener('pointerdown', handleOutsideClick)
  window.addEventListener('scroll', handleScroll)
  ghostTimer = window.setTimeout(triggerGhostMessage, 10000)
})

onBeforeUnmount(() => {
  document.removeEventListener('mouseleave', handleMouseLeave)
  document.removeEventListener('pointerdown', handleOutsideClick)
  window.removeEventListener('scroll', handleScroll)
  if (ghostTimer) {
    clearTimeout(ghostTimer)
  }
  if (loadingTimer) {
    clearTimeout(loadingTimer)
  }
  if (weatherTimer) {
    clearTimeout(weatherTimer)
  }
})
</script>

<template>
  <motion.section
    :initial="{ opacity: 0, y: 18 }"
    :while-in-view="{ opacity: 1, y: 0 }"
    :viewport="{ once: true, margin: '-100px' }"
    :transition="{ duration: 0.4 }"
    class="relative z-20 pb-8 font-sans transition-colors duration-500 min-h-screen bg-transparent text-slate-900"
  >
    <div class="max-w-6xl mx-auto px-4 sm:px-6 relative z-10">
      <AnimatePresence>
        <motion.div
          v-if="liveBookingMessage"
          :initial="{ opacity: 0, x: -50, scale: 0.9 }"
          :animate="{ opacity: 1, x: 0, scale: 1 }"
          :exit="{ opacity: 0, x: -50, scale: 0.9 }"
          class="fixed bottom-6 left-6 z-[200] max-w-[300px]"
        >
          <div class="p-4 rounded-2xl shadow-2xl backdrop-blur-xl border flex items-start gap-3 bg-white/90 border-white shadow-brand-orange/10">
            <div class="w-8 h-8 rounded-full bg-brand-orange/20 flex items-center justify-center shrink-0 mt-0.5">
              <Flame class="w-4 h-4 text-brand-orange" />
            </div>
            <p class="text-sm font-semibold leading-snug text-slate-800">
              {{ liveBookingMessage }}
            </p>
          </div>
        </motion.div>
      </AnimatePresence>

      <AnimatePresence>
        <motion.div
          v-if="isScrolled"
          :initial="{ y: -100, opacity: 0 }"
          :animate="{ y: 20, opacity: 1 }"
          :exit="{ y: -100, opacity: 0 }"
          :transition="{ type: 'spring', stiffness: 400, damping: 25 }"
          class="fixed top-0 left-1/2 -translate-x-1/2 z-50 pointer-events-none w-full px-4 flex justify-center"
        >
          <div class="bg-white/90 backdrop-blur-md shadow-xl border border-white rounded-full py-2 px-4 flex items-center justify-center gap-3 sm:gap-4 pointer-events-auto max-w-fit mx-auto cursor-pointer" @click="scrollToTop">
            <div class="flex items-center gap-1.5 text-[13px] font-bold text-slate-800">
              <MapPin class="w-3.5 h-3.5 text-brand-orange" /> {{ pickupLocationLabel }}
            </div>
            <div class="w-1 h-1 rounded-full bg-slate-300" />
            <div class="flex items-center gap-1.5 text-[13px] font-bold text-slate-800">
              <Calendar class="w-3.5 h-3.5 text-slate-400" /> {{ dateRangeLabel }}
            </div>
            <div class="w-1 h-1 rounded-full bg-slate-300 hidden sm:block" />
            <div class="hidden sm:flex items-center gap-1.5 text-[13px] font-bold text-slate-800 bg-slate-100 px-2 py-0.5 rounded-full group">
              <Cog class="w-3.5 h-3.5 text-slate-400" /> Auto
            </div>
            <div class="w-8 h-8 rounded-full bg-brand-orange text-white flex items-center justify-center ml-1 shadow-sm hover:scale-105 transition-transform">
              <Search class="w-4 h-4" />
            </div>
          </div>
        </motion.div>
      </AnimatePresence>

      <div ref="searchBarRef" class="flex flex-col items-center justify-center w-full relative z-40 mt-4">
        <motion.div
          layout
          :initial="{ borderRadius: 32 }"
          :animate="{ borderRadius: 32 }"
          class="backdrop-blur-3xl shadow-[0_8px_30px_rgb(0,0,0,0.04)] w-full max-w-4xl origin-top relative bg-white/80 border border-white/60"
          :transition="{ type: 'spring', stiffness: 400, damping: 30 }"
        >
          <div class="flex flex-col sm:flex-row items-center p-1.5 gap-1 relative z-50">
            <div class="relative flex-1 w-full sm:w-auto">
              <button
                type="button"
                class="w-full hover:bg-black/5 p-3 sm:px-5 sm:py-3 rounded-[24px] transition-colors flex items-center gap-3 text-left"
                :class="activeDropdown === 'where' ? 'bg-white shadow-sm ring-1 ring-black/5' : ''"
                @click="toggleDropdown('where')"
              >
                <MapPin class="w-5 h-5 text-slate-400 shrink-0" />
                <div class="flex flex-col flex-1 min-w-0">
                  <span class="text-[10px] font-bold text-slate-400 flex items-center gap-1 uppercase tracking-widest leading-none mb-1">Where <ChevronDown class="w-3 h-3" /></span>
                  <span class="text-[14px] font-bold text-slate-900 leading-none truncate">{{ whereSummaryLabel }}</span>
                </div>
              </button>

              <AnimatePresence>
                <motion.div
                  v-if="activeDropdown === 'where'"
                  :initial="{ opacity: 0, y: 10 }"
                  :animate="{ opacity: 1, y: 0 }"
                  :exit="{ opacity: 0, y: 10 }"
                  class="absolute top-full left-0 mt-2 w-full sm:w-[720px] bg-white rounded-3xl shadow-xl border border-slate-100 overflow-hidden z-[100]"
                >
                  <div class="flex flex-col gap-0">
                    <div class="flex flex-col gap-3 border-b border-slate-100 p-4 sm:p-5">
                      <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
                        <div>
                          <div class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Select location</div>
                          <div class="text-sm font-semibold text-slate-900">{{ whereSummaryLabel || 'Choose pickup and drop-off' }}</div>
                        </div>
                        <button
                          type="button"
                          class="text-[10px] font-bold uppercase tracking-widest text-brand-orange hover:underline self-start sm:self-auto"
                          @click="setSameAsPickup"
                        >
                          Same as pickup
                        </button>
                      </div>
                    </div>

                    <div class="grid sm:grid-cols-2">
                      <div class="p-4 sm:p-5 border-b sm:border-b-0 sm:border-r border-slate-100">
                        <div class="text-[10px] font-bold text-slate-400 uppercase tracking-widest mb-3">Pickup location</div>
                        <div class="max-h-[320px] overflow-y-auto hide-scrollbar pr-1 space-y-4">
                          <div v-for="group in whereDropdownGroups" :key="`pickup-${group.key}`" class="space-y-2">
                            <div class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{{ group.label }}</div>
                            <div class="space-y-1">
                              <button
                                v-for="item in group.items"
                                :key="item.backendId"
                                type="button"
                                class="w-full text-left px-3 py-2 rounded-xl font-semibold text-sm transition-colors flex items-center justify-between gap-3"
                                :class="Number(selectedPickupLocation?.backendId || 0) === Number(item.backendId || 0) ? 'bg-brand-orange/10 text-brand-orange' : 'hover:bg-slate-50 text-slate-900'"
                                @click="setPickupLocation(item)"
                              >
                                <span class="min-w-0 flex flex-col">
                                  <span class="truncate">{{ item.name }}</span>
                                  <span class="text-[11px] font-medium text-slate-400 truncate">{{ item.city }} · {{ item.code }}</span>
                                </span>
                                <span
                                  class="w-2.5 h-2.5 rounded-full shrink-0"
                                  :class="Number(selectedPickupLocation?.backendId || 0) === Number(item.backendId || 0) ? 'bg-brand-orange' : 'bg-slate-200'"
                                />
                              </button>
                            </div>
                          </div>
                        </div>
                      </div>

                      <div class="p-4 sm:p-5">
                        <div class="text-[10px] font-bold text-slate-400 uppercase tracking-widest mb-3 flex items-center justify-between">
                          <span>Drop-off</span>
                          <button
                            v-if="!returnToSameLocation"
                            type="button"
                            class="text-brand-orange hover:underline text-[9px] pointer-events-auto"
                            @click="setSameAsPickup"
                          >
                            Same as pickup
                          </button>
                        </div>
                        <div class="max-h-[320px] overflow-y-auto hide-scrollbar pr-1 space-y-4">
                          <div v-for="group in whereDropdownGroups" :key="`dropoff-${group.key}`" class="space-y-2">
                            <div class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{{ group.label }}</div>
                            <div class="space-y-1">
                              <button
                                v-for="item in group.items"
                                :key="item.backendId"
                                type="button"
                                class="w-full text-left px-3 py-2 rounded-xl font-semibold text-sm transition-colors flex items-center justify-between gap-3"
                                :class="Number(selectedDropoffLocation?.backendId || 0) === Number(item.backendId || 0) ? 'bg-blue-500/10 text-blue-600' : 'hover:bg-slate-50 text-slate-600'"
                                @click="setDropoffLocation(item)"
                              >
                                <span class="min-w-0 flex flex-col">
                                  <span class="truncate">{{ item.name }}</span>
                                  <span class="text-[11px] font-medium text-slate-400 truncate">{{ item.city }} · {{ item.code }}</span>
                                </span>
                                <span
                                  class="w-2.5 h-2.5 rounded-full shrink-0"
                                  :class="Number(selectedDropoffLocation?.backendId || 0) === Number(item.backendId || 0) ? 'bg-blue-500' : 'bg-slate-200'"
                                />
                              </button>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>

                    <div class="p-4 sm:p-5 border-t border-slate-100">
                      <button type="button" class="w-full py-2.5 bg-slate-900 text-white rounded-xl text-xs font-bold hover:bg-slate-800 transition-colors" @click="applyRoute">
                        Apply Route
                      </button>
                    </div>
                  </div>
                </motion.div>
              </AnimatePresence>
            </div>

            <div class="hidden sm:block w-px h-8 bg-slate-200" />

            <div class="relative flex-1 w-full sm:w-auto">
              <button
                type="button"
                class="w-full hover:bg-black/5 p-3 sm:px-5 sm:py-3 rounded-[24px] transition-colors flex items-center gap-3 text-left"
                :class="activeDropdown === 'when' ? 'bg-white shadow-sm ring-1 ring-black/5' : ''"
                @click="toggleDropdown('when')"
              >
                <Calendar class="w-5 h-5 text-slate-400 shrink-0" />
                <div class="flex flex-col flex-1 min-w-0">
                  <span class="text-[10px] font-bold text-slate-400 flex items-center gap-1 uppercase tracking-widest leading-none mb-1">When <ChevronDown class="w-3 h-3" /></span>
                  <span class="text-[14px] font-bold text-slate-900 leading-none truncate">{{ dateRangeLabel }}</span>
                </div>
              </button>

              <AnimatePresence>
                <motion.div
                  v-if="activeDropdown === 'when'"
                  :initial="{ opacity: 0, y: 10 }"
                  :animate="{ opacity: 1, y: 0 }"
                  :exit="{ opacity: 0, y: 10 }"
                  class="absolute top-full left-1/2 -translate-x-1/2 mt-2 bg-white rounded-[24px] shadow-xl border border-slate-100 p-4 z-50 flex flex-col items-center w-max"
                >
                  <AppCalendar
                    mode="range"
                    :selected="dateRange"
                    :number-of-months="1"
                    :disabled="{ before: baseDay }"
                    class="font-sans"
                    @select="handleDateSelect"
                    @update:selected="handleDateSelect"
                    @update:model-value="handleDateSelect"
                  />
                  <div class="w-full flex justify-end mt-2">
                    <button type="button" class="px-5 py-2 bg-slate-900 text-white rounded-xl text-xs font-bold hover:bg-slate-800 transition-colors" @click="applyDates">
                      {{ calendarDoneLabel }}
                    </button>
                  </div>
                </motion.div>
              </AnimatePresence>
            </div>

            <div class="hidden sm:block w-px h-8 bg-slate-200" />

            <button
              type="button"
              @click="isExpanded = !isExpanded; closeDropdown()"
              :class="[
                'flex-1 sm:flex-none w-full sm:w-[160px] p-2 sm:p-2 rounded-[24px] transition-colors flex items-center gap-3 text-left justify-between',
                isExpanded ? 'bg-slate-900 text-white shadow-md' : 'hover:bg-black/5',
              ]"
            >
              <div class="flex items-center justify-center w-8 h-8 rounded-full bg-black/5 shrink-0 ml-1">
                <ListFilter class="w-4 h-4" :class="isExpanded ? 'text-white' : 'text-slate-600'" />
              </div>
              <div class="flex flex-col flex-1 min-w-0">
                <span :class="['text-[10px] font-bold uppercase tracking-widest leading-none mb-1', isExpanded ? 'text-white/60' : 'text-slate-400']">More</span>
                <span :class="['text-[14px] font-bold leading-none truncate', isExpanded ? 'text-white' : 'text-slate-900']">Filters</span>
              </div>

              <motion.div
                :animate="{ rotate: isExpanded ? 180 : 0 }"
                class="w-6 h-6 rounded-full flex items-center justify-center mr-2"
              >
                <ChevronDown class="w-4 h-4" :class="isExpanded ? 'text-white/80' : 'text-slate-400'" />
              </motion.div>
            </button>
          </div>

          <motion.div
            v-if="isExpanded"
            :initial="{ height: 0, opacity: 0 }"
            :animate="{ height: 'auto', opacity: 1 }"
            :exit="{ height: 0, opacity: 0 }"
            :transition="{ type: 'spring', bounce: 0.1, duration: 0.5 }"
            class="overflow-hidden"
          >
            <div class="p-6 pt-5 border-t border-slate-100/50 max-h-[70vh] overflow-y-auto hide-scrollbar flex flex-col">
              <div class="grid sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-x-8 gap-y-10 flex-1">
                <div class="space-y-3.5">
                  <div class="text-[10px] font-bold text-slate-400 tracking-widest uppercase">Transmission</div>
                  <div class="flex flex-wrap gap-2">
                    <button
                      v-for="item in transmissionFilterItems"
                      :key="item.key"
                      type="button"
                      :class="[
                        'relative px-4 py-2 rounded-full text-[13px] font-medium transition-all duration-300',
                        filters.transmission.includes(item.key) ? 'bg-slate-900 text-white shadow-md scale-105' : 'bg-black/5 hover:bg-black/10 text-slate-700',
                      ]"
                      @click="toggleFilter('transmission', item.key)"
                    >
                      <span class="relative z-10 flex items-center gap-1.5">
                        {{ item.label }}
                        <span :class="filters.transmission.includes(item.key) ? 'text-white/60' : 'text-slate-400'">{{ item.count }}</span>
                      </span>
                    </button>
                  </div>
                </div>

                <div class="space-y-3.5">
                  <div class="text-[10px] font-bold text-slate-400 tracking-widest uppercase">Deposit Options</div>
                  <div class="flex flex-wrap gap-2">
                    <button
                      v-for="item in depositFilterItems"
                      :key="item.key"
                      type="button"
                      :class="[
                        'relative px-4 py-2 rounded-full text-[13px] font-medium transition-all duration-300',
                        filters.deposit.includes(item.key) ? 'bg-slate-900 text-white shadow-md scale-105' : 'bg-black/5 hover:bg-black/10 text-slate-700',
                      ]"
                      @click="toggleFilter('deposit', item.key)"
                    >
                      <span class="relative z-10 flex items-center gap-1.5">
                        {{ item.label }}
                        <span :class="filters.deposit.includes(item.key) ? 'text-white/60' : 'text-slate-400'">{{ item.count }}</span>
                      </span>
                    </button>
                  </div>
                </div>

                <div class="space-y-3.5">
                  <div class="text-[10px] font-bold text-slate-400 tracking-widest uppercase">Engine & Drive</div>
                  <div class="flex flex-wrap gap-2">
                    <button
                      v-for="item in engineFuelFilterItems"
                      :key="item.key"
                      type="button"
                      :class="[
                        'relative px-4 py-2 rounded-full text-[13px] font-medium transition-all duration-300',
                        filters.engine.includes(item.key) ? 'bg-slate-900 text-white shadow-md scale-105' : 'bg-black/5 hover:bg-black/10 text-slate-700',
                      ]"
                      @click="toggleFilter('engine', item.key)"
                    >
                      <span class="relative z-10 flex items-center gap-1.5">
                        {{ item.label }}
                        <span :class="filters.engine.includes(item.key) ? 'text-white/60' : 'text-slate-400'">{{ item.count }}</span>
                      </span>
                    </button>
                    <div class="w-full h-px bg-slate-100 my-1" />
                    <button
                      v-for="item in engineDriveFilterItems"
                      :key="item.key"
                      type="button"
                      :class="[
                        'relative px-4 py-2 rounded-full text-[13px] font-medium transition-all duration-300',
                        filters.engine.includes(item.filterKey) ? 'bg-slate-900 text-white shadow-md scale-105' : 'bg-black/5 hover:bg-black/10 text-slate-700',
                      ]"
                      @click="toggleFilter('engine', item.filterKey)"
                    >
                      <span class="relative z-10 flex items-center gap-1.5">
                        {{ item.label }}
                        <span :class="filters.engine.includes(item.filterKey) ? 'text-white/60' : 'text-slate-400'">{{ item.count }}</span>
                      </span>
                    </button>
                  </div>
                </div>

                <div class="space-y-3.5">
                  <div class="text-[10px] font-bold text-slate-400 tracking-widest uppercase">Payment Method</div>
                  <div class="flex flex-wrap gap-2">
                    <button
                      v-for="item in paymentFilterItems"
                      :key="item.key"
                      type="button"
                      :class="[
                        'relative px-4 py-2 rounded-full text-[13px] font-medium transition-all duration-300',
                        filters.payment.includes(item.key) ? 'bg-slate-900 text-white shadow-md scale-105' : 'bg-black/5 hover:bg-black/10 text-slate-700',
                      ]"
                      @click="toggleFilter('payment', item.key)"
                    >
                      <span class="relative z-10 flex items-center gap-1.5">
                        {{ item.label }}
                        <span :class="filters.payment.includes(item.key) ? 'text-white/60' : 'text-slate-400'">{{ item.count }}</span>
                      </span>
                    </button>
                  </div>
                </div>

                <div class="space-y-3.5 sm:col-span-2">
                  <div class="text-[10px] font-bold text-slate-400 tracking-widest uppercase">Smart Options</div>
                  <div class="flex flex-wrap gap-2">
                    <button
                      v-for="item in smartOptionItems"
                      :key="item.key"
                      type="button"
                      :class="[
                        'relative px-4 py-2 rounded-full text-[13px] font-medium transition-all duration-300',
                        filters.options.includes(item.key) ? 'bg-slate-900 text-white shadow-md scale-105' : 'bg-black/5 hover:bg-black/10 text-slate-700',
                      ]"
                      @click="toggleFilter('options', item.key)"
                    >
                      <span class="relative z-10 flex items-center gap-1.5">
                        {{ item.label }}
                        <span :class="filters.options.includes(item.key) ? 'text-white/60' : 'text-slate-400'">{{ item.count }}</span>
                      </span>
                    </button>
                  </div>
                </div>

                <div class="space-y-3.5 sm:col-span-2">
                  <div class="text-[10px] font-bold text-slate-400 tracking-widest uppercase flex items-center gap-1.5">
                    <Sparkles class="w-3.5 h-3.5" /> Wow-Features
                  </div>
                  <div class="flex flex-wrap gap-2">
                    <button
                      v-for="item in wowFeatureItems"
                      :key="item.key"
                      type="button"
                      :class="[
                        'relative px-4 py-2 rounded-full text-[13px] font-medium transition-all duration-300',
                        filters.options.includes(item.key) ? 'bg-slate-900 text-white shadow-md scale-105' : 'bg-black/5 hover:bg-black/10 text-slate-700',
                      ]"
                      @click="toggleFilter('options', item.key)"
                    >
                      <span class="relative z-10 flex items-center gap-1.5">
                        {{ item.label }}
                        <span :class="filters.options.includes(item.key) ? 'text-white/60' : 'text-slate-400'">{{ item.count }}</span>
                      </span>
                    </button>
                  </div>
                </div>

              </div>

              <div class="sticky bottom-0 -mx-6 -mb-6 mt-8 p-6 pt-4 bg-gradient-to-t from-white/90 via-white/80 to-transparent backdrop-blur-md">
                <button type="button" class="w-full py-4 bg-slate-900 text-white rounded-[20px] font-semibold text-[15px] shadow-lg shadow-slate-900/20 hover:scale-[1.01] active:scale-[0.99] transition-transform flex items-center justify-center gap-2" @click="applyCatalogFilters">
                  <Search class="w-4 h-4" /> {{ showVehiclesLabel }}
                </button>
              </div>
            </div>
          </motion.div>
        </motion.div>
      </div>

      <div class="max-w-6xl mx-auto mt-6 mb-6 overflow-hidden">
        <div class="flex items-center justify-start sm:justify-center gap-2.5 sm:gap-3 overflow-x-auto pb-4 px-4 sm:px-6 hide-scrollbar mask-edges">
          <button
            v-for="category in categories"
            :key="category.id"
            type="button"
            @click="selectCategory(category.id)"
            :class="[
              'group inline-flex flex-shrink-0 items-center justify-center gap-2 rounded-full px-5 py-2.5 text-[13px] font-medium transition-all duration-200 border active:scale-95 cursor-pointer shadow-md',
              activeCategory === category.id ? 'bg-slate-700 text-white border-slate-700 shadow-lg' : 'bg-white/40 text-slate-700 border-white hover:bg-white/60',
            ]"
          >
            <component
              :is="category.icon"
              class="w-4 h-4 sm:w-4 sm:h-4 transition-colors duration-300"
              :class="[
                activeCategory === category.id
                  ? 'text-white'
                  : category.tone === 'orange'
                    ? 'text-orange-500 group-hover:text-orange-600'
                    : category.tone === 'purple'
                      ? 'text-purple-500 group-hover:text-purple-600'
                      : 'text-slate-400 group-hover:text-slate-600',
              ]"
              stroke-width="2"
            />
            <span>{{ category.label }}</span>
          </button>
        </div>
      </div>

      <motion.div
        v-if="aiMode"
        :initial="{ height: 0, opacity: 0, y: -10 }"
        :animate="{ height: 'auto', opacity: 1, y: 0 }"
        :exit="{ height: 0, opacity: 0, y: -10 }"
        class="max-w-3xl mx-auto px-4 sm:px-6 mb-8 overflow-hidden transition-all duration-700"
      >
        <div class="border rounded-[32px] p-2 flex flex-col gap-2 shadow-inner relative overflow-hidden transition-all duration-700 bg-brand-orange/5 border-brand-orange/20 shadow-brand-orange/5">
          <div class="flex items-center gap-3 relative z-10">
            <div class="w-12 h-12 rounded-full bg-brand-orange text-white flex items-center justify-center shrink-0 shadow-md">
              <Sparkles class="w-5 h-5" />
            </div>
            <input
              v-model="aiQuery"
              type="text"
              placeholder="e.g. I need a cheap SUV to go to Kazbegi tomorrow..."
              @input="handleAiQueryInput"
              @keydown.enter.prevent="runAiSearch"
              class="flex-1 bg-transparent border-none outline-none font-medium placeholder:font-normal text-[15px] sm:text-[17px] pr-4 h-full min-h-[48px] text-slate-900 placeholder:text-slate-400"
            >
            <button
              v-if="aiQuery"
              type="button"
              :disabled="aiSearchLoading"
              class="absolute right-4 px-5 py-2.5 bg-brand-orange text-white text-sm font-bold rounded-full shadow-[0_0_15px_rgba(255,107,0,0.5)] hover:scale-105 transition-transform hidden sm:block disabled:opacity-60 disabled:cursor-not-allowed"
              @click="runAiSearch"
            >
              {{ aiSearchLoading ? 'Searching...' : 'Search' }}
            </button>
          </div>

          <div v-if="aiSearchError" class="px-3 sm:px-[60px] text-[12px] font-medium text-rose-500 relative z-10">
            {{ aiSearchError }}
          </div>

          <div
            v-if="normalizedAiSearchExplanation"
            class="mx-2 sm:mx-[60px] rounded-2xl border border-slate-200 bg-white/80 px-4 py-3 text-slate-700 relative z-10"
          >
            <div class="flex items-center gap-2 mb-1.5 text-[10px] font-bold uppercase tracking-[0.22em] text-brand-orange">
              <Sparkles class="w-3.5 h-3.5" />
              AI explanation
            </div>
            <p class="text-[13px] leading-relaxed whitespace-pre-line">
              {{ normalizedAiSearchExplanation }}
            </p>
          </div>

          <div class="flex flex-wrap gap-2 pl-3 sm:pl-[60px] pb-1 relative z-10">
            <button
              v-for="item in aiQuickPromptItems"
              :key="item.key"
              type="button"
              class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full border hover:shadow-sm transition-all text-[12px] font-semibold bg-white/80 border-brand-orange/10 text-slate-700"
              @click="handleAiPrompt(item.key)"
            >
              {{ item.icon }} {{ item.label }}
            </button>
          </div>
        </div>
      </motion.div>

      <div v-if="canShowWeatherForecast && (hasWeatherForecast || weatherLoading)" class="max-w-6xl mx-auto px-4 sm:px-6 mb-4">
        <div class="group flex flex-col sm:flex-row items-start sm:items-center gap-3 rounded-[18px] border border-white/70 bg-white/55 px-4 py-3 shadow-sm backdrop-blur-md transition-all duration-300 hover:bg-white/70">
          <div class="w-9 h-9 rounded-full flex items-center justify-center shrink-0 transition-colors duration-300 bg-slate-900 text-white shadow-sm">
            <CloudRain class="w-4 h-4" />
          </div>
          <div class="flex-1 min-w-0">
            <div class="flex flex-wrap items-center gap-2 mb-0.5">
              <span class="text-[10px] font-bold uppercase tracking-[0.2em] text-brand-orange">Smart trip check</span>
              <h4 class="text-[14px] font-bold tracking-tight text-slate-900">
                {{ weatherInsightTitle }}
              </h4>
            </div>
            <p class="text-[12px] font-medium leading-relaxed text-slate-500">
              {{ weatherInsightText }}
            </p>
          </div>
          <div v-if="weatherBadges.length" class="hidden shrink-0 flex-wrap justify-end gap-1.5 md:flex md:max-w-[220px] lg:max-w-[280px]">
            <span
              v-for="badge in weatherBadges"
              :key="badge.key"
              class="inline-flex items-center rounded-full px-2 py-0.5 text-[9px] font-bold uppercase tracking-widest whitespace-nowrap"
              :class="badge.className"
            >
              {{ badge.label }}
            </span>
          </div>
          <button
            type="button"
            class="group/btn relative overflow-hidden rounded-full bg-slate-900 px-4 py-2 text-[10px] font-bold uppercase tracking-widest text-white shadow-sm transition-all duration-300 hover:-translate-y-0.5 hover:bg-slate-800 shrink-0 flex items-center justify-center gap-2"
            @click="handleAwdQuickAction"
          >
            <span class="relative z-10">Show AWD / 4x4</span>
            <ChevronDown class="w-3.5 h-3.5 -rotate-90 group-hover/btn:translate-x-1 transition-transform relative z-10" />
          </button>
        </div>
      </div>

      <div class="max-w-6xl mx-auto px-4 sm:px-6">
        <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6">
          <div class="flex flex-wrap items-center gap-4">
            <h2 class="text-[22px] font-bold tracking-tight text-slate-900">{{ featuredLabel }}</h2>
            <div class="hidden sm:flex items-center gap-1.5 px-3 py-1 bg-brand-orange text-white text-xs font-bold rounded-full shadow-[0_0_10px_rgba(255,107,0,0.3)]">
              <Tag class="w-3.5 h-3.5" /> {{ bestValueLabel }}
            </div>
          </div>

          <div class="flex items-center gap-3 sm:gap-4 overflow-x-auto pb-2 sm:pb-0 hide-scrollbar mask-edges-right">
            <select v-model="sortMode" class="px-3 py-2 sm:px-0 sm:py-0 rounded-xl text-sm font-semibold cursor-pointer outline-none transition-colors border-none shrink-0 bg-slate-50 sm:bg-transparent text-slate-700 hover:text-slate-900">
              <option value="recommended">{{ sortRecommendedLabel }}</option>
              <option value="price-low">{{ sortPriceLowLabel }}</option>
              <option value="price-high">{{ sortPriceHighLabel }}</option>
              <option value="rating">{{ sortRatingLabel }}</option>
            </select>

          </div>
        </div>

        <div v-if="activeFilterBadgeGroups.length" class="mb-5 flex flex-wrap items-center gap-2">
          <div
            v-for="group in activeFilterBadgeGroups"
            :key="group.key"
            class="flex flex-wrap items-center gap-1.5"
          >
            <div class="text-[9px] font-bold uppercase tracking-[0.22em] text-slate-400 pr-1">
              {{ group.label }}
            </div>
            <button
              v-for="item in group.items"
              :key="item.key"
              type="button"
              class="group inline-flex items-center gap-1 rounded-full bg-white/60 border border-white px-2.5 py-1 text-[10px] font-semibold text-slate-800 backdrop-blur-sm transition-all hover:scale-[1.02] hover:bg-brand-orange hover:text-white hover:border-brand-orange active:scale-[0.98]"
              @click="item.onRemove"
            >
              <span class="max-w-[120px] truncate">{{ item.label }}</span>
              <X class="h-3 w-3 text-slate-400 group-hover:text-white" />
            </button>
          </div>
          <button
            type="button"
            class="text-[9px] font-bold uppercase tracking-widest text-slate-500 hover:text-slate-900 transition-colors"
            @click="clearAllFilterBadges"
          >
            Clear all
          </button>
        </div>

        <div v-if="showNoCarsState" class="rounded-[32px] bg-white/70 backdrop-blur-3xl border border-white/80 px-8 py-16 text-center shadow-[0_20px_60px_-15px_rgba(0,0,0,0.05)]">
          <h3 class="text-3xl font-display font-bold text-slate-900 mb-3">{{ noCarsLabel }}</h3>
          <p class="text-slate-500 max-w-xl mx-auto">Change filters and try again.</p>
        </div>

        <div v-else class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-x-6 gap-y-10">
          <template v-if="isCatalogLoading">
            <div
              v-for="i in 8"
              :key="i"
              class="bg-white rounded-[32px] overflow-hidden shadow-[0_15px_40px_-15px_rgba(0,0,0,0.05)] border border-slate-100 flex flex-col h-[420px] animate-pulse"
            >
              <div class="relative h-[220px] bg-slate-100 w-full overflow-hidden shrink-0" />
              <div class="p-6 flex flex-col flex-1">
                <div class="flex justify-between items-start mb-3 gap-4">
                  <div class="w-2/3">
                    <div class="h-5 bg-slate-200 rounded-md w-full mb-2" />
                    <div class="h-4 bg-slate-100 rounded-md w-1/2" />
                  </div>
                  <div class="h-6 w-12 bg-slate-100 rounded-full shrink-0" />
                </div>
                <div class="flex gap-2 mb-auto pb-4 border-b border-slate-100">
                  <div class="h-5 w-16 bg-slate-100 rounded-full" />
                  <div class="h-5 w-16 bg-slate-100 rounded-full" />
                  <div class="h-5 w-16 bg-slate-100 rounded-full" />
                </div>
                <div class="flex items-center justify-between pt-4 mt-auto">
                  <div class="flex flex-col gap-1">
                    <div class="h-3 w-10 bg-slate-100 rounded-sm" />
                    <div class="h-6 w-20 bg-slate-200 rounded-md" />
                  </div>
                  <div class="h-12 w-12 bg-slate-100 rounded-full" />
                </div>
              </div>
            </div>
          </template>

          <template v-else>
            <SimpleCarListCard
              v-for="car in visibleCars"
              :key="car.id"
              :car="car"
              :is-compared="compareList.includes(resolveCompareSelectionKey(car))"
              :locale="locale"
              @open="openQuickView"
              @compare="toggleCompare"
            />
          </template>
        </div>

        <div v-if="!isCatalogLoading" class="mt-24 mb-20 flex flex-col items-center w-full max-w-sm mx-auto">
          <div class="font-medium text-[13px] text-slate-500 mb-3 flex items-center gap-2">
            You viewed <span class="font-bold text-slate-900">{{ visibleCars.length }}</span> of <span class="font-bold text-slate-900">{{ filteredCars.length }}</span> cars
          </div>

          <div class="w-full h-1 bg-slate-100 rounded-full mb-10 overflow-hidden relative shadow-inner">
            <div
              class="absolute top-0 left-0 h-full bg-slate-900 transition-all duration-[1.5s] ease-[cubic-bezier(0.2,0.8,0.2,1)] rounded-full"
              :style="{ width: `${filteredCars.length ? (visibleCars.length / filteredCars.length) * 100 : 0}%` }"
            />
          </div>

          <button
            v-if="hasMoreCars"
            type="button"
            @click="loadMoreCars"
            class="relative group overflow-hidden w-full bg-slate-900 text-white font-medium py-4 rounded-xl shadow-[0_10px_40px_rgba(0,0,0,0.15)] hover:shadow-[0_15px_50px_rgba(0,0,0,0.25)] transition-all duration-500 flex items-center justify-center gap-3 text-[14px] hover:-translate-y-1"
          >
            <div class="absolute inset-0 bg-gradient-to-r from-transparent via-white/10 to-transparent translate-x-[-100%] group-hover:translate-x-[100%] transition-transform duration-1000 ease-in-out" />
            <span class="relative z-10 font-bold uppercase tracking-widest text-[11px] flex items-center gap-2">
              {{ showMoreLabel }}
              <div class="w-5 h-5 rounded-full bg-white/20 flex items-center justify-center group-hover:bg-white text-white group-hover:text-slate-900 transition-colors">
                <ChevronDown class="w-3.5 h-3.5 group-hover:translate-y-0.5 transition-transform" />
              </div>
            </span>
          </button>
        </div>
      </div>
    </div>

    <SimpleCarListCompareDock
      :compare-cars="compareCars"
      :can-run-compare="canRunCompare"
      :compare-summary="compareSummary"
      :compare-loading="aiCompareLoading"
      :compare-error="aiCompareError"
      :show-compare-summary="showCompareSummary"
      @clear="clearCompare"
      @toggle-summary="openCompareSummary"
      @close-summary="closeCompareSummary"
      @continue-booking="closeCompareSummary"
    />

    <SimpleCarListQuickViewModal
      :car="quickViewCarWithLiveAvailability"
      :all-cars="catalogCars"
      :insurance-options="liveCatalogExtras"
      :location="pickupLocationLabel"
      :pickup-location="selectedPickupLocation"
      :dropoff-location="selectedDropoffLocation"
      :booking-payload="quickViewBookingPayload"
      @close="closeQuickView"
    />

    <SimpleCarListGamificationModal
      :open="showGamification"
      :car="gamificationCar"
      :insurance-options="liveCatalogExtras"
      @close="closeGamificationModal"
    />
  </motion.section>
</template>
