import type { LocationQuery } from 'vue-router'

export type SelectMode = 'product' | 'supplier' | 'hub' | null
export type MapViewMode = 'offers' | 'hubs' | 'suppliers'
export type CatalogMode = 'explore' | 'quote'
export type InfoEntityType = 'hub' | 'supplier' | 'offer'
export type DisplayMode =
  | 'map-default'
  | 'grid-products'
  | 'grid-suppliers'
  | 'grid-hubs'
  | 'grid-hubs-for-product'
  | 'grid-products-from-supplier'
  | 'grid-products-in-hub'
  | 'grid-offers'

export interface InfoId {
  type: InfoEntityType
  uuid: string
}

export interface SearchFilter {
  type: 'product' | 'supplier' | 'hub' | 'quantity'
  id: string
  label: string
}

export interface SearchState {
  selectMode: SelectMode
  product: { id: string; name: string } | null
  supplier: { id: string; name: string } | null
  hub: { id: string; name: string } | null
  quantity: string | null
}

// Color scheme for entity types
export const entityColors = {
  product: '#f97316', // orange
  supplier: '#3b82f6', // blue
  hub: '#22c55e', // green
  offer: '#f97316' // orange (same as product context)
} as const

// Filter labels cache (to show names instead of UUIDs)
const filterLabels = ref<Record<string, Record<string, string>>>({
  product: {},
  supplier: {},
  hub: {}
})

