<script setup>
import { motion } from 'motion-v'
import {
  AlertCircle,
  ArrowLeft,
  Baby,
  Calendar,
  Car,
  Check,
  CheckCircle2,
  Clock,
  CreditCard,
  Info,
  Package,
  Settings2,
  Shield,
  ShieldAlert,
  ShieldCheck,
  Snowflake,
  Sparkles,
  UserPlus,
  Users,
  Wifi,
} from 'lucide-vue-next'
import OfferContextBanner from '~/components/offers/OfferContextBanner.vue'
import { buildSearchScarcity, resolveSearchMarketingBadgeLabel } from '~/constants/search-ui'
import {
  formatPublicDateTime,
  formatPublicDayCount,
  formatPublicMoney,
  formatPublicQuoteLineLabel,
  formatPublicSeatCount,
  localizePublicFuel,
  localizePublicTransmission,
  localizePublicVehicleCategory,
  resolvePublicApiError,
  resolvePublicAssetUrl,
} from '~/content/utils'
import { resolveOfferPricingTierForDays } from '~/content/offer-pricing'
import { resolveOfferForVehicleGroupId, useOffersContent } from '~/content/offers'
import { buildExtrasPayload, buildExtrasQuery, parseExtrasQuery } from '~/utils/public-booking-extras'
import { buildRentCheckoutRoute, buildRentSearchRoute } from '~/utils/public-routes'

const props = defineProps({
  vehicleGroupId: {
    type: [Number, String],
    default: null,
  },
})

const route = useRoute()
const runtimeConfig = useRuntimeConfig()
const offersContent = useOffersContent()
const { currency } = usePublicPreferences()
const { locale } = usePublicLocale()
const ui = usePublicUi()
const { activeOfferSlug } = usePublicOfferContext()
const { buildCatalogPayload, fetchCatalog, parseSearchQuery } = useSearchCatalog()
const { fetchQuote } = usePublicBooking()

const catalogExtras = ref([])
const isLoadingCatalog = ref(false)
const isLoadingQuote = ref(false)
const catalogError = ref('')
const quoteError = ref('')
const quoteRefreshError = ref('')
const quoteData = ref(null)
const selectedExtraIds = ref(parseExtrasQuery(route.query.extras))
const quoteRequestId = ref(0)
const hasAppliedPrefillExtra = ref(false)
const offerCards = computed(() => offersContent.offerCards.value || [])
const resolvedOfferBySlug = offersContent.useResolvedOffer(activeOfferSlug)
const activeOffer = computed(() => {
  if (resolvedOfferBySlug.value) {
    return resolvedOfferBySlug.value
  }

  return resolveOfferForVehicleGroupId(offerCards.value, Number(props.vehicleGroupId || 0))
})

function parsePrefillExtraCodes(value) {
  if (Array.isArray(value)) {
    return value
      .flatMap((entry) => String(entry || '').split(','))
      .map((entry) => entry.trim())
      .filter(Boolean)
  }

  return String(value || '')
    .split(',')
    .map((entry) => entry.trim())
    .filter(Boolean)
}

const extraIcons = {
  baby: Baby,
  driver: UserPlus,
  package: Package,
  shield: ShieldAlert,
  'shield-check': ShieldCheck,
  snowflake: Snowflake,
  wifi: Wifi,
}

const hasRequiredTripQuery = computed(() => {
  return Boolean(route.query.pickupLocationId && route.query.pickupAt && route.query.dropoffAt)
})

const resolvedVehicleGroupId = computed(() => {
  const numericId = Number(props.vehicleGroupId || 0)
  return numericId > 0 ? numericId : null
})

const parsedTrip = computed(() => {
  if (!hasRequiredTripQuery.value) {
    return null
  }

  return parseSearchQuery(route.query)
})

const catalogPayload = computed(() => {
  if (!resolvedVehicleGroupId.value || !parsedTrip.value) {
    return null
  }

  return buildCatalogPayload({
    pickupLocationId: Number(route.query.pickupLocationId),
    dropoffLocationId: Number(route.query.dropoffLocationId || route.query.pickupLocationId),
    pickupDate: parsedTrip.value.pickupDate,
    dropoffDate: parsedTrip.value.dropoffDate,
    pickupTime: parsedTrip.value.pickupTime,
    dropoffTime: parsedTrip.value.dropoffTime,
    currency: currency.value,
    promoCode: String(route.query.promoCode || ''),
    offerSlug: activeOffer.value?.slug || activeOfferSlug.value || undefined,
  })
})

