/**
 * Composable for pull-to-refresh functionality
 *
 * Works on both mobile web and Capacitor apps.
 * Provides touch gesture detection and visual feedback.
 *
 * @example
 * const { isRefreshing, pullToRefreshProps } = usePullToRefresh({
 *   onRefresh: async () => {
 *     await refresh()
 *   }
 * })
 */

import { useEventListener } from '@vueuse/core'

interface UsePullToRefreshOptions {
  /**
   * Callback function to execute when pull-to-refresh is triggered
   */
  onRefresh: () => Promise<void> | void
  /**
   * Threshold in pixels before triggering refresh (default: 80)
   */
  threshold?: number
  /**
   * Whether pull-to-refresh is enabled (default: true)
   */
  enabled?: boolean
}

export function usePullToRefresh(options: UsePullToRefreshOptions) {
  const { onRefresh, threshold = 80, enabled = true } = options

  const isRefreshing = ref(false)
  const pullDistance = ref(0)
  const startY = ref(0)
  const isPulling = ref(false)
  const elementRef = ref<HTMLElement | null>(null)

  // Only enable on mobile devices (touch-capable)
  const isMobile = computed(() => {
    if (!import.meta.client) return false
    return 'ontouchstart' in window || navigator.maxTouchPoints > 0
  })

  const canPull = computed(() => {
    if (!enabled || !isMobile.value || isRefreshing.value) return false
    if (!import.meta.client) return false

    // Only allow pull-to-refresh when scrolled to the top of the page
    const scrollTop = window.scrollY || document.documentElement.scrollTop || 0
    return scrollTop === 0
  })

  const handleTouchStart = (e: TouchEvent) => {
    if (!canPull.value || !e.touches[0]) return

    startY.value = e.touches[0].clientY
    isPulling.value = true
  }

  const handleTouchMove = (e: TouchEvent) => {
    if (!isPulling.value || !canPull.value || !e.touches[0]) return

    const currentY = e.touches[0].clientY
    const deltaY = currentY - startY.value

    // Only allow pulling down (positive deltaY)
    if (deltaY > 0) {
      // Apply resistance when pulling beyond threshold
      const resistance = deltaY > threshold ? 0.5 : 1
      pullDistance.value = Math.min(deltaY * resistance, threshold * 1.5)

      // Prevent default scrolling when pulling
      if (pullDistance.value > 10) {
        e.preventDefault()
      }
    } else {
      pullDistance.value = 0
    }
  }

  const handleTouchEnd = async () => {
    if (!isPulling.value) return

    isPulling.value = false

    // Trigger refresh if pulled beyond threshold
    if (pullDistance.value >= threshold) {
      isRefreshing.value = true
      pullDistance.value = threshold // Keep visual feedback during refresh

      try {
        await onRefresh()
      } finally {
        // Animate back to top
        pullDistance.value = 0
        isRefreshing.value = false
      }
    } else {
      // Animate back to top if not enough pull
      pullDistance.value = 0
    }
  }

  // Set up event listeners on window for page-level scrolling
  if (import.meta.client) {
    useEventListener(window, 'touchstart', handleTouchStart, { passive: true })
    useEventListener(window, 'touchmove', handleTouchMove, { passive: false })
    useEventListener(window, 'touchend', handleTouchEnd, { passive: true })
    useEventListener(window, 'touchcancel', handleTouchEnd, { passive: true })
  }

  // Computed style for pull indicator
  const pullStyle = computed(() => {
    if (pullDistance.value === 0) return {}
    return {
      transform: `translateY(${pullDistance.value}px)`,
      transition: isRefreshing.value ? 'transform 0.3s ease-out' : 'none'
    }
  })

  // Computed opacity for pull indicator
  const pullOpacity = computed(() => {
    if (pullDistance.value === 0) return 0
    return Math.min(pullDistance.value / threshold, 1)
  })

  return {
    /**
     * Ref to attach to the scrollable container element
     */
    elementRef,
    /**
     * Whether refresh is currently in progress
     */
    isRefreshing: readonly(isRefreshing),
    /**
     * Current pull distance in pixels
     */
    pullDistance: readonly(pullDistance),
    /**
     * Whether user is currently pulling
     */
    isPulling: readonly(isPulling),
    /**
     * Whether pull-to-refresh is enabled and available
     */
    canPull: readonly(canPull),
    /**
     * Style object for pull indicator animation
     */
    pullStyle,
    /**
     * Opacity for pull indicator (0-1)
     */
    pullOpacity,
    /**
     * Pull distance value for direct use in templates
     */
    pullDistanceValue: computed(() => pullDistance.value)
  }
}
