'use client';

/**
 * UX Hooks Collection
 * 
 * - Haptic feedback
 * - Pull to refresh
 * - Swipe actions
 * - App badging
 */

import { useCallback, useRef, useState, useEffect } from 'react';

// ============================================
// Haptic Feedback Hook
// ============================================

type HapticPattern = 'success' | 'error' | 'warning' | 'light' | 'medium' | 'heavy' | number[];

const HAPTIC_PATTERNS: Record<string, number[]> = {
  success: [50, 30, 50],
  error: [100, 50, 100, 50, 100],
  warning: [100, 100],
  light: [30],
  medium: [50],
  heavy: [100],
};

export function useHaptic() {
  const vibrate = useCallback((pattern: HapticPattern = 'medium') => {
    if (!navigator.vibrate) return false;

    const vibrationPattern = Array.isArray(pattern) 
      ? pattern 
      : HAPTIC_PATTERNS[pattern] || [50];

    try {
      navigator.vibrate(vibrationPattern);
      return true;
    } catch {
      return false;
    }
  }, []);

  const success = useCallback(() => vibrate('success'), [vibrate]);
  const error = useCallback(() => vibrate('error'), [vibrate]);
  const warning = useCallback(() => vibrate('warning'), [vibrate]);
  const light = useCallback(() => vibrate('light'), [vibrate]);
  const medium = useCallback(() => vibrate('medium'), [vibrate]);
  const heavy = useCallback(() => vibrate('heavy'), [vibrate]);

  return { vibrate, success, error, warning, light, medium, heavy };
}

// ============================================
// Pull to Refresh Hook
// ============================================

interface PullToRefreshOptions {
  onRefresh: () => Promise<void>;
  threshold?: number;
  resistance?: number;
}

export function usePullToRefresh({
  onRefresh,
  threshold = 80,
  resistance = 2.5,
}: PullToRefreshOptions) {
  const [isPulling, setIsPulling] = useState(false);
  const [isRefreshing, setIsRefreshing] = useState(false);
  const [pullDistance, setPullDistance] = useState(0);
  
  const startY = useRef(0);
  const containerRef = useRef<HTMLDivElement>(null);

  const handleTouchStart = useCallback((e: TouchEvent) => {
    if (containerRef.current && containerRef.current.scrollTop === 0) {
      startY.current = e.touches[0].clientY;
      setIsPulling(true);
    }
  }, []);

  const handleTouchMove = useCallback((e: TouchEvent) => {
    if (!isPulling || isRefreshing) return;

    const currentY = e.touches[0].clientY;
    const diff = (currentY - startY.current) / resistance;

    if (diff > 0) {
      setPullDistance(Math.min(diff, threshold * 1.5));
      
      // Prevent default scroll when pulling
      if (containerRef.current?.scrollTop === 0) {
        e.preventDefault();
      }
    }
  }, [isPulling, isRefreshing, resistance, threshold]);

  const handleTouchEnd = useCallback(async () => {
    if (!isPulling) return;

    if (pullDistance >= threshold && !isRefreshing) {
      setIsRefreshing(true);
      setPullDistance(threshold);

      // Haptic feedback
      if (navigator.vibrate) {
        navigator.vibrate(50);
      }

      try {
        await onRefresh();
      } finally {
        setIsRefreshing(false);
      }
    }

    setIsPulling(false);
    setPullDistance(0);
  }, [isPulling, pullDistance, threshold, isRefreshing, onRefresh]);

  useEffect(() => {
    const container = containerRef.current;
    if (!container) return;

    container.addEventListener('touchstart', handleTouchStart, { passive: true });
    container.addEventListener('touchmove', handleTouchMove, { passive: false });
    container.addEventListener('touchend', handleTouchEnd);

    return () => {
      container.removeEventListener('touchstart', handleTouchStart);
      container.removeEventListener('touchmove', handleTouchMove);
      container.removeEventListener('touchend', handleTouchEnd);
    };
  }, [handleTouchStart, handleTouchMove, handleTouchEnd]);

  const progress = Math.min(pullDistance / threshold, 1);

  return {
    containerRef,
    isPulling,
    isRefreshing,
    pullDistance,
    progress,
  };
}

// ============================================
// Swipe Actions Hook
// ============================================

type SwipeDirection = 'left' | 'right';

interface SwipeActionsOptions {
  onSwipeLeft?: () => void;
  onSwipeRight?: () => void;
  threshold?: number;
}

