import type { SuppliersListQueryResult, NearestSuppliersQueryResult } from '~/composables/graphql/public/geo-generated'
import { SuppliersListDocument, NearestSuppliersDocument } from '~/composables/graphql/public/geo-generated'

const PAGE_SIZE = 500

// Types from codegen
type SupplierItem = NonNullable<NonNullable<SuppliersListQueryResult['suppliers_list']>[number]>
type NearestSupplierItem = NonNullable<NonNullable<NearestSuppliersQueryResult['nearest_suppliers']>[number]>

// Shared state across list and map views
const items = ref<Array<SupplierItem | NearestSupplierItem>>([])
const total = ref(0)
const isLoading = ref(false)
const isLoadingMore = ref(false)
const isInitialized = ref(false)
const filterProductUuid = ref<string | null>(null)
const filterBounds = ref<{ west: number; south: number; east: number; north: number } | null>(null)

export function useCatalogSuppliers() {
  const { execute } = useGraphQL()

  const itemsWithCoords = computed(() =>
    items.value.filter((s): s is NearestSupplierItem => 'latitude' in s && 'longitude' in s && s.latitude != null && s.longitude != null)
  )

  const canLoadMore = computed(() => items.value.length < total.value)

  const fetchPage = async (offset: number, replace = false) => {
    if (replace) isLoading.value = true
    try {
      // If filtering by product, use nearestSuppliers (product-only list)
      if (filterProductUuid.value) {
        const data = await execute(
          NearestSuppliersDocument,
          {
            lat: 0,
            lon: 0,
            productUuid: filterProductUuid.value,
            limit: 500 // Increased limit for global search
          },
          'public',
          'geo'
        )
        items.value = (data?.nearest_suppliers || []).filter((s): s is NearestSupplierItem => s !== null)
        total.value = items.value.length
        isInitialized.value = true
        return
      }

      // Default: fetch all suppliers from GEO (graph-based)
      const data = await execute(
        SuppliersListDocument,
        {
          limit: PAGE_SIZE,
          offset,
          ...(filterBounds.value && {
            west: filterBounds.value.west,
            south: filterBounds.value.south,
            east: filterBounds.value.east,
            north: filterBounds.value.north
          })
        },
        'public',
        'geo'
      )
      const next = (data?.suppliers_list || []).filter((s): s is SupplierItem => s !== null)

      items.value = replace ? next : items.value.concat(next)
      // suppliersList doesn't return total count, estimate from fetched items
      if (replace) {
        total.value = next.length < PAGE_SIZE ? next.length : next.length + PAGE_SIZE
      } else if (next.length < PAGE_SIZE) {
        total.value = items.value.length
      }
      isInitialized.value = true
    } finally {
      isLoading.value = false
    }
  }

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

  // Initialize data if not already loaded
  const init = async () => {
    if (!isInitialized.value && items.value.length === 0) {
      await fetchPage(0, true)
    }
  }

  const setProductFilter = (uuid: string | null) => {
    if (filterProductUuid.value === uuid) return // Early return if unchanged
    filterProductUuid.value = uuid
    fetchPage(0, true)
  }

  const setBoundsFilter = (bounds: { west: number; south: number; east: number; north: number } | null) => {
    // Early return if bounds haven't changed
    const prev = filterBounds.value
    const same = prev === bounds || (
      prev && bounds &&
      prev.west === bounds.west &&
      prev.south === bounds.south &&
      prev.east === bounds.east &&
      prev.north === bounds.north
    )
    if (same) return

    filterBounds.value = bounds
    if (isInitialized.value) {
      fetchPage(0, true)
    }
  }

  return {
    items,
    total,
    isLoading,
    isLoadingMore,
    itemsWithCoords,
    canLoadMore,
    fetchPage,
    loadMore,
    init,
    setProductFilter,
    setBoundsFilter
  }
}
