export interface DataProcessor<T = any> {
  filter: (data: T[], predicate: (item: T) => boolean) => T[]
  sort: (data: T[], key: keyof T, direction?: 'asc' | 'desc') => T[]
  group: (data: T[], key: keyof T) => Record<string, T[]>
  aggregate: (data: T[], key: keyof T, operation: 'sum' | 'avg' | 'min' | 'max' | 'count') => number
  paginate: (data: T[], page: number, pageSize: number) => T[]
  search: (data: T[], query: string, searchKeys?: (keyof T)[]) => T[]
  transform: <U>(data: T[], transformer: (item: T) => U) => U[]
}

export function createDataProcessor<T = any>(): DataProcessor<T> {
  return {
    filter: (data: T[], predicate: (item: T) => boolean) => {
      return data.filter(predicate)
    },

    sort: (data: T[], key: keyof T, direction: 'asc' | 'desc' = 'asc') => {
      return [...data].sort((a, b) => {
        const aVal = a[key]
        const bVal = b[key]
        
        if (aVal === bVal) return 0
        
        const comparison = aVal < bVal ? -1 : 1
        return direction === 'asc' ? comparison : -comparison
      })
    },

    group: (data: T[], key: keyof T) => {
      return data.reduce((groups, item) => {
        const groupKey = String(item[key])
        if (!groups[groupKey]) {
          groups[groupKey] = []
        }
        groups[groupKey].push(item)
        return groups
      }, {} as Record<string, T[]>)
    },

    aggregate: (data: T[], key: keyof T, operation: 'sum' | 'avg' | 'min' | 'max' | 'count') => {
      const values = data.map(item => Number(item[key])).filter(val => !isNaN(val))
      
      if (values.length === 0) return 0
      
      switch (operation) {
        case 'sum':
          return values.reduce((sum, val) => sum + val, 0)
        case 'avg':
          return values.reduce((sum, val) => sum + val, 0) / values.length
        case 'min':
          return Math.min(...values)
        case 'max':
          return Math.max(...values)
        case 'count':
          return values.length
        default:
          return 0
      }
    },

    paginate: (data: T[], page: number, pageSize: number) => {
      const startIndex = (page - 1) * pageSize
      const endIndex = startIndex + pageSize
      return data.slice(startIndex, endIndex)
    },

    search: (data: T[], query: string, searchKeys?: (keyof T)[]) => {
      if (!query.trim()) return data
      
      const lowerQuery = query.toLowerCase()
      
      return data.filter(item => {
        const keysToSearch = searchKeys || Object.keys(item as Record<string, any>) as (keyof T)[]
        
        return keysToSearch.some(key => {
          const value = item[key]
          if (value == null) return false
          return String(value).toLowerCase().includes(lowerQuery)
        })
      })
    },

    transform: <U>(data: T[], transformer: (item: T) => U) => {
      return data.map(transformer)
    }
  }
}

// Utility functions for common data operations
export function calculatePercentageChange(current: number, previous: number): number {
  if (previous === 0) return current > 0 ? 100 : 0
  return ((current - previous) / previous) * 100
}

export function formatNumber(value: number, options?: {
  decimals?: number
  currency?: string
  percentage?: boolean
  compact?: boolean
}): string {
  const { decimals = 2, currency, percentage = false, compact = false } = options || {}
  
  if (percentage) {
    return `${value.toFixed(decimals)}%`
  }
  
  if (currency) {
    return new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency,
      minimumFractionDigits: decimals,
      maximumFractionDigits: decimals,
    }).format(value)
  }
  
  if (compact && Math.abs(value) >= 1000) {
    return new Intl.NumberFormat('en-US', {
      notation: 'compact',
      minimumFractionDigits: 0,
      maximumFractionDigits: 1,
    }).format(value)
  }
  
  return value.toFixed(decimals)
}

export function generateDateRange(start: Date, end: Date, interval: 'day' | 'week' | 'month' = 'day'): Date[] {
  const dates: Date[] = []
  const current = new Date(start)
  
  while (current <= end) {
    dates.push(new Date(current))
    
    switch (interval) {
      case 'day':
        current.setDate(current.getDate() + 1)
        break
      case 'week':
        current.setDate(current.getDate() + 7)
        break
      case 'month':
        current.setMonth(current.getMonth() + 1)
        break
    }
  }
  
  return dates
}

// debounce function removed to avoid conflicts with @moontra/moonui
// Use debounce from @moontra/moonui instead