export function useSwipeActions({
  onSwipeLeft,
  onSwipeRight,
  threshold = 80,
}: SwipeActionsOptions) {
  const [swipeOffset, setSwipeOffset] = useState(0);
  const [isSwipingLeft, setIsSwipingLeft] = useState(false);
  const [isSwipingRight, setIsSwipingRight] = useState(false);
  
  const startX = useRef(0);
  const startY = useRef(0);
  const elementRef = useRef<HTMLDivElement>(null);
  const isHorizontalSwipe = useRef<boolean | null>(null);

  const handleTouchStart = useCallback((e: React.TouchEvent) => {
    startX.current = e.touches[0].clientX;
    startY.current = e.touches[0].clientY;
    isHorizontalSwipe.current = null;
  }, []);

  const handleTouchMove = useCallback((e: React.TouchEvent) => {
    const currentX = e.touches[0].clientX;
    const currentY = e.touches[0].clientY;
    const diffX = currentX - startX.current;
    const diffY = currentY - startY.current;

    // Determine swipe direction on first significant movement
    if (isHorizontalSwipe.current === null) {
      if (Math.abs(diffX) > 10 || Math.abs(diffY) > 10) {
        isHorizontalSwipe.current = Math.abs(diffX) > Math.abs(diffY);
      }
    }

    // Only handle horizontal swipes
    if (isHorizontalSwipe.current) {
      e.preventDefault();
      
      // Limit swipe range
      const clampedOffset = Math.max(-threshold * 1.2, Math.min(threshold * 1.2, diffX));
      setSwipeOffset(clampedOffset);
      setIsSwipingLeft(clampedOffset < -threshold * 0.3);
      setIsSwipingRight(clampedOffset > threshold * 0.3);
    }
  }, [threshold]);

  const handleTouchEnd = useCallback(() => {
    if (swipeOffset <= -threshold && onSwipeLeft) {
      onSwipeLeft();
      // Haptic feedback
      if (navigator.vibrate) navigator.vibrate(50);
    } else if (swipeOffset >= threshold && onSwipeRight) {
      onSwipeRight();
      // Haptic feedback
      if (navigator.vibrate) navigator.vibrate(50);
    }

    // Reset
    setSwipeOffset(0);
    setIsSwipingLeft(false);
    setIsSwipingRight(false);
    isHorizontalSwipe.current = null;
  }, [swipeOffset, threshold, onSwipeLeft, onSwipeRight]);

  return {
    elementRef,
    swipeOffset,
    isSwipingLeft,
    isSwipingRight,
    handlers: {
      onTouchStart: handleTouchStart,
      onTouchMove: handleTouchMove,
      onTouchEnd: handleTouchEnd,
    },
  };
}

// ============================================
// App Badging Hook
// ============================================

export function useAppBadge() {
  const [badgeCount, setBadgeCount] = useState(0);
  const [isSupported, setIsSupported] = useState(false);

  useEffect(() => {
    // Check if Badge API is supported
    setIsSupported('setAppBadge' in navigator);
  }, []);

  const setBadge = useCallback(async (count: number) => {
    setBadgeCount(count);

    if (!('setAppBadge' in navigator)) return;

    try {
      if (count > 0) {
        // @ts-ignore - Badge API
        await navigator.setAppBadge(count);
      } else {
        // @ts-ignore - Badge API
        await navigator.clearAppBadge();
      }
    } catch (error) {
      console.error('Failed to set app badge:', error);
    }
  }, []);

  const clearBadge = useCallback(async () => {
    setBadgeCount(0);

    if (!('clearAppBadge' in navigator)) return;

    try {
      // @ts-ignore - Badge API
      await navigator.clearAppBadge();
    } catch (error) {
      console.error('Failed to clear app badge:', error);
    }
  }, []);

  const incrementBadge = useCallback(async (amount: number = 1) => {
    await setBadge(badgeCount + amount);
  }, [badgeCount, setBadge]);

  return {
    badgeCount,
    isSupported,
    setBadge,
    clearBadge,
    incrementBadge,
  };
}

// ============================================
// Form State Recovery Hook
// ============================================

interface FormState {
  [key: string]: any;
}

export function useFormRecovery<T extends FormState>(
  formKey: string,
  initialState: T
) {
  const [formState, setFormState] = useState<T>(initialState);
  const [hasRecovered, setHasRecovered] = useState(false);

  // Load saved state on mount
  useEffect(() => {
    try {
      const saved = sessionStorage.getItem(`form_recovery_${formKey}`);
      if (saved) {
        const parsed = JSON.parse(saved);
        setFormState(parsed);
        setHasRecovered(true);
      }
    } catch {
      // Ignore errors
    }
  }, [formKey]);

  // Save state on change
  useEffect(() => {
    try {
      sessionStorage.setItem(`form_recovery_${formKey}`, JSON.stringify(formState));
    } catch {
      // Ignore errors
    }
  }, [formKey, formState]);

  // Update a single field
  const updateField = useCallback(<K extends keyof T>(field: K, value: T[K]) => {
    setFormState(prev => ({ ...prev, [field]: value }));
  }, []);

  // Clear saved state
  const clearRecovery = useCallback(() => {
    try {
      sessionStorage.removeItem(`form_recovery_${formKey}`);
      setFormState(initialState);
      setHasRecovered(false);
    } catch {
      // Ignore errors
    }
  }, [formKey, initialState]);

  // Dismiss recovery notification
  const dismissRecovery = useCallback(() => {
    setHasRecovered(false);
  }, []);

  return {
    formState,
    setFormState,
    updateField,
    hasRecovered,
    clearRecovery,
    dismissRecovery,
  };
}
