import { vi, afterEach } from 'vitest'
import React from 'react'

// Extend globals
vi.stubGlobal('vi', vi)

// Mock React Native core
vi.mock('react-native', () => {
  const RN = vi.importActual('react-native')
  return {
    ...RN,
    Alert: {
      alert: vi.fn(),
    },
    Platform: {
      OS: 'ios',
      select: vi.fn((obj) => obj.ios),
    },
    StyleSheet: {
      create: (styles: any) => styles,
      hairlineWidth: 1,
    },
    Dimensions: {
      get: vi.fn(() => ({ width: 375, height: 812 })),
      addEventListener: vi.fn(() => ({ remove: vi.fn() })),
    },
    View: 'View',
    Text: 'Text',
    TouchableOpacity: 'TouchableOpacity',
    Pressable: 'Pressable',
    Image: 'Image',
    ScrollView: 'ScrollView',
    FlatList: 'FlatList',
    ActivityIndicator: 'ActivityIndicator',
    SafeAreaView: 'SafeAreaView',
    Easing: {
      linear: vi.fn((v: number) => v),
      ease: vi.fn((v: number) => v),
      bezier: vi.fn(() => vi.fn((v: number) => v)),
      quad: vi.fn((v: number) => v),
      cubic: vi.fn((v: number) => v),
      poly: vi.fn(() => vi.fn((v: number) => v)),
      sin: vi.fn((v: number) => v),
      circle: vi.fn((v: number) => v),
      exp: vi.fn((v: number) => v),
      elastic: vi.fn(() => vi.fn((v: number) => v)),
      back: vi.fn(() => vi.fn((v: number) => v)),
      bounce: vi.fn((v: number) => v),
      in: vi.fn((easing: any) => easing),
      out: vi.fn((easing: any) => easing),
      inOut: vi.fn((easing: any) => easing),
    },
    Animated: {
      Value: vi.fn(() => ({
        interpolate: vi.fn(() => 0),
        setValue: vi.fn(),
      })),
      View: 'Animated.View',
      Text: 'Animated.Text',
      Image: 'Animated.Image',
      ScrollView: 'Animated.ScrollView',
      FlatList: 'Animated.FlatList',
      createAnimatedComponent: vi.fn((comp: any) => comp),
      timing: vi.fn(() => ({ start: vi.fn() })),
      spring: vi.fn(() => ({ start: vi.fn() })),
      decay: vi.fn(() => ({ start: vi.fn() })),
      sequence: vi.fn(() => ({ start: vi.fn() })),
      parallel: vi.fn(() => ({ start: vi.fn() })),
      loop: vi.fn(() => ({ start: vi.fn() })),
      event: vi.fn(),
      add: vi.fn(),
      multiply: vi.fn(),
      diffClamp: vi.fn(),
    },
  }
})

// Mock expo modules
vi.mock('expo-constants', () => ({
  default: {
    expoConfig: { version: '1.0.0' },
    systemFonts: [],
  },
}))

vi.mock('expo-linking', () => ({
  default: {
    openURL: vi.fn(),
    createURL: vi.fn(),
  },
}))

vi.mock('expo-haptics', () => ({
  impactAsync: vi.fn(),
  ImpactFeedbackStyle: {
    Light: 'light',
    Medium: 'medium',
    Heavy: 'heavy',
  },
  notificationAsync: vi.fn(),
  NotificationFeedbackType: {
    Success: 'success',
    Warning: 'warning',
    Error: 'error',
  },
}))

vi.mock('expo-av', () => ({
  Audio: {
    Sound: {
      createAsync: vi.fn().mockResolvedValue({
        sound: {
          playAsync: vi.fn(),
          pauseAsync: vi.fn(),
          stopAsync: vi.fn(),
          unloadAsync: vi.fn(),
          setPositionAsync: vi.fn(),
          setVolumeAsync: vi.fn(),
        },
        status: { isLoaded: true },
      }),
    },
    setAudioModeAsync: vi.fn(),
  },
  Video: 'Video',
}))

vi.mock('expo-video', () => ({
  useVideoPlayer: vi.fn(() => ({
    play: vi.fn(),
    pause: vi.fn(),
    replace: vi.fn(),
    currentTime: 0,
    duration: 100,
    playing: false,
    muted: false,
    volume: 1,
  })),
  VideoView: 'VideoView',
  VideoSource: vi.fn(),
}))