const quotePayload = computed(() => {
  if (!catalogPayload.value || !resolvedVehicleGroupId.value) {
    return null
  }

  return {
    ...catalogPayload.value,
    vehicle_group_id: resolvedVehicleGroupId.value,
    extras: buildExtrasPayload(selectedExtraIds.value),
    offer_slug: activeOffer.value?.slug || activeOfferSlug.value || undefined,
  }
})

const quoteGroup = computed(() => quoteData.value?.group || quoteData.value || null)
const quoteSummary = computed(() => quoteData.value?.quote || null)
const offerPricingTier = computed(() => resolveOfferPricingTierForDays(activeOffer.value || {}, Number(quoteSummary.value?.days || 0)))
const summaryLines = computed(() => {
  return (quoteSummary.value?.lines || [])
    .filter((line) => Number(line?.amount || 0) !== 0)
    .map((line) => {
      const amount = String(line?.code || '').trim() === 'rental' && offerPricingTier.value?.newPrice
        ? Number(offerPricingTier.value.newPrice || 0) * Number(quoteSummary.value?.days || 0)
        : Number(line?.amount || 0)
      const lineForLabel = {
        ...line,
        amount,
        unitAmount: String(line?.code || '').trim() === 'rental' && offerPricingTier.value?.newPrice
          ? Number(offerPricingTier.value.newPrice || 0)
          : Number(line?.unitAmount || line?.amount || 0),
      }

      return {
        ...lineForLabel,
        localizedLabel: formatPublicQuoteLineLabel(lineForLabel, {
          locale: locale.value,
          currencyCode: quoteSummary.value?.currency || quoteGroup.value?.currency || 'USD',
          days: quoteSummary.value?.days || 0,
        }),
      }
    })
})
const currencyCode = computed(() => quoteSummary.value?.currency || quoteGroup.value?.currency || 'USD')
const selectedExtrasSet = computed(() => new Set(selectedExtraIds.value))
const includedExtras = computed(() => catalogExtras.value.filter((item) => item.pricingType === 'included' || item.group === 'included'))
const selectableExtras = computed(() => catalogExtras.value.filter((item) => item.pricingType !== 'included' && item.group !== 'included'))
const blockingError = computed(() => catalogError.value || quoteError.value)
const isBootstrapping = computed(() => {
  return (!quoteSummary.value || !quoteGroup.value) && (isLoadingCatalog.value || isLoadingQuote.value)
})
const isRefreshingQuote = computed(() => isLoadingQuote.value && !!quoteSummary.value && !!quoteGroup.value)
const vehicleImage = computed(() => {
  return resolvePublicAssetUrl(
    quoteGroup.value?.imageUrl
    || quoteGroup.value?.vehicle?.imageUrl
    || '',
    runtimeConfig.public.apiBaseUrl,
  )
})
const vehicleName = computed(() => {
  const make = quoteGroup.value?.model?.make || quoteGroup.value?.vehicle?.make || ''
  const model = quoteGroup.value?.model?.name || quoteGroup.value?.vehicle?.model || quoteGroup.value?.name || ''

  return [make, model].filter(Boolean).join(' ').trim() || ui.value.checkout.selectedVehicle
})
const heroCategoryLabel = computed(() => localizePublicVehicleCategory(quoteGroup.value?.category, locale.value))
const heroMarketingBadge = computed(() => {
  const category = heroCategoryLabel.value.toLowerCase()
  const marketingBadge = String(resolveSearchMarketingBadgeLabel(quoteGroup.value, ui.value.search || {}) || '').trim()

  if (!marketingBadge) {
    return ''
  }

  return marketingBadge.toLowerCase() === category ? '' : marketingBadge
})
const vehicleSpecs = computed(() => [
  {
    key: 'seats',
    value: formatPublicSeatCount(quoteGroup.value?.model?.seats || quoteGroup.value?.seats, locale.value),
    icon: Users,
  },
  {
    key: 'transmission',
    value: localizePublicTransmission(quoteGroup.value?.model?.transmission || quoteGroup.value?.transmission, locale.value),
    icon: Settings2,
  },
  {
    key: 'fuel',
    value: localizePublicFuel(quoteGroup.value?.model?.powertrain || quoteGroup.value?.fuelType, locale.value),
    icon: Car,
  },
].filter((item) => item.value))
const pickupLabel = computed(() => {
  if (!parsedTrip.value?.pickupDateTime) {
    return ui.value.extras.pickup
  }

  return formatPublicDateTime(parsedTrip.value.pickupDateTime, locale.value)
})
const dropoffLabel = computed(() => {
  if (!parsedTrip.value?.dropoffDateTime) {
    return ui.value.extras.dropoff
  }

  return formatPublicDateTime(parsedTrip.value.dropoffDateTime, locale.value)
})
const totalDays = computed(() => Number(quoteSummary.value?.days || 0))
const totalDaysLabel = computed(() => formatPublicDayCount(totalDays.value, locale.value, 'extras.dayTotalTemplate'))
const offerDiscountLabel = computed(() => {
  return String(activeOffer.value?.discount || '').trim()
})
const offerDiscountPercent = computed(() => {
  const match = offerDiscountLabel.value.match(/(\d+(?:\.\d+)?)/)
  const numericValue = Number(match?.[1] || 0)

  return numericValue > 0 ? numericValue : null
})
const currentDailyRate = computed(() => {
  return Number(offerPricingTier.value?.newPrice || quoteGroup.value?.pricePerDay || quoteSummary.value?.dailyRate || 0)
})
const offerReferenceDailyPrice = computed(() => {
  if (offerPricingTier.value?.oldPrice && offerPricingTier.value.oldPrice > currentDailyRate.value) {
    return Number(offerPricingTier.value.oldPrice)
  }

  if (!offerDiscountPercent.value || currentDailyRate.value <= 0 || offerDiscountPercent.value >= 100) {
    return null
  }

  const referenceRate = currentDailyRate.value / (1 - (offerDiscountPercent.value / 100))

  if (!Number.isFinite(referenceRate) || referenceRate <= currentDailyRate.value) {
    return null
  }

  return referenceRate
})
const demandMessage = computed(() => {
  const localizedScarcity = buildSearchScarcity({
    availableCount: Number(quoteGroup.value?.availableCount || 0),
    available: Boolean(quoteGroup.value?.available ?? true),
    reasonCode: quoteGroup.value?.reasonCode || null,
    reason: quoteGroup.value?.reason || null,
  }, ui.value.search || {})

  if (localizedScarcity) {
    return localizedScarcity
  }

  const bookedToday = Number(quoteGroup.value?.demandSignals?.bookedToday || 0)

  if (bookedToday > 0) {
    return ui.value.search.bookedToday
      .replace('{count}', String(bookedToday))
      .replace('{suffix}', bookedToday === 1 ? '' : 's')
  }

  return ui.value.checkout.availabilityChecked
})
const selectedExtrasCountLabel = computed(() => ui.value.extras.selectedTemplate.replace('{count}', String(selectedExtraIds.value.length)))
const quoteDepositAmount = computed(() => Number(quoteSummary.value?.depositAmount || 0))
const quoteFinalTotal = computed(() => summaryLines.value.reduce((total, line) => total + Number(line?.amount || 0), 0))
const depositLabel = computed(() => {
  const amount = quoteDepositAmount.value

  if (amount > 0) {
    return formatMoney(amount, currencyCode.value)
  }

  return ui.value.extras.noDeposit
})

