<template>
  <Stack gap="0">
    <!-- Loading -->
    <Section v-if="isLoading" variant="plain" paddingY="lg">
      <Stack align="center" justify="center" gap="4">
        <Spinner />
        <Text tone="muted">{{ t('catalogHub.states.loading') }}</Text>
      </Stack>
    </Section>

    <!-- Error / Not Found -->
    <Section v-else-if="!hub" variant="plain" paddingY="lg">
      <Card padding="lg">
        <Stack align="center" gap="4">
          <IconCircle tone="primary">
            <Icon name="lucide:map-pin" size="24" />
          </IconCircle>
          <Heading :level="2">{{ t('catalogHub.not_found.title') }}</Heading>
          <Text tone="muted">{{ t('catalogHub.not_found.subtitle') }}</Text>
          <Button @click="navigateTo(localePath('/catalog'))">
            {{ t('catalogHub.actions.back_to_catalog') }}
          </Button>
        </Stack>
      </Card>
    </Section>

    <template v-else>
      <CatalogPage
        :items="sources"
        :loading="isLoadingRoutes"
        :with-map="true"
        map-id="hub-sources-map"
        point-color="#10b981"
        v-model:selected-id="selectedSourceUuid"
      >
        <template #header>
          <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
            <div>
              <Heading :level="1">{{ hub.name }}</Heading>
              <Text tone="muted" size="sm">{{ hub.country }}</Text>
            </div>
          </div>
        </template>

        <template #filters>
          <div class="flex gap-3 overflow-x-auto pb-2">
            <Card
              v-for="product in products"
              :key="product.uuid"
              padding="sm"
              interactive
              class="min-w-32 cursor-pointer shrink-0"
              :class="selectedProductUuid === product.uuid ? 'ring-2 ring-primary' : ''"
              @click="selectedProductUuid = product.uuid"
            >
              <Text weight="semibold" size="sm">{{ product.name }}</Text>
            </Card>
          </div>
        </template>

        <template #card="{ item }">
          <OfferResultCard
            :location-name="getOfferData(item.uuid)?.locationName"
            :product-name="selectedProductName"
            :price-per-unit="getOfferData(item.uuid)?.pricePerUnit"
            :currency="getOfferData(item.uuid)?.currency"
            :unit="getOfferData(item.uuid)?.unit"
            :stages="item.stages"
          />
        </template>

        <template #empty>
          <Stack align="center" gap="2">
            <Icon name="lucide:package-x" size="32" class="text-base-content/40" />
            <Text tone="muted">
              {{ selectedProductUuid ? t('catalogHub.sources.empty') : t('catalogHub.sources.selectProduct') }}
            </Text>
          </Stack>
        </template>
      </CatalogPage>
    </template>
  </Stack>
</template>

<script setup lang="ts">
import { GetNodeConnectionsDocument, FindProductRoutesDocument } from '~/composables/graphql/public/geo-generated'
import { GetAvailableProductsDocument, GetOfferDocument } from '~/composables/graphql/public/exchange-generated'

definePageMeta({
  layout: 'topnav'
})

const route = useRoute()
const localePath = useLocalePath()
const { t } = useI18n()
const { execute } = useGraphQL()

const isLoading = ref(true)
const isLoadingRoutes = ref(false)
const hub = ref<any>(null)
const products = ref<Array<{ uuid: string; name: string }>>([])
const selectedProductUuid = ref('')
const selectedSourceUuid = ref('')
const rawSources = ref<any[]>([])
const offersData = ref<Map<string, any>>(new Map())

const hubId = computed(() => route.params.id as string)

// Selected product name
const selectedProductName = computed(() => {
  const product = products.value.find(p => p.uuid === selectedProductUuid.value)
  return product?.name || ''
})

// Transform sources for CatalogPage (needs uuid, latitude, longitude, name, stages)
const sources = computed(() => {
  return rawSources.value.map(source => ({
    uuid: source.sourceUuid || '',
    name: source.sourceName || '',
    latitude: source.sourceLat,
    longitude: source.sourceLon,
    distanceKm: source.distanceKm,
    durationSeconds: source.routes?.[0]?.totalTimeSeconds,
    stages: (source.routes?.[0]?.stages || []).map((stage: any) => ({
      transportType: stage?.transportType,
      distanceKm: stage?.distanceKm
    }))
  }))
})

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

// Load offer details for prices
const loadOfferDetails = async () => {
  if (rawSources.value.length === 0) {
    offersData.value.clear()
    return
  }

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

// Load routes when product changes
const loadRoutes = async () => {
  if (!selectedProductUuid.value || !hubId.value) {
    rawSources.value = []
    offersData.value.clear()
    return
  }

  isLoadingRoutes.value = true
  selectedSourceUuid.value = ''

  try {
    const data = await execute(
      FindProductRoutesDocument,
      {
        productUuid: selectedProductUuid.value,
        toUuid: hubId.value,
        limitSources: 12,
        limitRoutes: 1
      },
      'public',
      'geo'
    )
    rawSources.value = (data?.findProductRoutes || []).filter(Boolean)
    await loadOfferDetails()
  } catch (error) {
    console.error('Error loading routes:', error)
    rawSources.value = []
  } finally {
    isLoadingRoutes.value = false
  }
}

watch(selectedProductUuid, loadRoutes)

// 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}м`
}

// Initial load
try {
  const [{ data: connectionsData }, { data: productsData }] = await Promise.all([
    useServerQuery('hub-connections', GetNodeConnectionsDocument, { uuid: hubId.value }, 'public', 'geo'),
    useServerQuery('available-products', GetAvailableProductsDocument, {}, 'public', 'exchange')
  ])

  hub.value = connectionsData.value?.nodeConnections?.hub || null
  products.value = (productsData.value?.getAvailableProducts || [])
    .filter((p): p is { uuid: string; name: string } => p !== null && !!p.uuid && !!p.name)
    .map(p => ({ uuid: p.uuid!, name: p.name! }))
} catch (error) {
  console.error('Error loading hub:', error)
} finally {
  isLoading.value = false
}

// SEO
useHead(() => ({
  title: hub.value?.name
    ? t('catalogHub.meta.title_with_name', { name: hub.value.name })
    : t('catalogHub.meta.title'),
  meta: [
    {
      name: 'description',
      content: t('catalogHub.meta.description', {
        name: hub.value?.name || '',
        country: hub.value?.country || '',
        offers: sources.value.length,
        suppliers: 0
      })
    }
  ]
}))
</script>