vi.mock('expo-image', () => ({
  Image: 'Image',
}))

vi.mock('expo-linear-gradient', () => ({
  LinearGradient: 'LinearGradient',
}))

vi.mock('expo-blur', () => ({
  BlurView: 'BlurView',
}))

vi.mock('expo-router', () => ({
  useRouter: vi.fn(() => ({
    push: vi.fn(),
    replace: vi.fn(),
    back: vi.fn(),
  })),
  useLocalSearchParams: vi.fn(() => ({})),
  Link: 'Link',
  Stack: {
    Screen: 'Screen',
  },
  Tabs: {
    Tab: 'Tab',
  },
}))

vi.mock('expo-localization', () => ({
  getLocales: vi.fn(() => [{ languageTag: 'en-US' }]),
}))

vi.mock('expo-keep-awake', () => ({
  activateKeepAwakeAsync: vi.fn(),
  deactivateKeepAwake: vi.fn(),
}))

vi.mock('expo-notifications', () => ({
  scheduleNotificationAsync: vi.fn(),
  cancelScheduledNotificationAsync: vi.fn(),
  getAllScheduledNotificationsAsync: vi.fn().mockResolvedValue([]),
  setNotificationHandler: vi.fn(),
}))

vi.mock('expo-splash-screen', () => ({
  preventAutoHideAsync: vi.fn(),
  hideAsync: vi.fn(),
}))

vi.mock('expo-font', () => ({
  loadAsync: vi.fn(),
}))

vi.mock('expo-file-system', () => ({
  documentDirectory: '/tmp/',
  cacheDirectory: '/tmp/cache/',
  readAsStringAsync: vi.fn(),
  writeAsStringAsync: vi.fn(),
  deleteAsync: vi.fn(),
  getInfoAsync: vi.fn().mockResolvedValue({ exists: false }),
}))

vi.mock('expo-device', () => ({
  isDevice: true,
  model: 'iPhone 15',
}))

vi.mock('expo-application', () => ({
  nativeApplicationVersion: '1.0.0',
  nativeBuildVersion: '1',
}))

// Mock AsyncStorage
vi.mock('@react-native-async-storage/async-storage', () => ({
  default: {
    getItem: vi.fn().mockResolvedValue(null),
    setItem: vi.fn().mockResolvedValue(undefined),
    removeItem: vi.fn().mockResolvedValue(undefined),
    clear: vi.fn().mockResolvedValue(undefined),
    getAllKeys: vi.fn().mockResolvedValue([]),
  },
}))

// Mock react-native-purchases (RevenueCat)
vi.mock('react-native-purchases', () => ({
  default: {
    configure: vi.fn().mockResolvedValue(undefined),
    getOfferings: vi.fn().mockResolvedValue({
      current: {
        monthly: {
          identifier: 'monthly',
          product: {
            identifier: 'tabatafit.premium.monthly',
            priceString: '$9.99',
          },
        },
        annual: {
          identifier: 'annual',
          product: {
            identifier: 'tabatafit.premium.yearly',
            priceString: '$79.99',
          },
        },
      },
    }),
    getCustomerInfo: vi.fn().mockResolvedValue({
      entitlements: { active: {}, all: {} },
      activeSubscriptions: [],
      allPurchasedProductIdentifiers: [],
    }),
    purchasePackage: vi.fn().mockResolvedValue({
      customerInfo: {
        entitlements: { active: {}, all: {} },
        activeSubscriptions: [],
      },
    }),
    restorePurchases: vi.fn().mockResolvedValue({
      entitlements: { active: {}, all: {} },
      activeSubscriptions: [],
    }),
    addCustomerInfoUpdateListener: vi.fn(),
    removeCustomerInfoUpdateListener: vi.fn(),
    setLogLevel: vi.fn(),
    LOG_LEVEL: {
      VERBOSE: 'verbose',
      DEBUG: 'debug',
      INFO: 'info',
      WARN: 'warn',
      ERROR: 'error',
    },
  },
  LOG_LEVEL: {
    VERBOSE: 'verbose',
    DEBUG: 'debug',
    INFO: 'info',
    WARN: 'warn',
    ERROR: 'error',
  },
}))

