import { vi, afterEach, expect } from 'vitest'
import React from 'react'
import { cleanup } from '@testing-library/react-native'

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

// Quieter test output
vi.stubGlobal('console', {
  ...console,
  log: vi.fn(),
  info: vi.fn(),
  warn: vi.fn(),
  error: vi.fn(),
})

afterEach(() => {
  cleanup()
  vi.clearAllMocks()
})

vi.mock('expo-blur', () => ({
  BlurView: ({ intensity, tint, children, style }: any) => {
    return React.createElement('BlurView', { intensity, tint, style, testID: 'blur-view' }, children)
  },
}))

vi.mock('expo-linear-gradient', () => ({
  LinearGradient: ({ colors, start, end, style, children }: any) => {
    return React.createElement(
      'LinearGradient',
      { colors, start, end, style, testID: 'linear-gradient' },
      children
    )
  },
}))

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: ({ player, style, contentFit, nativeControls }: any) => {
    return React.createElement('VideoView', { player, style, contentFit, nativeControls, testID: 'video-view' })
  },
}))

vi.mock('expo-symbols', () => ({
  SymbolView: ({ name, size, tintColor, style, weight, type }: any) => {
    return React.createElement('SymbolView', { name, size, tintColor, style, weight, type, testID: `icon-${name}` })
  },
}))

vi.mock('react-native-safe-area-context', () => ({
  useSafeAreaInsets: () => ({ top: 47, bottom: 34, left: 0, right: 0 }),
  SafeAreaProvider: ({ children }: any) => children,
}))

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

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-linking', () => ({
  default: {
    openURL: vi.fn(),
    createURL: vi.fn(),
  },
}))

const mockThemeColors = {
  bg: {
    base: '#0D1B2A',
    surface: '#112240',
    elevated: '#1A3050',
    overlay1: 'rgba(168,178,216,0.06)',
    overlay2: 'rgba(168,178,216,0.10)',
    overlay3: 'rgba(168,178,216,0.15)',
    scrim: 'rgba(0,0,0,0.6)',
  },
  text: {
    primary: '#E6F1FF',
    secondary: '#A8B2D8',
    tertiary: '#8892B0',
    muted: '#8892B0',
    hint: '#8892B0',
    disabled: '#3A3A3C',
  },
  surface: {
    default: {
      backgroundColor: '#112240',
      borderColor: 'rgba(168,178,216,0.15)',
      borderWidth: 1,
    },
    accent: {
      backgroundColor: 'rgba(0,200,150,0.05)',
      borderColor: 'rgba(0,200,150,0.35)',
      borderWidth: 1.5,
    },
    tip: {
      backgroundColor: 'rgba(255,138,92,0.12)',
      borderColor: '#FF8A5C',
      borderWidth: 1,
    },
  },
  border: {
    dim: 'rgba(168,178,216,0.15)',
    hover: 'rgba(168,178,216,0.25)',
    brand: 'rgba(0,200,150,0.35)',
  },
  gradients: {
    videoOverlay: ['transparent', 'rgba(0,0,0,0.8)'],
    videoTop: ['rgba(0,0,0,0.5)', 'transparent'],
  },
  colorScheme: 'dark' as const,
  statusBarStyle: 'light' as const,
}

vi.mock('@/src/shared/theme', () => ({
  useThemeColors: () => mockThemeColors,
  ThemeProvider: ({ children }: any) => children,
}))

vi.mock('@/src/shared/constants/borderRadius', () => ({
  RADIUS: {
    NONE: 0,
    SM: 4,
    MD: 8,
    LG: 12,
    XL: 16,
    PILL: 9999,
    FULL: 9999,
  },
}))

vi.mock('@/src/shared/constants/spacing', () => ({
  SPACING: {
    1: 4,
    2: 8,
    3: 12,
    4: 16,
    5: 20,
    6: 24,
    8: 32,
  },
  LAYOUT: {
    SCREEN_PADDING: 24,
    BUTTON_HEIGHT: 52,
  },
}))

vi.mock('@/src/shared/constants/animations', () => ({
  DURATION: {
    FAST: 150,
    NORMAL: 250,
    SLOW: 400,
  },
  EASE: {
    EASE_OUT: { x: 0.25, y: 0.1, x2: 0.25, y2: 1 },
  },
}))

vi.mock('react-i18next', () => ({
  useTranslation: () => ({
    t: (key: string) => key,
    i18n: { changeLanguage: vi.fn(), language: 'en' },
  }),
}))

// ---------------------------------------------------------------------------
// Mocks from setup.ts that are needed for render tests
// (react-native is NOT mocked here — it's provided by resolve.alias)
// ---------------------------------------------------------------------------

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-image', () => ({
  Image: 'Image',
}))

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',
}))

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([]),
  },
}))

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',
  },
}))

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),
}))

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: {},
}))

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

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

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(),
    })),
  },
}))

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(),
  })),
}))

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