import { describe, it, expect, beforeEach } from 'vitest'
import { usePlayerStore } from '../../shared/stores/playerStore'
import type { Workout } from '../../shared/types'

const mockWorkout: Workout = {
  id: 'test-workout',
  title: 'Test Workout',
  trainerId: 'trainer-1',
  category: 'full-body',
  level: 'Beginner',
  duration: 4,
  calories: 45,
  rounds: 8,
  prepTime: 10,
  workTime: 20,
  restTime: 10,
  equipment: [],
  musicVibe: 'electronic',
  exercises: [
    { name: 'Jumping Jacks', duration: 20 },
    { name: 'Squats', duration: 20 },
    { name: 'Push-ups', duration: 20 },
    { name: 'High Knees', duration: 20 },
  ],
}

describe('playerStore', () => {
  beforeEach(() => {
    usePlayerStore.getState().reset()
  })

  describe('initial state', () => {
    it('should have correct default values', () => {
      const state = usePlayerStore.getState()
      
      expect(state.workout).toBeNull()
      expect(state.phase).toBe('PREP')
      expect(state.timeRemaining).toBe(10)
      expect(state.currentRound).toBe(1)
      expect(state.isPaused).toBe(false)
      expect(state.isRunning).toBe(false)
      expect(state.calories).toBe(0)
      expect(state.startedAt).toBeNull()
    })
  })

  describe('loadWorkout', () => {
    it('should load workout and reset all state', () => {
      const store = usePlayerStore.getState()
      
      store.loadWorkout(mockWorkout)
      
      const state = usePlayerStore.getState()
      expect(state.workout).toEqual(mockWorkout)
      expect(state.phase).toBe('PREP')
      expect(state.timeRemaining).toBe(mockWorkout.prepTime)
      expect(state.currentRound).toBe(1)
      expect(state.isPaused).toBe(false)
      expect(state.isRunning).toBe(false)
      expect(state.calories).toBe(0)
      expect(state.startedAt).toBeNull()
    })

    it('should use workout prepTime for timeRemaining', () => {
      const workoutWithCustomPrep: Workout = { ...mockWorkout, prepTime: 15 }
      
      usePlayerStore.getState().loadWorkout(workoutWithCustomPrep)
      
      expect(usePlayerStore.getState().timeRemaining).toBe(15)
    })
  })

  describe('setPhase', () => {
    it('should update phase', () => {
      const store = usePlayerStore.getState()
      
      store.setPhase('WORK')
      expect(usePlayerStore.getState().phase).toBe('WORK')
      
      store.setPhase('REST')
      expect(usePlayerStore.getState().phase).toBe('REST')
      
      store.setPhase('COMPLETE')
      expect(usePlayerStore.getState().phase).toBe('COMPLETE')
    })
  })

  describe('setTimeRemaining', () => {
    it('should update timeRemaining', () => {
      const store = usePlayerStore.getState()
      
      store.setTimeRemaining(5)
      expect(usePlayerStore.getState().timeRemaining).toBe(5)
      
      store.setTimeRemaining(0)
      expect(usePlayerStore.getState().timeRemaining).toBe(0)
    })
  })

  describe('setCurrentRound', () => {
    it('should update currentRound', () => {
      const store = usePlayerStore.getState()
      
      store.setCurrentRound(3)
      expect(usePlayerStore.getState().currentRound).toBe(3)
      
      store.setCurrentRound(8)
      expect(usePlayerStore.getState().currentRound).toBe(8)
    })
  })

  describe('setPaused', () => {
    it('should toggle pause state', () => {
      const store = usePlayerStore.getState()
      
      store.setPaused(true)
      expect(usePlayerStore.getState().isPaused).toBe(true)
      
      store.setPaused(false)
      expect(usePlayerStore.getState().isPaused).toBe(false)
    })
  })

  describe('setRunning', () => {
    it('should set running state', () => {
      const store = usePlayerStore.getState()
      
      store.setRunning(true)
      expect(usePlayerStore.getState().isRunning).toBe(true)
    })

    it('should set startedAt when first running', () => {
      const store = usePlayerStore.getState()
      const beforeSet = Date.now()
      
      store.setRunning(true)
      
      const state = usePlayerStore.getState()
      expect(state.startedAt).toBeGreaterThanOrEqual(beforeSet)
      expect(state.startedAt).toBeLessThanOrEqual(Date.now())
    })

    it('should not update startedAt if already set', () => {
      const store = usePlayerStore.getState()
      
      store.setRunning(true)
      const firstStartedAt = usePlayerStore.getState().startedAt
      
      store.setRunning(false)
      store.setRunning(true)
      
      expect(usePlayerStore.getState().startedAt).toBe(firstStartedAt)
    })
  })

  describe('addCalories', () => {
    it('should accumulate calories', () => {
      const store = usePlayerStore.getState()
      
      store.addCalories(5)
      expect(usePlayerStore.getState().calories).toBe(5)
      
      store.addCalories(5)
      expect(usePlayerStore.getState().calories).toBe(10)
      
      store.addCalories(3)
      expect(usePlayerStore.getState().calories).toBe(13)
    })
  })

  describe('reset', () => {
    it('should reset all state to defaults', () => {
      const store = usePlayerStore.getState()
      
      store.loadWorkout(mockWorkout)
      store.setPhase('WORK')
      store.setCurrentRound(5)
      store.setRunning(true)
      store.addCalories(25)
      
      store.reset()
      
      const state = usePlayerStore.getState()
      expect(state.workout).toBeNull()
      expect(state.phase).toBe('PREP')
      expect(state.timeRemaining).toBe(10)
      expect(state.currentRound).toBe(1)
      expect(state.isPaused).toBe(false)
      expect(state.isRunning).toBe(false)
      expect(state.calories).toBe(0)
      expect(state.startedAt).toBeNull()
    })
  })

  describe('workout phase simulation', () => {
    it('should track complete workout flow', () => {
      const store = usePlayerStore.getState()
      
      store.loadWorkout(mockWorkout)
      
      expect(store.phase).toBe('PREP')
      expect(store.timeRemaining).toBe(10)
      
      store.setPhase('WORK')
      store.setTimeRemaining(20)
      expect(usePlayerStore.getState().phase).toBe('WORK')
      
      store.setTimeRemaining(0)
      store.addCalories(6)
      store.setPhase('REST')
      store.setTimeRemaining(10)
      expect(usePlayerStore.getState().calories).toBe(6)
      expect(usePlayerStore.getState().phase).toBe('REST')
      
      store.setCurrentRound(2)
      store.setPhase('WORK')
      expect(usePlayerStore.getState().currentRound).toBe(2)
    })
  })
})
