import { describe, it, expect, beforeEach } from 'vitest'
import { useWorkoutProgramStore } from '../../shared/stores/workoutProgramStore'
import type { WorkoutProgram } from '../../shared/types/workoutProgram'

const resetStore = () => {
  useWorkoutProgramStore.setState({ completions: {} })
}

const mockPrograms: WorkoutProgram[] = [
  {
    id: 'prog-1',
    title: 'Upper Body Basics',
    description: 'Upper body workout',
    bodyZone: 'upper-body',
    level: 'Beginner',
    isFree: true,
    musicVibe: 'electronic',
    estimatedDuration: 12,
    estimatedCalories: 100,
    icon: 'dumbbell',
    accentColor: '#FF6B35',
    sortOrder: 1,
    tabatas: [],
    createdAt: '2024-01-01',
    updatedAt: '2024-01-01',
  },
  {
    id: 'prog-2',
    title: 'Lower Body Burn',
    description: 'Lower body workout',
    bodyZone: 'lower-body',
    level: 'Intermediate',
    isFree: false,
    musicVibe: 'hip-hop',
    estimatedDuration: 15,
    estimatedCalories: 150,
    icon: 'figure.walk',
    accentColor: '#5AC8FA',
    sortOrder: 2,
    tabatas: [],
    createdAt: '2024-01-01',
    updatedAt: '2024-01-01',
  },
  {
    id: 'prog-3',
    title: 'Full Body Advanced',
    description: 'Full body workout',
    bodyZone: 'full-body',
    level: 'Advanced',
    isFree: false,
    musicVibe: 'rock',
    estimatedDuration: 20,
    estimatedCalories: 200,
    icon: 'bolt',
    accentColor: '#30D158',
    sortOrder: 3,
    tabatas: [],
    createdAt: '2024-01-01',
    updatedAt: '2024-01-01',
  },
]

describe('workoutProgramStore', () => {
  beforeEach(() => {
    resetStore()
  })

  describe('initial state', () => {
    it('should have empty completions', () => {
      expect(useWorkoutProgramStore.getState().completions).toEqual({})
    })
  })

  describe('completeProgram', () => {
    it('should mark entire program as completed when no tabataPosition', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1')
      const state = useWorkoutProgramStore.getState()
      expect(state.completions['prog-1']).toBeDefined()
      expect(state.completions['prog-1'].tabatasCompleted).toEqual([1, 2, 3])
      expect(state.completions['prog-1'].completedAt).toBeTruthy()
    })

    it('should mark specific tabata as completed', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1', 1)
      const state = useWorkoutProgramStore.getState()
      expect(state.completions['prog-1'].tabatasCompleted).toEqual([1])
    })

    it('should accumulate tabata completions', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1', 1)
      useWorkoutProgramStore.getState().completeProgram('prog-1', 2)
      const state = useWorkoutProgramStore.getState()
      expect(state.completions['prog-1'].tabatasCompleted).toEqual([1, 2])
    })

    it('should not duplicate tabata positions', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1', 1)
      useWorkoutProgramStore.getState().completeProgram('prog-1', 1)
      const state = useWorkoutProgramStore.getState()
      expect(state.completions['prog-1'].tabatasCompleted).toEqual([1])
    })

    it('should set completedAt when all 3 tabatas done', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1', 1)
      useWorkoutProgramStore.getState().completeProgram('prog-1', 2)
      useWorkoutProgramStore.getState().completeProgram('prog-1', 3)
      const state = useWorkoutProgramStore.getState()
      expect(state.completions['prog-1'].completedAt).toBeTruthy()
      expect(state.completions['prog-1'].tabatasCompleted).toHaveLength(3)
    })
  })

  describe('resetProgram', () => {
    it('should remove program completion', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1')
      useWorkoutProgramStore.getState().resetProgram('prog-1')
      expect(useWorkoutProgramStore.getState().completions['prog-1']).toBeUndefined()
    })

    it('should not affect other programs', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1')
      useWorkoutProgramStore.getState().completeProgram('prog-2')
      useWorkoutProgramStore.getState().resetProgram('prog-1')
      expect(useWorkoutProgramStore.getState().completions['prog-2']).toBeDefined()
    })
  })

  describe('isProgramCompleted', () => {
    it('should return false for uncompleted program', () => {
      expect(useWorkoutProgramStore.getState().isProgramCompleted('prog-1')).toBe(false)
    })

    it('should return true when all 3 tabatas completed', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1')
      expect(useWorkoutProgramStore.getState().isProgramCompleted('prog-1')).toBe(true)
    })

    it('should return false when only 2 tabatas completed', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1', 1)
      useWorkoutProgramStore.getState().completeProgram('prog-1', 2)
      expect(useWorkoutProgramStore.getState().isProgramCompleted('prog-1')).toBe(false)
    })
  })

  describe('getCompletedCount', () => {
    it('should return 0 initially', () => {
      expect(useWorkoutProgramStore.getState().getCompletedCount()).toBe(0)
    })

    it('should count fully completed programs', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1')
      useWorkoutProgramStore.getState().completeProgram('prog-2')
      useWorkoutProgramStore.getState().completeProgram('prog-3', 1) // partial
      expect(useWorkoutProgramStore.getState().getCompletedCount()).toBe(2)
    })
  })

  describe('getRecommendedNext', () => {
    it('should recommend first incomplete program sorted by level', () => {
      const rec = useWorkoutProgramStore.getState().getRecommendedNext(mockPrograms)
      expect(rec).not.toBeNull()
      expect(rec?.id).toBe('prog-1') // Beginner first
    })

    it('should skip completed programs', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1')
      const rec = useWorkoutProgramStore.getState().getRecommendedNext(mockPrograms)
      expect(rec?.id).toBe('prog-2') // Intermediate
    })

    it('should return null when all completed', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1')
      useWorkoutProgramStore.getState().completeProgram('prog-2')
      useWorkoutProgramStore.getState().completeProgram('prog-3')
      expect(useWorkoutProgramStore.getState().getRecommendedNext(mockPrograms)).toBeNull()
    })
  })

  describe('getTabatasCompleted', () => {
    it('should return empty array for unknown program', () => {
      expect(useWorkoutProgramStore.getState().getTabatasCompleted('unknown')).toEqual([])
    })

    it('should return completed tabata positions', () => {
      useWorkoutProgramStore.getState().completeProgram('prog-1', 2)
      expect(useWorkoutProgramStore.getState().getTabatasCompleted('prog-1')).toEqual([2])
    })
  })
})