function formatMoney(amount, currencyValue) {
  return formatPublicMoney(amount, currencyValue || 'USD', locale.value)
}

function isExtraSelected(extraId) {
  return selectedExtrasSet.value.has(Number(extraId))
}

async function syncExtrasQuery(nextExtraIds) {
  const extras = buildExtrasQuery(nextExtraIds)
  
  if (!import.meta.client) {
    return
  }

  const nextUrl = new URL(window.location.href)

  if (extras) {
    nextUrl.searchParams.set('extras', extras)
  } else {
    nextUrl.searchParams.delete('extras')
  }

  nextUrl.searchParams.delete('prefillExtra')
  nextUrl.searchParams.delete('prefillExtras')

  window.history.replaceState(window.history.state, '', `${nextUrl.pathname}${nextUrl.search}${nextUrl.hash}`)
}

async function toggleExtra(extraId) {
  const numericId = Number(extraId || 0)

  if (numericId <= 0) {
    return
  }

  const nextIds = isExtraSelected(numericId)
    ? selectedExtraIds.value.filter((item) => item !== numericId)
    : [...selectedExtraIds.value, numericId]

  selectedExtraIds.value = nextIds
  syncExtrasQuery(nextIds)
}

async function proceedToCheckout() {
  await navigateTo(buildRentCheckoutRoute(resolvedVehicleGroupId.value, {
    ...route.query,
    extras: buildExtrasQuery(selectedExtraIds.value),
  }, {
    locale: locale.value,
  }))
}