export function useCatalogSearch() {
  const route = useRoute()
  const router = useRouter()
  const { t } = useI18n()

  // Parse current state from query params
  const selectMode = computed<SelectMode>(() => {
    const select = route.query.select as string | undefined
    if (select === 'product' || select === 'supplier' || select === 'hub') {
      return select
    }
    return null
  })

  // Parse info state from query param (format: "type:uuid")
  const infoId = computed<InfoId | null>(() => {
    const info = route.query.info as string | undefined
    if (!info) return null
    const [type, uuid] = info.split(':')
    if (type && uuid && ['hub', 'supplier', 'offer'].includes(type)) {
      return { type: type as InfoEntityType, uuid }
    }
    return null
  })

  // Info panel tab (stored in URL for sharing)
  const infoTab = computed(() => route.query.infoTab as string | undefined)

  // Info panel selected product (stored in URL for sharing)
  const infoProduct = computed(() => route.query.infoProduct as string | undefined)

  const productId = computed(() => route.query.product as string | undefined)
  const supplierId = computed(() => route.query.supplier as string | undefined)
  const hubId = computed(() => route.query.hub as string | undefined)
  const quantity = computed(() => route.query.qty as string | undefined)

  // Map bounds from URL (format: west,south,east,north)
  const urlBounds = computed((): { west: number; south: number; east: number; north: number } | null => {
    const b = route.query.bounds as string | undefined
    if (!b) return null
    const parts = b.split(',').map(Number)
    if (parts.length !== 4 || parts.some(isNaN)) return null
    return { west: parts[0]!, south: parts[1]!, east: parts[2]!, north: parts[3]! }
  })

  // Filter by bounds checkbox state from URL
  // Use explicit flag so bounds don't auto-enable filtering.
  const filterByBounds = computed(() => route.query.boundsFilter === '1')

  // Get label for a filter (from cache or fallback to ID)
  const getLabel = (type: string, id: string | undefined): string | null => {
    if (!id) return null
    return filterLabels.value[type]?.[id] || id.slice(0, 8) + '...'
  }

  // Set label in cache (trigger reactivity by reassigning)
  const setLabel = (type: string, id: string, label: string) => {
    filterLabels.value = {
      ...filterLabels.value,
      [type]: {
        ...filterLabels.value[type],
        [id]: label
      }
    }
  }

  // Active tokens for display
  const activeTokens = computed(() => {
    const tokens: Array<{ type: string; id: string; label: string; icon: string }> = []

    if (productId.value) {
      tokens.push({
        type: 'product',
        id: productId.value,
        label: getLabel('product', productId.value) || t('catalog.filters.product'),
        icon: 'lucide:package'
      })
    }
    if (supplierId.value) {
      tokens.push({
        type: 'supplier',
        id: supplierId.value,
        label: getLabel('supplier', supplierId.value) || t('catalog.filters.supplier'),
        icon: 'lucide:factory'
      })
    }
    if (hubId.value) {
      tokens.push({
        type: 'hub',
        id: hubId.value,
        label: getLabel('hub', hubId.value) || t('catalog.filters.hub'),
        icon: 'lucide:map-pin'
      })
    }
    if (quantity.value) {
      tokens.push({
        type: 'quantity',
        id: quantity.value,
        label: `${quantity.value} т`,
        icon: 'lucide:scale'
      })
    }

    return tokens
  })

  // Available chips (filters not yet set)
  const availableChips = computed(() => {
    const chips: Array<{ type: string; label: string }> = []

    if (!productId.value && selectMode.value !== 'product') {
      chips.push({ type: 'product', label: t('catalog.filters.product') })
    }
    if (!supplierId.value && selectMode.value !== 'supplier') {
      chips.push({ type: 'supplier', label: t('catalog.filters.supplier') })
    }
    if (!hubId.value && selectMode.value !== 'hub') {
      chips.push({ type: 'hub', label: t('catalog.filters.hub') })
    }
    // Quantity only available after product is selected
    if (productId.value && !quantity.value) {
      chips.push({ type: 'quantity', label: t('catalog.filters.quantity') })
    }

    return chips
  })

  // Determine what content to show
  const displayMode = computed<DisplayMode>(() => {
    // Selection mode takes priority
    if (selectMode.value === 'product') return 'grid-products'
    if (selectMode.value === 'supplier') return 'grid-suppliers'
    if (selectMode.value === 'hub') return 'grid-hubs'

    // Results based on filters
    if (productId.value && hubId.value) return 'grid-offers'
    if (supplierId.value && productId.value) return 'grid-offers'
    if (productId.value) return 'grid-hubs-for-product'
    if (supplierId.value) return 'grid-products-from-supplier'
    if (hubId.value) return 'grid-products-in-hub'

    // Default: show map with all offers
    return 'map-default'
  })

  // Check if we're on the main page (not /catalog)
  const localePath = useLocalePath()
  const isMainPage = computed(() => {
    const catalogPath = localePath('/catalog')
    return !route.path.startsWith(catalogPath)
  })

  // Navigation helpers
  const updateQuery = (updates: Partial<LocationQuery>) => {
    const newQuery = { ...route.query }

    Object.entries(updates).forEach(([key, value]) => {
      if (value === null || value === undefined) {
        delete newQuery[key]
      } else {
        newQuery[key] = value as string
      }
    })

    // If on main page and adding filters, navigate to /catalog
    if (isMainPage.value && Object.keys(newQuery).length > 0) {
      router.push({ path: localePath('/catalog'), query: newQuery })
    } else {
      router.push({ query: newQuery })
    }
  }

  const startSelect = (type: SelectMode) => {
    if (!selectMode.value) {
      lastViewMode.value = mapViewMode.value
    }
    updateQuery({ select: type })
  }

  const cancelSelect = () => {
    updateQuery({
      select: null
    })
  }

  const selectItem = (type: string, id: string, label: string) => {
    setLabel(type, id, label)
    const forcedView = (type === 'hub' || type === 'supplier') ? null : (lastViewMode.value === 'offers' ? null : lastViewMode.value)
    updateQuery({
      [type]: id,
      select: null, // Exit selection mode
      info: null, // Exit info mode
      view: forcedView
    })
  }

  const removeFilter = (type: string) => {
    updateQuery({ [type]: null })
  }

  const editFilter = (type: string) => {
    updateQuery({ select: type as SelectMode })
  }

  const setQuantity = (value: string) => {
    const qty = value ? value : null
    updateQuery({ qty })
  }

  // Set map bounds in URL (for filter by map feature)
  const setBoundsInUrl = (bounds: { west: number; south: number; east: number; north: number } | null) => {
    if (bounds) {
      const boundsStr = `${bounds.west.toFixed(4)},${bounds.south.toFixed(4)},${bounds.east.toFixed(4)},${bounds.north.toFixed(4)}`
      updateQuery({ bounds: boundsStr, boundsFilter: '1' })
    } else {
      updateQuery({ bounds: null })
    }
  }

  // Clear bounds from URL
  const clearBoundsFromUrl = () => {
    updateQuery({ bounds: null, boundsFilter: null })
  }

  // Explicitly enable/disable bounds filter flag in URL
  const setBoundsFilterEnabled = (enabled: boolean) => {
    updateQuery({ boundsFilter: enabled ? '1' : null })
  }

  const openInfo = (type: InfoEntityType, uuid: string) => {
    updateQuery({ info: `${type}:${uuid}`, select: null, infoTab: null, infoProduct: null })
  }

  const closeInfo = () => {
    updateQuery({ info: null, infoTab: null, infoProduct: null })
  }

  const setInfoTab = (tab: string) => {
    updateQuery({ infoTab: tab })
  }

  const setInfoProduct = (productUuid: string | null) => {
    updateQuery({ infoProduct: productUuid })
  }

  const clearAll = () => {
    if (isMainPage.value) {
      router.push({ path: localePath('/catalog'), query: {} })
    } else {
      router.push({ query: {} })
    }
  }

  // Text search (for filtering within current grid) - shared via useState
  const searchQuery = useState<string>('catalog-search-query', () => '')

  // Map view mode (stored in URL query param 'view')
  const mapViewMode = computed<MapViewMode>(() => {
    const view = route.query.view as string | undefined
    if (view === 'hubs' || view === 'suppliers' || view === 'offers') {
      return view
    }
    return 'offers' // default
  })
  const lastViewMode = useState<MapViewMode>('catalog-last-view-mode', () => 'offers')
  const setMapViewMode = (mode: MapViewMode) => {
    const newSelectMode: SelectMode = mode === 'hubs' ? 'hub'
      : mode === 'suppliers' ? 'supplier'
      : 'product'
    updateQuery({
      view: mode === 'offers' ? null : mode,
      select: newSelectMode
    })
  }

  // Drawer state for list view
  const isDrawerOpen = ref(false)
  const drawerSelectedItem = ref<{ uuid: string; name: string } | null>(null)

  const openDrawer = () => {
    isDrawerOpen.value = true
    drawerSelectedItem.value = null

    // Set selectMode based on mapViewMode so SelectionPanel shows the right list
    const newSelectMode: SelectMode = mapViewMode.value === 'hubs' ? 'hub'
      : mapViewMode.value === 'suppliers' ? 'supplier'
      : 'product'
    startSelect(newSelectMode)
  }

  const closeDrawer = () => {
    isDrawerOpen.value = false
    drawerSelectedItem.value = null
    cancelSelect() // Also exit selection mode
  }

  const selectDrawerItem = (uuid: string, name: string) => {
    drawerSelectedItem.value = { uuid, name }
  }

  const applyDrawerFilter = () => {
    if (!drawerSelectedItem.value) {
      closeDrawer()
      return
    }

    // Determine filter type based on mapViewMode
    const type = mapViewMode.value === 'hubs' ? 'hub'
      : mapViewMode.value === 'suppliers' ? 'supplier'
      : 'product' // offers -> select product from offer

    const { uuid, name } = drawerSelectedItem.value
    selectItem(type, uuid, name)
    closeDrawer()
  }

  // Catalog mode: explore (map browsing) or quote (search for offers)
  const catalogMode = computed<CatalogMode>(() => {
    return route.query.mode === 'quote' ? 'quote' : 'explore'
  })

  const setCatalogMode = (newMode: CatalogMode) => {
    const defaultSelect: SelectMode = selectMode.value
      || (mapViewMode.value === 'hubs' ? 'hub'
        : mapViewMode.value === 'suppliers' ? 'supplier'
        : 'product')
    if (newMode === 'explore') {
      updateQuery({ mode: newMode, qty: null, select: defaultSelect })
    } else {
      updateQuery({ mode: newMode, select: defaultSelect })
    }
  }

  // Can search for offers (product + hub or product + supplier required)
  const canSearch = computed(() => {
    return !!(productId.value && (hubId.value || supplierId.value))
  })

  // Labels for Quote mode display
  const productLabel = computed(() => getLabel('product', productId.value))
  const hubLabel = computed(() => getLabel('hub', hubId.value))
  const supplierLabel = computed(() => getLabel('supplier', supplierId.value))

  return {
    // State
    selectMode,
    infoId,
    infoTab,
    infoProduct,
    displayMode,
    catalogMode,
    productId,
    supplierId,
    hubId,
    quantity,
    searchQuery,
    mapViewMode,
    urlBounds,
    filterByBounds,

    // Drawer state
    isDrawerOpen,
    drawerSelectedItem,

    // Colors
    entityColors,

    // Computed
    activeTokens,
    availableChips,
    canSearch,
    productLabel,
    hubLabel,
    supplierLabel,

    // Actions
    startSelect,
    cancelSelect,
    selectItem,
    removeFilter,
    editFilter,
    setQuantity,
    setBoundsInUrl,
    clearBoundsFromUrl,
    setBoundsFilterEnabled,
    openInfo,
    closeInfo,
    setInfoTab,
    setInfoProduct,
    clearAll,
    setLabel,
    setMapViewMode,
    setCatalogMode,

    // Drawer actions
    openDrawer,
    closeDrawer,
    selectDrawerItem,
    applyDrawerFilter,

    // Labels cache
    filterLabels
  }
}
