<template>
  <Stack gap="6">
    <PageHeader :title="t('clientOffersList.header.title')">
      <template #actions>
        <NuxtLink :to="localePath('/clientarea/offers/new')">
          <Button>
            <Icon name="lucide:plus" size="16" class="mr-2" />
            {{ t('clientOffersList.actions.add') }}
          </Button>
        </NuxtLink>
      </template>
    </PageHeader>

    <Alert v-if="hasError" variant="error">
      <Stack gap="2">
        <Heading :level="4" weight="semibold">{{ t('clientOffersList.error.title') }}</Heading>
        <Text tone="muted">{{ error }}</Text>
        <Button @click="loadOffers">{{ t('clientOffersList.error.retry') }}</Button>
      </Stack>
    </Alert>

    <Stack v-else-if="isLoading" align="center" justify="center" gap="3">
      <Spinner />
      <Text tone="muted">{{ t('clientOffersList.states.loading') }}</Text>
    </Stack>

    <template v-else>
      <Stack v-if="offers.length" gap="4">
        <Card v-for="offer in offers" :key="offer.uuid" padding="lg">
          <Stack gap="3">
            <Stack direction="row" justify="between" align="center">
              <Heading :level="3">{{ offer.productName || t('clientOffersList.labels.untitled') }}</Heading>
              <Badge :variant="getStatusVariant(offer.status)">
                {{ getStatusText(offer.status) }}
              </Badge>
            </Stack>

            <Text v-if="offer.categoryName" tone="muted">{{ offer.categoryName }}</Text>

            <Grid :cols="1" :md="4" :gap="3">
              <Stack gap="1">
                <Text size="sm" tone="muted">{{ t('clientOffersList.labels.quantity') }}</Text>
                <Text weight="semibold">{{ offer.quantity }} {{ offer.unit || t('search.units.tons_short') }}</Text>
              </Stack>

              <Stack gap="1">
                <Text size="sm" tone="muted">{{ t('clientOffersList.labels.price') }}</Text>
                <Text weight="semibold">{{ formatPrice(offer.pricePerUnit, offer.currency) }}</Text>
              </Stack>

              <Stack gap="1">
                <Text size="sm" tone="muted">{{ t('clientOffersList.labels.location') }}</Text>
                <Text>{{ offer.locationName || t('clientOffersList.labels.not_specified') }}</Text>
              </Stack>

              <Stack gap="1">
                <Text size="sm" tone="muted">{{ t('clientOffersList.labels.valid_until') }}</Text>
                <Text>{{ formatDate(offer.validUntil) }}</Text>
              </Stack>
            </Grid>
          </Stack>
        </Card>

        <PaginationLoadMore
          :shown="offers.length"
          :total="totalOffers"
          :can-load-more="canLoadMore"
          :loading="isLoadingMore"
          @load-more="loadMore"
        />
      </Stack>

      <EmptyState
        v-else
        icon="🏷️"
        :title="t('clientOffersList.empty.title')"
        :description="t('clientOffersList.empty.subtitle')"
        :action-label="t('clientOffersList.actions.addOffer')"
        :action-to="localePath('/clientarea/offers/new')"
        action-icon="lucide:plus"
      />
    </template>
  </Stack>
</template>

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

definePageMeta({
  middleware: ['auth-oidc']
})

const localePath = useLocalePath()
const { t, locale } = useI18n()
const { activeTeamId } = useActiveTeam()

const { execute } = useGraphQL()
const PAGE_SIZE = 24
const offers = ref<any[]>([])
const totalOffers = ref(0)
const isLoadingMore = ref(false)

const {
  data: offersData,
  pending: offersPending,
  error: loadError,
  refresh: refreshOffers
} = await useServerQuery(
  'client-offers-list',
  GetOffersDocument,
  { teamUuid: activeTeamId.value || null, limit: PAGE_SIZE, offset: 0 },
  'public',
  'exchange'
)

watchEffect(() => {
  if (offersData.value?.getOffers) {
    offers.value = offersData.value.getOffers
    totalOffers.value = offersData.value.getOffersCount ?? offersData.value.getOffers.length
  }
})

const isLoading = computed(() => offersPending.value && offers.value.length === 0)
const canLoadMore = computed(() => offers.value.length < totalOffers.value)
const hasError = computed(() => !!loadError.value)
const error = computed(() => loadError.value?.message || t('clientOffersList.error.load'))

const getStatusVariant = (status: string) => {
  const variants: Record<string, string> = {
    active: 'success',
    draft: 'warning',
    expired: 'error',
    sold: 'muted'
  }
  return variants[status] || 'muted'
}

const getStatusText = (status: string) => {
  const texts: Record<string, string> = {
    active: t('clientOffersList.status.active'),
    draft: t('clientOffersList.status.draft'),
    expired: t('clientOffersList.status.expired'),
    sold: t('clientOffersList.status.sold')
  }
  return texts[status] || status || t('clientOffersList.status.unknown')
}

const formatDate = (date: string) => {
  if (!date) return t('clientOffersList.labels.not_specified')
  try {
    const dateObj = new Date(date)
    if (isNaN(dateObj.getTime())) return t('clientOffersList.labels.invalid_date')
    return new Intl.DateTimeFormat(locale.value === 'ru' ? 'ru-RU' : 'en-US', {
      day: 'numeric',
      month: 'long',
      year: 'numeric'
    }).format(dateObj)
  } catch {
    return t('clientOffersList.labels.invalid_date')
  }
}

const formatPrice = (price: number | string | null | undefined, currency?: string | null) => {
  if (!price) return t('clientOffersList.labels.not_specified')
  const num = typeof price === 'string' ? parseFloat(price) : price
  const curr = currency || 'USD'
  try {
    return new Intl.NumberFormat(locale.value === 'ru' ? 'ru-RU' : 'en-US', {
      style: 'currency',
      currency: curr,
      maximumFractionDigits: 0
    }).format(num)
  } catch {
    return `${num} ${curr}`
  }
}

const fetchOffers = async (offset = 0, replace = false) => {
  const data = await execute(
    GetOffersDocument,
    { teamUuid: activeTeamId.value || null, limit: PAGE_SIZE, offset },
    'public',
    'exchange'
  )
  const next = data?.getOffers || []
  offers.value = replace ? next : offers.value.concat(next)
  totalOffers.value = data?.getOffersCount ?? totalOffers.value
}

const loadOffers = async () => refreshOffers()
const loadMore = async () => {
  if (isLoadingMore.value) return
  isLoadingMore.value = true
  try {
    await fetchOffers(offers.value.length)
  } finally {
    isLoadingMore.value = false
  }
}

watch(
  () => activeTeamId.value,
  async () => {
    await fetchOffers(0, true)
  }
)
</script>
