<template>
  <Stack gap="6">
    <Section variant="plain" paddingY="md">
      <PageHeader :title="t('catalogHubsSection.header.title')" />
    </Section>

    <Section v-if="isLoading" variant="plain" paddingY="md">
      <Card padding="lg">
        <Stack align="center" justify="center" gap="3">
          <Spinner />
          <Text tone="muted">{{ t('catalogLanding.states.loading') }}</Text>
        </Stack>
      </Card>
    </Section>

    <Section v-else variant="plain" paddingY="md">
      <Stack gap="6">
        <Stack direction="row" gap="2" wrap>
          <Pill
            v-for="filter in transportFilters"
            :key="filter.id"
            :variant="filter.id === selectedTransport ? 'primary' : 'outline'"
            class="cursor-pointer"
            @click="selectedTransport = filter.id"
          >
            {{ filter.label }}
          </Pill>
        </Stack>
        <div v-for="country in hubsByCountry" :key="country.name" class="space-y-3">
          <Text weight="semibold">{{ country.name }}</Text>
          <Grid :cols="1" :md="2" :lg="3" :gap="4">
            <HubCard
              v-for="hub in country.hubs"
              :key="hub.uuid"
              :hub="hub"
            />
          </Grid>
        </div>
        <PaginationLoadMore
          :shown="hubs.length"
          :total="totalHubs"
          :can-load-more="canLoadMore"
          :loading="isLoadingMore"
          @load-more="loadMore"
        />
        <Stack v-if="hubs.length === 0" align="center" gap="2">
          <Text tone="muted">{{ t('catalogHubsSection.empty.no_hubs') }}</Text>
        </Stack>
      </Stack>
    </Section>
  </Stack>
</template>

<script setup lang="ts">
import { GetNodesDocument } from '~/composables/graphql/public/geo-generated'

const { t } = useI18n()

const { execute } = useGraphQL()
const PAGE_SIZE = 24
const selectedTransport = ref('all')
const hubs = ref<any[]>([])
const totalHubs = ref(0)
const isLoadingMore = ref(false)

const initialVariables = {
  limit: PAGE_SIZE,
  offset: 0,
  transportType: null
}

const { data: hubsData, pending: hubsPending } = await useServerQuery(
  'catalog-hubs',
  GetNodesDocument,
  initialVariables,
  'public',
  'geo'
)

watchEffect(() => {
  if (hubsData.value?.nodes) {
    hubs.value = hubsData.value.nodes
    totalHubs.value = hubsData.value.nodesCount ?? hubsData.value.nodes.length
  }
})

const isLoading = computed(() => hubsPending.value && hubs.value.length === 0)

const transportLabels = computed(() => ({
  all: t('catalogHubsSection.filters.all'),
  auto: t('catalogHubsSection.filters.auto'),
  rail: t('catalogHubsSection.filters.rail'),
  sea: t('catalogHubsSection.filters.sea'),
  air: t('catalogHubsSection.filters.air')
}))

const transportFilters = computed(() => {
  return [
    { id: 'all', label: transportLabels.value.all },
    { id: 'auto', label: transportLabels.value.auto },
    { id: 'rail', label: transportLabels.value.rail },
    { id: 'sea', label: transportLabels.value.sea },
    { id: 'air', label: transportLabels.value.air }
  ]
})

const canLoadMore = computed(() => hubs.value.length < totalHubs.value)

const fetchPage = async (offset: number, replace = false) => {
  const transportType = selectedTransport.value === 'all' ? null : selectedTransport.value
  const data = await execute(
    GetNodesDocument,
    { limit: PAGE_SIZE, offset, transportType },
    'public',
    'geo'
  )
  const next = data?.nodes || []
  hubs.value = replace ? next : hubs.value.concat(next)
  totalHubs.value = data?.nodesCount ?? totalHubs.value
}

const loadMore = async () => {
  if (isLoadingMore.value) return
  isLoadingMore.value = true
  try {
    await fetchPage(hubs.value.length)
  } finally {
    isLoadingMore.value = false
  }
}

watch(selectedTransport, async () => {
  await fetchPage(0, true)
})

const hubsByCountry = computed(() => {
  const grouped = new Map<string, any[]>()
  hubs.value.forEach(hub => {
    const country = hub.country || t('catalogMap.labels.country_unknown')
    if (!grouped.has(country)) grouped.set(country, [])
    grouped.get(country)!.push(hub)
  })
  return Array.from(grouped.entries())
    .map(([name, hubsList]) => ({ name, hubs: hubsList }))
    .sort((a, b) => a.name.localeCompare(b.name))
})

useHead(() => ({
  title: t('catalogHubsSection.header.title')
}))
</script>
