<template>
  <div class="space-y-6">
    <!-- Header -->
    <Card padding="lg" class="border border-base-300">
      <RouteSummaryHeader :title="summaryTitle" :meta="summaryMeta" />
    </Card>

    <!-- Loading -->
    <div v-if="pending" class="text-sm text-base-content/60">
      Загрузка маршрутов...
    </div>

    <!-- Error -->
    <div v-else-if="error" class="text-sm text-error">
      Ошибка загрузки маршрутов: {{ error.message }}
    </div>

    <!-- Results -->
    <div v-else-if="productRouteOptions.length > 0" class="space-y-4">
      <OfferResultCard
        v-for="option in productRouteOptions"
        :key="option.sourceUuid"
        :location-name="getOfferData(option.sourceUuid)?.locationName"
        :product-name="productName"
        :price-per-unit="getOfferData(option.sourceUuid)?.pricePerUnit"
        :currency="getOfferData(option.sourceUuid)?.currency"
        :unit="getOfferData(option.sourceUuid)?.unit"
        :stages="getRouteStages(option)"
      />
    </div>

    <!-- Legacy routes (fallback) -->
    <div v-else-if="legacyRoutes.length > 0" class="space-y-6">
      <Card
        v-for="(route, routeIndex) in legacyRoutes"
        :key="routeIndex"
        padding="lg"
        class="border border-base-300"
      >
        <Stack gap="4">
          <div class="flex flex-wrap items-center justify-between gap-2">
            <Text weight="semibold">Маршрут {{ routeIndex + 1 }}</Text>
            <Text tone="muted" size="sm">
              {{ formatDistance(route.totalDistanceKm) }} км · {{ formatDuration(route.totalTimeSeconds) }}
            </Text>
          </div>

          <RouteStagesList :stages="mapRouteStages(route)" />

          <div class="divider my-0"></div>

          <RequestRoutesMap :routes="[route]" :height="240" />
        </Stack>
      </Card>
    </div>

    <!-- Empty -->
    <div v-else class="text-sm text-base-content/60">
      Маршруты не найдены. Возможно, нет связи между точками в графе.
    </div>
  </div>
</template>

<script setup lang="ts">
import { FindRoutesDocument } from '~/composables/graphql/public/geo-generated'
import type { RoutePathType } from '~/composables/graphql/public/geo-generated'
import type { RouteStageItem } from '~/components/RouteStagesList.vue'
import { GetOfferDocument } from '~/composables/graphql/public/exchange-generated'

const route = useRoute()
const searchStore = useSearchStore()
const { execute } = useGraphQL()

const productName = computed(() => searchStore.searchForm.product || (route.query.product as string) || 'Товар')
const locationName = computed(() => searchStore.searchForm.location || (route.query.location as string) || 'Назначение')
const quantity = computed(() => (route.query.quantity as string) || (searchStore.searchForm as any)?.quantity)

// Offer data for prices
const offersData = ref<Map<string, any>>(new Map())

const summaryTitle = computed(() => `${productName.value} → ${locationName.value}`)
const summaryMeta = computed(() => {
  const meta: string[] = []
  if (quantity.value) {
    meta.push(`${quantity.value}`)
  }
  return meta
})

// Determine context (new flow: product + destination; legacy: from param)
const productUuid = computed(() => (route.query.productUuid as string) || searchStore.searchForm.productUuid)
const destinationUuid = computed(() => (route.query.locationUuid as string) || searchStore.searchForm.locationUuid)
const legacyFromUuid = computed(() => route.params.id as string | undefined)

type ProductRouteOption = {
  sourceUuid?: string | null
  sourceName?: string | null
  sourceLat?: number | null
  sourceLon?: number | null
  distanceKm?: number | null
  routes?: RoutePathType[] | null
}

