import { describe, it, expect, vi, beforeEach } from 'vitest'
import * as Haptics from 'expo-haptics'
import { useUserStore } from '../../shared/stores/userStore'

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

describe('useHaptics logic', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    useUserStore.setState({
      settings: {
        haptics: true,
        soundEffects: true,
        voiceCoaching: true,
        musicEnabled: true,
        musicVolume: 0.5,
        reminders: false,
        reminderTime: '09:00',
      },
    })
  })

  describe('haptic feedback functions', () => {
    const createHapticCallbacks = () => {
      const hapticsEnabled = useUserStore.getState().settings.haptics
      
      const phaseChange = () => {
        if (!hapticsEnabled) return
        Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy)
      }
      
      const buttonTap = () => {
        if (!hapticsEnabled) return
        Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium)
      }
      
      const countdownTick = () => {
        if (!hapticsEnabled) return
        Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light)
      }
      
      const workoutComplete = () => {
        if (!hapticsEnabled) return
        Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success)
      }
      
      const selection = () => {
        if (!hapticsEnabled) return
        Haptics.selectionAsync()
      }
      
      return { phaseChange, buttonTap, countdownTick, workoutComplete, selection }
    }

    describe('when haptics enabled', () => {
      it('should call impactAsync with Heavy for phaseChange', () => {
        const callbacks = createHapticCallbacks()
        callbacks.phaseChange()
        
        expect(Haptics.impactAsync).toHaveBeenCalledWith(Haptics.ImpactFeedbackStyle.Heavy)
      })

      it('should call impactAsync with Medium for buttonTap', () => {
        const callbacks = createHapticCallbacks()
        callbacks.buttonTap()
        
        expect(Haptics.impactAsync).toHaveBeenCalledWith(Haptics.ImpactFeedbackStyle.Medium)
      })

      it('should call impactAsync with Light for countdownTick', () => {
        const callbacks = createHapticCallbacks()
        callbacks.countdownTick()
        
        expect(Haptics.impactAsync).toHaveBeenCalledWith(Haptics.ImpactFeedbackStyle.Light)
      })

      it('should call notificationAsync with Success for workoutComplete', () => {
        const callbacks = createHapticCallbacks()
        callbacks.workoutComplete()
        
        expect(Haptics.notificationAsync).toHaveBeenCalledWith(Haptics.NotificationFeedbackType.Success)
      })

      it('should call selectionAsync for selection', () => {
        const callbacks = createHapticCallbacks()
        callbacks.selection()
        
        expect(Haptics.selectionAsync).toHaveBeenCalled()
      })
    })

    describe('when haptics disabled', () => {
      beforeEach(() => {
        useUserStore.setState({
          settings: {
            haptics: false,
            soundEffects: true,
            voiceCoaching: true,
            musicEnabled: true,
            musicVolume: 0.5,
            reminders: false,
            reminderTime: '09:00',
          },
        })
      })

      it('should not call impactAsync for phaseChange', () => {
        const callbacks = createHapticCallbacks()
        callbacks.phaseChange()
        
        expect(Haptics.impactAsync).not.toHaveBeenCalled()
      })

      it('should not call impactAsync for buttonTap', () => {
        const callbacks = createHapticCallbacks()
        callbacks.buttonTap()
        
        expect(Haptics.impactAsync).not.toHaveBeenCalled()
      })

      it('should not call impactAsync for countdownTick', () => {
        const callbacks = createHapticCallbacks()
        callbacks.countdownTick()
        
        expect(Haptics.impactAsync).not.toHaveBeenCalled()
      })

      it('should not call notificationAsync for workoutComplete', () => {
        const callbacks = createHapticCallbacks()
        callbacks.workoutComplete()
        
        expect(Haptics.notificationAsync).not.toHaveBeenCalled()
      })

      it('should not call selectionAsync for selection', () => {
        const callbacks = createHapticCallbacks()
        callbacks.selection()
        
        expect(Haptics.selectionAsync).not.toHaveBeenCalled()
      })
    })
  })

  describe('feedback style mapping', () => {
    it('should map phase change to heavy impact', () => {
      expect(Haptics.ImpactFeedbackStyle.Heavy).toBe('heavy')
    })

    it('should map button tap to medium impact', () => {
      expect(Haptics.ImpactFeedbackStyle.Medium).toBe('medium')
    })

    it('should map countdown tick to light impact', () => {
      expect(Haptics.ImpactFeedbackStyle.Light).toBe('light')
    })

    it('should map workout complete to success notification', () => {
      expect(Haptics.NotificationFeedbackType.Success).toBe('success')
    })
  })
})