async function loadCatalogExtras() {
  if (import.meta.server) {
    return
  }

  if (!catalogPayload.value) {
    return
  }

  isLoadingCatalog.value = true
  catalogError.value = ''

  try {
    const catalog = await fetchCatalog(catalogPayload.value)
    catalogExtras.value = Array.isArray(catalog.extras) ? catalog.extras : []
  } catch (error) {
    console.error('Failed to load extras catalog', error)
    catalogExtras.value = []
    catalogError.value = resolvePublicApiError(error, ui.value.extras.couldNotLoad, locale.value)
  } finally {
    isLoadingCatalog.value = false
  }
}

async function loadQuote() {
  if (import.meta.server) {
    return
  }

  if (!quotePayload.value) {
    return
  }

  isLoadingQuote.value = true
  quoteRefreshError.value = ''
  const currentRequestId = quoteRequestId.value + 1
  quoteRequestId.value = currentRequestId

  try {
    const nextQuote = await fetchQuote(quotePayload.value)

    if (currentRequestId !== quoteRequestId.value) {
      return
    }

    quoteData.value = nextQuote
    quoteError.value = ''
  } catch (error) {
    console.error('Failed to load extras quote', error)
    if (currentRequestId !== quoteRequestId.value) {
      return
    }

    const message = resolvePublicApiError(error, ui.value.extras.couldNotPrepare, locale.value)

    if (!quoteData.value) {
      quoteError.value = message
      quoteData.value = null
    } else {
      quoteRefreshError.value = message
    }
  } finally {
    if (currentRequestId === quoteRequestId.value) {
      isLoadingQuote.value = false
    }
  }
}

watch(
  () => route.query.extras,
  (value) => {
    const parsed = parseExtrasQuery(value)

    if (JSON.stringify(parsed) !== JSON.stringify(selectedExtraIds.value)) {
      selectedExtraIds.value = parsed
    }
  },
  { immediate: true },
)

watch(
  [catalogExtras, () => route.query.prefillExtra, () => route.query.prefillExtras, () => route.query.extras],
  async () => {
    if (hasAppliedPrefillExtra.value || route.query.extras || !catalogExtras.value.length) {
      return
    }

    const requestedCodes = [
      ...parsePrefillExtraCodes(route.query.prefillExtras),
      ...parsePrefillExtraCodes(route.query.prefillExtra),
    ]

    if (!requestedCodes.length) {
      return
    }

    hasAppliedPrefillExtra.value = true
    const nextIds = [
      ...new Set([
        ...selectedExtraIds.value,
        ...requestedCodes
          .map((requestedCode) => {
            const matchedExtra = catalogExtras.value.find((item) => {
              return String(item.code || item.id || '').trim() === requestedCode
            })

            return Number(matchedExtra?.id || 0)
          })
          .filter((id) => id > 0),
      ]),
    ]

    selectedExtraIds.value = nextIds
    await syncExtrasQuery(nextIds)
  },
  { immediate: true },
)

watch(
  catalogPayload,
  async () => {
    if (!catalogPayload.value) {
      return
    }

    await loadCatalogExtras()
  },
  { immediate: true },
)

watch(
  quotePayload,
  async () => {
    if (!quotePayload.value) {
      return
    }

    await loadQuote()
  },
  { immediate: true },
)
</script>