// Mock react-native-reanimated
vi.mock('react-native-reanimated', () => ({
  default: {
    createAnimatedComponent: (comp: any) => comp,
    View: 'View',
    Text: 'Text',
    Image: 'Image',
    ScrollView: 'ScrollView',
  },
  useAnimatedStyle: vi.fn(() => ({})),
  useSharedValue: vi.fn(() => ({ value: 0 })),
  withSpring: vi.fn((v) => v),
  withTiming: vi.fn((v) => v),
  withRepeat: vi.fn((v) => v),
  withSequence: vi.fn((...v) => v[0]),
  withDelay: vi.fn((_, v) => v),
  Easing: {
    linear: vi.fn(),
    ease: vi.fn(),
    bezier: vi.fn(),
  },
  runOnJS: vi.fn((fn) => fn),
}))

// Mock react-native-gesture-handler
vi.mock('react-native-gesture-handler', () => ({
  Gesture: {
    Pan: vi.fn(() => ({ onStart: vi.fn(), onUpdate: vi.fn(), onEnd: vi.fn() })),
    Tap: vi.fn(() => ({ onStart: vi.fn(), onEnd: vi.fn() })),
  },
  GestureDetector: 'GestureDetector',
  PanGestureHandler: 'PanGestureHandler',
  TapGestureHandler: 'TapGestureHandler',
  State: {},
}))

// Mock react-native-screens
vi.mock('react-native-screens', () => ({
  enableScreens: vi.fn(),
}))

// Mock react-native-safe-area-context
vi.mock('react-native-safe-area-context', () => ({
  SafeAreaProvider: ({ children }: { children: React.ReactNode }) => children,
  useSafeAreaInsets: vi.fn(() => ({ top: 44, bottom: 34, left: 0, right: 0 })),
  SafeAreaView: 'SafeAreaView',
}))

// Mock react-native-svg
vi.mock('react-native-svg', () => ({
  Svg: 'Svg',
  Path: 'Path',
  Circle: 'Circle',
  Rect: 'Rect',
  G: 'G',
  Defs: 'Defs',
  Use: 'Use',
}))

// Mock Supabase
vi.mock('@/src/shared/supabase', () => ({
  supabase: {
    auth: {
      signInAnonymously: vi.fn().mockResolvedValue({
        data: { user: { id: 'test-user-id' } },
        error: null,
      }),
      getUser: vi.fn().mockResolvedValue({
        data: { user: { id: 'test-user-id' } },
      }),
      getSession: vi.fn().mockResolvedValue({
        data: { session: { user: { id: 'test-user-id' } } },
      }),
      signOut: vi.fn().mockResolvedValue({ error: null }),
    },
    from: vi.fn(() => ({
      insert: vi.fn().mockResolvedValue({ error: null }),
      select: vi.fn().mockReturnThis(),
      eq: vi.fn().mockReturnThis(),
      order: vi.fn().mockReturnThis(),
      limit: vi.fn().mockResolvedValue({ data: [], error: null }),
      delete: vi.fn().mockReturnThis(),
      update: vi.fn().mockReturnThis(),
    })),
  },
}))

// Mock PostHog
vi.mock('posthog-react-native', () => ({
  PostHogProvider: ({ children }: { children: React.ReactNode }) => children,
  usePostHog: vi.fn(() => ({
    capture: vi.fn(),
    identify: vi.fn(),
    screen: vi.fn(),
    reset: vi.fn(),
  })),
}))

// Mock i18next
vi.mock('@/src/shared/i18n', () => ({
  default: {
    t: vi.fn((key: string) => key),
    changeLanguage: vi.fn(),
    language: 'en',
  },
}))

// Mock __DEV__
vi.stubGlobal('__DEV__', true)

// Mock console methods for cleaner test output
const originalConsole = { ...console }
vi.stubGlobal('console', {
  ...console,
  log: vi.fn(),
  info: vi.fn(),
  warn: vi.fn(),
  error: vi.fn(),
})

// Restore console after each test if needed
afterEach(() => {
  vi.clearAllMocks()
})