const fetchProductRoutes = async () => {
  if (!productUuid.value || !destinationUuid.value) return null
  const { client } = useApolloClient('publicGeo')
  const { default: gql } = await import('graphql-tag')

  const query = gql`
    query FindProductRoutes($productUuid: String!, $toUuid: String!, $limitSources: Int, $limitRoutes: Int) {
      findProductRoutes(
        productUuid: $productUuid
        toUuid: $toUuid
        limitSources: $limitSources
        limitRoutes: $limitRoutes
      ) {
        sourceUuid
        sourceName
        sourceLat
        sourceLon
        distanceKm
        routes {
          totalDistanceKm
          totalTimeSeconds
          stages {
            fromUuid
            fromName
            fromLat
            fromLon
            toUuid
            toName
            toLat
            toLon
            distanceKm
            travelTimeSeconds
            transportType
          }
        }
      }
    }
  `

  const { data } = await client.query({
    query,
    variables: {
      productUuid: productUuid.value,
      toUuid: destinationUuid.value,
      limitSources: 5,
      limitRoutes: 1
    }
  })
  return data
}

const fetchLegacyRoutes = async () => {
  if (!legacyFromUuid.value || !destinationUuid.value) return null
  const { client } = useApolloClient('publicGeo')
  const { data } = await client.query({
    query: FindRoutesDocument,
    variables: {
      fromUuid: legacyFromUuid.value,
      toUuid: destinationUuid.value,
      limit: 3
    }
  })
  return data
}

const { data: productRoutesData, pending, error } = await useAsyncData(
  () => `product-routes-${productUuid.value}-${destinationUuid.value}-${legacyFromUuid.value || 'none'}`,
  async () => {
    // Prefer product-based routes; fallback to legacy if no product
    if (productUuid.value && destinationUuid.value) {
      return await fetchProductRoutes()
    }
    if (legacyFromUuid.value && destinationUuid.value) {
      return await fetchLegacyRoutes()
    }
    return null
  },
  { watch: [productUuid, destinationUuid, legacyFromUuid] }
)

const productRouteOptions = computed(() => {
  const options = productRoutesData.value?.findProductRoutes as ProductRouteOption[] | undefined
  return options?.filter(Boolean) || []
})

const legacyRoutes = computed(() => {
  const data = productRoutesData.value?.findRoutes
  if (!data) return []
  return (data as (RoutePathType | null)[]).filter((r): r is RoutePathType => r !== null)
})

const mapRouteStages = (route: RoutePathType): RouteStageItem[] => {
  return (route.stages || [])
    .filter(Boolean)
    .map((stage, index) => ({
      key: stage?.fromUuid || `stage-${index}`,
      from: stage?.fromName || 'Начало',
      to: stage?.toName || 'Конец',
      distanceKm: stage?.distanceKm,
      durationSeconds: stage?.travelTimeSeconds,
      transportType: stage?.transportType
    }))
}

// Get route stages for OfferResultCard stepper
const getRouteStages = (option: ProductRouteOption) => {
  const route = option.routes?.[0]
  if (!route?.stages) return []
  return route.stages.filter(Boolean).map((stage: any) => ({
    transportType: stage?.transportType,
    distanceKm: stage?.distanceKm
  }))
}

// Get offer data for card
const getOfferData = (uuid?: string | null) => {
  if (!uuid) return null
  return offersData.value.get(uuid)
}

// Load offer details for prices
const loadOfferDetails = async (options: ProductRouteOption[]) => {
  if (options.length === 0) {
    offersData.value.clear()
    return
  }

  const newOffersData = new Map<string, any>()
  await Promise.all(options.map(async (option) => {
    if (!option.sourceUuid) return
    try {
      const data = await execute(GetOfferDocument, { uuid: option.sourceUuid }, 'public', 'exchange')
      if (data?.getOffer) {
        newOffersData.set(option.sourceUuid, data.getOffer)
      }
    } catch (error) {
      console.error('Error loading offer:', option.sourceUuid, error)
    }
  }))
  offersData.value = newOffersData
}

// Watch for route options and load offers
watch(productRouteOptions, (options) => {
  if (options.length > 0) {
    loadOfferDetails(options)
  }
}, { immediate: true })

// Formatting helpers
const formatDistance = (km: number | null | undefined) => {
  if (!km) return '0'
  return Math.round(km).toLocaleString()
}

const formatDuration = (seconds: number | null | undefined) => {
  if (!seconds) return '-'
  const hours = Math.floor(seconds / 3600)
  const minutes = Math.floor((seconds % 3600) / 60)
  if (hours > 24) {
    const days = Math.floor(hours / 24)
    const remainingHours = hours % 24
    return `${days}д ${remainingHours}ч`
  }
  if (hours > 0) {
    return `${hours}ч ${minutes}м`
  }
  return `${minutes}м`
}
</script>