<template>
  <div class="min-h-screen text-slate-900 font-sans relative selection:bg-brand-orange/30 pb-24">
    <div class="absolute inset-0 overflow-hidden pointer-events-none">
      <div class="absolute top-[-10%] left-[-10%] w-[60vw] h-[60vw] bg-brand-orange/10 blur-[120px] rounded-full" />
      <div class="absolute bottom-[-10%] right-[-10%] w-[50vw] h-[50vw] bg-blue-500/10 blur-[120px] rounded-full" />
    </div>

    <main class="container mx-auto px-4 max-w-7xl pt-8 md:pt-10 relative z-10">
      <div class="flex items-center justify-between gap-4 mb-8">
        <NuxtLink
          :to="buildRentSearchRoute(route.query, { locale })"
          class="inline-flex items-center gap-3 text-slate-600 hover:text-slate-900 font-medium transition-all group"
        >
          <div class="w-10 h-10 rounded-full bg-white/70 backdrop-blur-md border border-white/80 shadow-sm flex items-center justify-center group-hover:bg-white group-hover:scale-105 transition-all">
            <ArrowLeft class="w-5 h-5" />
          </div>
          <span class="tracking-wide">{{ ui.common.backToSearch }}</span>
        </NuxtLink>

        <div class="hidden sm:inline-flex items-center gap-2 px-4 py-2 rounded-full bg-white/70 backdrop-blur-md border border-white/80 shadow-sm">
          <Sparkles class="w-4 h-4 text-brand-orange" />
          <span class="text-xs font-bold uppercase tracking-wider text-slate-700">{{ ui.common.customizeExtras }}</span>
        </div>
      </div>

      <div v-if="!hasRequiredTripQuery || !resolvedVehicleGroupId || blockingError" class="max-w-2xl mx-auto">
        <div class="bg-white/70 backdrop-blur-2xl rounded-[2.5rem] p-8 md:p-12 shadow-[0_8px_30px_rgb(0,0,0,0.04)] border border-white/50">
          <div class="inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-red-50 text-red-500 text-xs font-bold uppercase tracking-widest mb-4">
            <AlertCircle class="w-3.5 h-3.5" />
            {{ ui.extras.extrasUnavailable }}
          </div>
          <h1 class="text-3xl font-display font-bold text-slate-900 mb-3">{{ ui.extras.couldNotPrepareTitle }}</h1>
          <p class="text-slate-500 mb-8">
            {{ blockingError || ui.extras.selectedTripMissing }}
          </p>
          <NuxtLink
            :to="buildRentSearchRoute(route.query, { locale })"
            class="inline-flex px-8 py-4 bg-slate-900 text-white rounded-2xl font-bold hover:bg-brand-orange transition-all"
          >
            {{ ui.common.backToSearch }}
          </NuxtLink>
        </div>
      </div>

      <div v-else-if="isBootstrapping" class="max-w-2xl mx-auto">
        <div class="bg-white/70 backdrop-blur-2xl rounded-[2.5rem] p-8 md:p-12 shadow-[0_8px_30px_rgb(0,0,0,0.04)] border border-white/50 text-center">
          <motion.div
            :animate="{ rotate: 360 }"
            :transition="{ duration: 1, repeat: Infinity, ease: 'linear' }"
            class="w-12 h-12 border-4 border-brand-orange/20 border-t-brand-orange rounded-full mx-auto mb-6"
          />
          <h1 class="text-3xl font-display font-bold text-slate-900 mb-3">{{ ui.extras.preparing }}</h1>
          <p class="text-slate-500">{{ ui.extras.preparingDescription }}</p>
        </div>
      </div>

      <div v-else class="grid grid-cols-1 lg:grid-cols-12 lg:items-start gap-8 lg:gap-12">
        <div class="lg:col-span-7 xl:col-span-8 space-y-10">
          <motion.div
            :initial="{ opacity: 0, y: 20 }"
            :animate="{ opacity: 1, y: 0 }"
            class="relative rounded-[2.5rem] overflow-hidden bg-white/40 backdrop-blur-2xl border border-white/80 shadow-[0_8px_32px_rgba(0,0,0,0.04)] group"
          >
            <div class="relative aspect-[16/9] rounded-[2.5rem] overflow-hidden m-1">
              <img
                v-if="vehicleImage"
                :src="vehicleImage"
                :alt="vehicleName"
                class="w-full h-full object-cover transition-transform duration-1000 group-hover:scale-105"
              >
              <div v-else class="w-full h-full bg-slate-100 text-slate-400 flex items-center justify-center">
                <Car class="w-16 h-16" />
              </div>
              <div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/20 to-transparent opacity-90" />

              <div class="absolute top-6 left-6 flex flex-col gap-2">
                <div
                  v-if="heroCategoryLabel"
                  class="bg-white/20 backdrop-blur-md border border-white/30 text-white text-xs font-bold uppercase tracking-widest px-4 py-2 rounded-full shadow-lg"
                >
                  {{ heroCategoryLabel }}
                </div>
                <div
                  v-if="heroMarketingBadge"
                  class="bg-brand-orange/90 backdrop-blur-md border border-brand-orange/50 text-white text-xs font-bold uppercase tracking-widest px-4 py-2 rounded-full shadow-lg flex items-center gap-1.5"
                >
                  <Sparkles class="w-3.5 h-3.5" /> {{ heroMarketingBadge }}
                </div>
              </div>
            </div>

            <div class="absolute bottom-0 left-0 right-0 p-8 md:p-10">
              <h1 class="text-4xl md:text-6xl font-display font-bold tracking-tighter text-white mb-6 drop-shadow-2xl">
                {{ vehicleName }}
              </h1>

              <div class="flex flex-wrap gap-3">
                <div
                  v-for="spec in vehicleSpecs.filter((item) => item.value)"
                  :key="spec.key"
                  class="flex items-center gap-2 bg-white/20 backdrop-blur-xl border border-white/30 px-4 py-2.5 rounded-2xl text-sm font-medium text-white shadow-lg"
                >
                  <component :is="spec.icon" class="w-4 h-4 text-brand-orange" />
                  {{ spec.value }}
                </div>
              </div>
            </div>
          </motion.div>

          <motion.section
            :initial="{ opacity: 0, y: 20 }"
            :animate="{ opacity: 1, y: 0 }"
            :transition="{ delay: 0.1 }"
          >
              <div class="flex items-center justify-between mb-6">
                <h2 class="text-2xl font-display font-bold flex items-center gap-3 text-slate-900">
                  <Sparkles class="w-6 h-6 text-brand-orange" />
                  {{ ui.extras.title }}
                </h2>
                <div class="flex items-center gap-3">
                  <div v-if="isRefreshingQuote" class="text-[11px] font-bold uppercase tracking-widest text-brand-orange">
                    {{ ui.extras.updatingTotal }}
                  </div>
                  <div class="text-xs font-bold uppercase tracking-widest text-slate-400">
                    {{ selectedExtrasCountLabel }}
                  </div>
                </div>
            </div>

            <div v-if="selectableExtras.length" class="grid grid-cols-1 sm:grid-cols-2 gap-5">
              <motion.div
                v-for="extra in selectableExtras"
                :key="extra.id"
                while-hover="{ scale: 1.02 }"
                while-tap="{ scale: 0.98 }"
                @click="toggleExtra(extra.id)"
                :class="[
                  'relative overflow-hidden p-6 rounded-3xl transition-all duration-300 text-left group',
                  isExtraSelected(extra.id)
                    ? 'bg-white/80 backdrop-blur-2xl border border-brand-orange/50 shadow-[0_10px_40px_-10px_rgba(249,115,22,0.2)]'
                    : 'bg-white/40 backdrop-blur-2xl border border-white/80 shadow-[0_8px_32px_rgba(0,0,0,0.04)] hover:bg-white/60 hover:shadow-[0_8px_32px_rgba(0,0,0,0.08)]',
                ]"
              >
                <div :class="['absolute top-6 right-6 w-6 h-6 rounded-full flex items-center justify-center transition-all duration-300', isExtraSelected(extra.id) ? 'bg-brand-orange shadow-md' : 'bg-white/60 border border-white shadow-sm']">
                  <Check v-if="isExtraSelected(extra.id)" class="w-3.5 h-3.5 text-white" stroke-width="3" />
                </div>

                <div :class="['w-12 h-12 rounded-2xl flex items-center justify-center mb-5 transition-colors duration-300 border border-white/60 shadow-sm', isExtraSelected(extra.id) ? 'bg-brand-orange/10' : 'bg-white/50 group-hover:bg-white/80']">
                  <component :is="extraIcons[extra.iconKey] || Package" :class="['w-6 h-6 transition-colors duration-300', isExtraSelected(extra.id) ? 'text-brand-orange' : 'text-slate-500']" />
                </div>

                <h3 class="text-lg font-bold text-slate-900 mb-1">{{ extra.name }}</h3>
                <p class="text-sm text-slate-600 leading-relaxed mb-5 min-h-[40px]">{{ extra.description }}</p>

                <div class="flex items-baseline gap-1">
                  <span :class="['text-xl font-display font-bold', isExtraSelected(extra.id) ? 'text-brand-orange' : 'text-slate-900']">
                    {{ formatMoney(extra.price, extra.currency || currencyCode) }}
                  </span>
                  <span class="text-xs text-slate-500 uppercase tracking-wider">
                    {{ extra.pricingType === 'per_day' ? ui.extras.perDaySuffix : ui.extras.perTripSuffix }}
                  </span>
                </div>
              </motion.div>
            </div>

            <div v-else class="bg-white/40 backdrop-blur-2xl border border-white/80 rounded-[2.5rem] p-8 text-slate-500 shadow-[0_8px_32px_rgba(0,0,0,0.04)]">
              {{ ui.extras.noPaidExtras }}
            </div>
          </motion.section>

          <motion.section
            :initial="{ opacity: 0, y: 20 }"
            :animate="{ opacity: 1, y: 0 }"
            :transition="{ delay: 0.2 }"
            class="bg-white/40 backdrop-blur-2xl border border-white/80 rounded-[2.5rem] p-8 md:p-10 shadow-[0_8px_32px_rgba(0,0,0,0.04)]"
          >
            <h2 class="text-2xl font-display font-bold mb-8 flex items-center gap-3 text-slate-900">
              <CheckCircle2 class="w-6 h-6 text-brand-orange" />
              {{ ui.extras.alreadyIncluded }}
            </h2>

            <div v-if="includedExtras.length" class="grid grid-cols-1 md:grid-cols-2 gap-6">
              <div
                v-for="extra in includedExtras"
                :key="extra.id"
                class="flex gap-4 bg-white/50 border border-white/70 rounded-3xl p-5"
              >
                <div class="w-12 h-12 rounded-2xl bg-white/70 flex items-center justify-center shrink-0 border border-white shadow-sm">
                  <component :is="extraIcons[extra.iconKey] || ShieldCheck" class="w-6 h-6 text-brand-orange" />
                </div>
                <div>
                  <div class="flex items-center gap-2 mb-1">
                    <h4 class="text-lg font-bold text-slate-900">{{ extra.name }}</h4>
                    <span class="text-[10px] font-bold uppercase tracking-widest text-emerald-600 bg-emerald-50 px-2 py-1 rounded-full">
                      {{ extra.salesLabel || ui.extras.includedLabel }}
                    </span>
                  </div>
                  <p class="text-sm text-slate-600 leading-relaxed">{{ extra.description }}</p>
                </div>
              </div>
            </div>
            <div v-else class="rounded-3xl border border-dashed border-slate-200 bg-white/40 px-6 py-5 text-sm text-slate-500">
              {{ ui.extras.noBundledExtras }}
            </div>
          </motion.section>

          <motion.section
            :initial="{ opacity: 0, y: 20 }"
            :animate="{ opacity: 1, y: 0 }"
            :transition="{ delay: 0.3 }"
            class="bg-white/40 backdrop-blur-2xl border border-white/80 rounded-[2.5rem] p-8 md:p-10 shadow-[0_8px_32px_rgba(0,0,0,0.04)]"
          >
            <h2 class="text-2xl font-display font-bold mb-8 flex items-center gap-3 text-slate-900">
              <Info class="w-6 h-6 text-blue-500" />
              {{ ui.extras.goodToKnow }}
            </h2>
            <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
              <div class="flex gap-5">
                <div class="w-12 h-12 rounded-2xl bg-white/60 backdrop-blur-md border border-white/80 flex items-center justify-center shrink-0 shadow-sm">
                  <CreditCard class="w-6 h-6 text-slate-700" />
                </div>
                <div>
                  <h4 class="font-bold text-slate-900 mb-1.5 text-lg">{{ ui.extras.securityDeposit }}</h4>
                  <p class="text-sm text-slate-600 leading-relaxed">
                    {{ quoteDepositAmount > 0 ? ui.extras.refundableDepositTemplate.replace('{amount}', depositLabel) : ui.extras.noDepositDescription }}
                  </p>
                </div>
              </div>
              <div class="flex gap-5">
                <div class="w-12 h-12 rounded-2xl bg-white/60 backdrop-blur-md border border-white/80 flex items-center justify-center shrink-0 shadow-sm">
                  <Clock class="w-6 h-6 text-slate-700" />
                </div>
                <div>
                  <h4 class="font-bold text-slate-900 mb-1.5 text-lg">{{ ui.extras.liveQuote }}</h4>
                  <p class="text-sm text-slate-600 leading-relaxed">{{ ui.extras.liveQuoteDescription }}</p>
                </div>
              </div>
            </div>
          </motion.section>
        </div>

        <aside class="lg:col-span-5 xl:col-span-4 lg:self-start lg:h-fit lg:sticky lg:top-28 space-y-6">
          <motion.div
            :initial="{ opacity: 0, y: -20 }"
            :animate="{ opacity: 1, y: 0 }"
            class="bg-rose-50/60 backdrop-blur-xl border border-white/80 text-rose-600 p-4 rounded-3xl shadow-sm flex items-start gap-3"
          >
            <Shield class="w-5 h-5 shrink-0 mt-0.5" />
            <div>
              <p class="text-sm font-bold">{{ ui.extras.liveDemand }}</p>
              <p class="text-xs mt-1 opacity-90">{{ demandMessage }}</p>
            </div>
          </motion.div>

          <motion.div
            :initial="{ opacity: 0, scale: 0.95 }"
            :animate="{ opacity: 1, scale: 1 }"
            :transition="{ delay: 0.2 }"
            class="bg-white/50 backdrop-blur-3xl border border-white/80 rounded-[2.5rem] p-8 shadow-[0_20px_60px_-15px_rgba(0,0,0,0.08)] relative z-10 overflow-hidden"
          >
            <div class="absolute top-0 left-1/2 -translate-x-1/2 w-full h-32 bg-brand-orange/10 blur-[60px] pointer-events-none" />

            <div v-if="activeOffer" class="mb-5 relative z-10">
              <OfferContextBanner :offer="activeOffer" compact />
            </div>

            <div class="flex items-end gap-2 mb-2 relative z-10 flex-wrap">
              <span class="text-5xl font-display font-bold tracking-tighter text-slate-900">{{ formatMoney(currentDailyRate || 0, currencyCode) }}</span>
              <span class="text-slate-500 font-medium mb-2">{{ ui.extras.perDaySuffix }}</span>
              <div v-if="offerReferenceDailyPrice || offerDiscountLabel" class="mb-2 ml-2 inline-flex items-center gap-2 rounded-full border border-brand-orange/15 bg-brand-orange/[0.07] px-3 py-1.5">
                <span
                  v-if="offerReferenceDailyPrice"
                  class="text-sm font-bold text-slate-400 line-through"
                >
                  {{ formatMoney(offerReferenceDailyPrice, currencyCode) }}
                </span>
                <span
                  v-if="offerDiscountLabel"
                  class="text-[11px] font-black uppercase tracking-[0.16em] text-brand-orange"
                >
                  {{ offerDiscountLabel }}
                </span>
              </div>
            </div>

            <div class="flex items-center gap-1.5 text-slate-500 text-xs font-medium mb-8">
              <Calendar class="w-3.5 h-3.5" />
              {{ pickupLabel }} <span class="mx-1">→</span> {{ dropoffLabel }}
            </div>

            <div class="bg-white/40 hover:bg-white/70 border border-white/80 shadow-sm rounded-2xl p-5 mb-8">
              <div class="text-xs font-bold uppercase tracking-widest text-slate-500 mb-3 ml-2">{{ ui.extras.rentalPeriod }}</div>
              <div class="font-bold text-slate-900 text-sm">
                {{ pickupLabel }} <span class="text-slate-400 mx-2">→</span> {{ dropoffLabel }}
              </div>
              <div class="text-xs text-slate-500 mt-0.5">{{ totalDaysLabel }}</div>
            </div>

            <div v-if="quoteRefreshError" class="mb-6 rounded-2xl border border-amber-200 bg-amber-50/80 px-4 py-3 text-sm font-medium text-amber-700">
              {{ quoteRefreshError }}
            </div>

            <div class="space-y-4 mb-8 relative z-10">
              <div
                v-for="line in summaryLines"
                :key="line.code || line.label"
                :class="[
                  'flex justify-between text-sm',
                  Number(line.amount || 0) >= 0 ? 'text-slate-600' : 'text-emerald-600 font-medium',
                ]"
              >
                <span>{{ line.localizedLabel || line.label }}</span>
                <span class="font-medium" :class="Number(line.amount || 0) >= 0 ? 'text-slate-900' : 'text-emerald-600'">
                  {{ formatMoney(line.amount, currencyCode) }}
                </span>
              </div>
            </div>

            <div class="border-t border-slate-200/50 pt-6 mb-8 flex justify-between items-end relative z-10">
              <div>
                <div class="text-sm text-slate-600 mb-1">{{ ui.extras.totalAmount }}</div>
                <div class="text-xs text-slate-400">{{ ui.extras.includesSelectedExtras }}</div>
              </div>
              <div class="font-display font-bold text-4xl tracking-tighter text-slate-900">
                {{ formatMoney(quoteFinalTotal, currencyCode) }}
              </div>
            </div>

            <button
              type="button"
              :disabled="isRefreshingQuote"
              class="w-full py-5 bg-slate-900 text-white rounded-2xl font-bold text-lg shadow-xl shadow-slate-900/20 hover:shadow-slate-900/30 hover:-translate-y-0.5 transition-all duration-300 flex items-center justify-center gap-2 relative z-10 overflow-hidden group"
              @click="proceedToCheckout"
            >
              <span class="relative z-10">{{ isRefreshingQuote ? ui.extras.updatingCta : ui.extras.proceedToCheckout }}</span>
              <ArrowLeft class="w-5 h-5 rotate-180 relative z-10 group-hover:translate-x-1 transition-transform" />
            </button>

            <div class="mt-6 flex items-start gap-2 text-xs text-slate-500 font-medium relative z-10">
              <Info class="w-4 h-4 shrink-0 mt-0.5" />
              {{ ui.extras.savedToCheckout }}
            </div>
          </motion.div>
        </aside>
      </div>
    </main>
  </div>
</template>
