import { ref, computed, readonly, type Ref } from 'vue'
import type { Product } from '../types/market'

export interface CategoryItem {
  category: string
  count: number
  selected: boolean
}

export interface CategoryFilterOptions {
  caseSensitive?: boolean
  includeEmpty?: boolean
  minCount?: number
  mode?: 'any' | 'all' // OR vs AND logic
}

/**
 * Composable for category filtering functionality
 * Provides reactive category management with optimized performance
 */
export function useCategoryFilter(
  products: Ref<Product[]>,
  options: CategoryFilterOptions = {}
) {
  // Use Set for O(1) lookups instead of array
  const selectedCategories = ref<Set<string>>(new Set())

  // Filter mode state (reactive)
  const filterMode = ref<'any' | 'all'>(options.mode || 'any')

  // Computed property for all available categories with counts
  const allCategories = computed<CategoryItem[]>(() => {
    const categoryMap = new Map<string, number>()

    // Count categories across all products
    products.value.forEach(product => {
      product.categories?.forEach(cat => {
        if (cat && cat.trim()) {
          const category = options.caseSensitive ? cat : cat.toLowerCase()
          categoryMap.set(category, (categoryMap.get(category) || 0) + 1)
        }
      })
    })

    // Convert to CategoryItem array with selection state
    return Array.from(categoryMap.entries())
      .filter(([_, count]) => count >= (options.minCount || 1))
      .map(([category, count]) => ({
        category,
        count,
        selected: selectedCategories.value.has(category)
      }))
      .sort((a, b) => b.count - a.count) // Sort by popularity
  })

  // Optimized product filtering with AND/OR logic
  const filteredProducts = computed<Product[]>(() => {
    const selectedSet = selectedCategories.value

    // Early return if no filters
    if (selectedSet.size === 0) {
      return products.value
    }

    return products.value.filter(product => {
      // Handle empty categories
      if (!product.categories?.length) {
        return options.includeEmpty || false
      }

      // Normalize product categories
      const productCategories = product.categories
        .filter(cat => cat && cat.trim())
        .map(cat => options.caseSensitive ? cat : cat.toLowerCase())

      if (productCategories.length === 0) {
        return options.includeEmpty || false
      }

      // Count matches between product categories and selected categories
      const matchingCategories = productCategories.filter(cat =>
        selectedSet.has(cat)
      )

      // Apply AND/OR logic
      if (filterMode.value === 'all') {
        // AND logic: Product must have ALL selected categories
        return matchingCategories.length === selectedSet.size
      } else {
        // OR logic: Product must have ANY selected category
        return matchingCategories.length > 0
      }
    })
  })

  // Computed properties for UI state
  const selectedCount = computed(() => selectedCategories.value.size)

  const selectedCategoryNames = computed(() =>
    Array.from(selectedCategories.value)
  )

  const hasActiveFilters = computed(() => selectedCategories.value.size > 0)

  // Actions with optimized reactivity
  const toggleCategory = (category: string) => {
    const normalizedCategory = options.caseSensitive ? category : category.toLowerCase()
    const currentSet = selectedCategories.value

    // Create new Set to maintain reactivity (more efficient than copying)
    if (currentSet.has(normalizedCategory)) {
      const newSet = new Set(currentSet)
      newSet.delete(normalizedCategory)
      selectedCategories.value = newSet
    } else {
      const newSet = new Set(currentSet)
      newSet.add(normalizedCategory)
      selectedCategories.value = newSet
    }
  }

  const addCategory = (category: string) => {
    const normalizedCategory = options.caseSensitive ? category : category.toLowerCase()
    const newSet = new Set(selectedCategories.value)
    newSet.add(normalizedCategory)
    selectedCategories.value = newSet
  }

  const removeCategory = (category: string) => {
    const normalizedCategory = options.caseSensitive ? category : category.toLowerCase()
    const newSet = new Set(selectedCategories.value)
    newSet.delete(normalizedCategory)
    selectedCategories.value = newSet
  }

  const clearAllCategories = () => {
    selectedCategories.value = new Set() // Create new empty Set
  }

  const selectMultipleCategories = (categories: string[]) => {
    const newSet = new Set(selectedCategories.value)
    categories.forEach(cat => {
      const normalizedCategory = options.caseSensitive ? cat : cat.toLowerCase()
      newSet.add(normalizedCategory)
    })
    selectedCategories.value = newSet
  }

  const isSelected = (category: string): boolean => {
    const normalizedCategory = options.caseSensitive ? category : category.toLowerCase()
    return selectedCategories.value.has(normalizedCategory)
  }

  const setFilterMode = (mode: 'any' | 'all') => {
    filterMode.value = mode
  }

  const toggleFilterMode = () => {
    filterMode.value = filterMode.value === 'any' ? 'all' : 'any'
  }

  // Category statistics
  const categoryStats = computed(() => ({
    totalCategories: allCategories.value.length,
    selectedCategories: selectedCategories.value.size,
    filteredProductCount: filteredProducts.value.length,
    totalProductCount: products.value.length
  }))

  return {
    // State (readonly to prevent external mutation)
    selectedCategories: readonly(selectedCategories),
    filterMode: readonly(filterMode),
    allCategories,
    filteredProducts,
    selectedCount,
    selectedCategoryNames,
    hasActiveFilters,
    categoryStats,

    // Actions
    toggleCategory,
    addCategory,
    removeCategory,
    clearAllCategories,
    selectMultipleCategories,
    isSelected,
    setFilterMode,
    toggleFilterMode
  }
}

export default useCategoryFilter