/**
 * useChartData Composable
 *
 * 封装图表数据的加载、转换、缓存等操作
 */

import { ref, computed } from 'vue'
import type { Ref } from 'vue'

/**
 * 使用图表数据的 Composable
 *
 * @param apiMethod 数据加载方法
 */
export function useChartData<T = any>(apiMethod?: (params?: any) => Promise<T>) {
  const data = ref<T>(null as unknown as T)
  const loading = ref(false)
  const error = ref<Error | null>(null)
  const cache = ref<Map<string, { data: T; timestamp: number }>>(new Map())
  const cacheExpiry = ref(5 * 60 * 1000) // 默认缓存5分钟

  /**
   * 加载数据
   */
  const loadData = async (params?: any, options?: {
    useCache?: boolean
    cacheKey?: string
    showLoading?: boolean
  }) => {
    if (!apiMethod) {
      console.warn('[useChartData] No API method provided')
      return null
    }

    const {
      useCache: shouldUseCache = true,
      cacheKey: customCacheKey,
      showLoading: shouldShowLoading = true,
    } = options || {}

    // 生成缓存键
    const cacheKey = customCacheKey || JSON.stringify(params || {})

    // 检查缓存
    if (shouldUseCache) {
      const cached = cache.value.get(cacheKey)
      if (cached && Date.now() - cached.timestamp < cacheExpiry.value) {
        console.log('[useChartData] Using cached data:', cacheKey)
        data.value = cached.data
        return cached.data
      }
    }

    // 加载数据
    if (shouldShowLoading) {
      loading.value = true
    }
    error.value = null

    try {
      const result = await apiMethod(params)
      data.value = result

      // 更新缓存
      if (shouldUseCache) {
        cache.value.set(cacheKey, {
          data: result,
          timestamp: Date.now(),
        })
      }

      console.log('[useChartData] Data loaded successfully')
      return result
    } catch (err) {
      const errorObj = err instanceof Error ? err : new Error(String(err))
      error.value = errorObj
      console.error('[useChartData] Failed to load data:', errorObj)
      throw errorObj
    } finally {
      if (shouldShowLoading) {
        loading.value = false
      }
    }
  }

  /**
   * 刷新数据
   */
  const refresh = (params?: any) => {
    return loadData(params, { useCache: false })
  }

  /**
   * 清除缓存
   */
  const clearCache = (cacheKey?: string) => {
    if (cacheKey) {
      cache.value.delete(cacheKey)
      console.log('[useChartData] Cache cleared for key:', cacheKey)
    } else {
      cache.value.clear()
      console.log('[useChartData] All cache cleared')
    }
  }

  /**
   * 设置缓存过期时间
   */
  const setCacheExpiry = (milliseconds: number) => {
    cacheExpiry.value = milliseconds
  }

  /**
   * 重置状态
   */
  const reset = () => {
    data.value = null as unknown as T
    loading.value = false
    error.value = null
  }

  /**
   * 转换数据为图表格式
   */
  const transformToChartData = (
    rawData: any[],
    config: {
      nameKey?: string
      valueKey?: string
      filter?: (item: any) => boolean
      sort?: 'asc' | 'desc' | ((a: any, b: any) => number)
    } = {}
  ) => {
    const {
      nameKey = 'name',
      valueKey = 'value',
      filter,
      sort,
    } = config

    let result = rawData.map(item => ({
      name: item[nameKey],
      value: item[valueKey],
      ...item,
    }))

    // 过滤
    if (filter) {
      result = result.filter(filter)
    }

    // 排序
    if (sort === 'asc') {
      result.sort((a, b) => a.value - b.value)
    } else if (sort === 'desc') {
      result.sort((a, b) => b.value - a.value)
    } else if (typeof sort === 'function') {
      result.sort(sort)
    }

    return result
  }

  /**
   * 计算百分比
   */
  const calculatePercentages = (
    items: Array<{ value: number }>
  ) => {
    const total = items.reduce((sum, item) => sum + item.value, 0)
    return items.map(item => ({
      ...item,
      percentage: total > 0 ? (item.value / total) * 100 : 0,
    }))
  }

  /**
   * 分组聚合
   */
  const groupBy = (
    items: any[],
    key: string,
    aggregate: 'sum' | 'count' | 'avg' = 'count'
  ) => {
    const groups = new Map<string, number[]>()

    items.forEach(item => {
      const groupKey = item[key]
      if (!groups.has(groupKey)) {
        groups.set(groupKey, [])
      }
      groups.get(groupKey)!.push(item.value || 1)
    })

    return Array.from(groups.entries()).map(([name, values]) => {
      let value: number
      if (aggregate === 'sum') {
        value = values.reduce((sum, v) => sum + v, 0)
      } else if (aggregate === 'avg') {
        value = values.reduce((sum, v) => sum + v, 0) / values.length
      } else {
        value = values.length
      }
      return { name, value }
    })
  }

  return {
    data,
    loading,
    error,
    isLoaded: computed(() => data.value !== null),
    hasError: computed(() => error.value !== null),
    loadData,
    refresh,
    clearCache,
    setCacheExpiry,
    reset,
    transformToChartData,
    calculatePercentages,
    groupBy,
  }
}
