import { describe, it, expect } from 'vitest'
import { WORKOUTS } from '../../shared/data/workouts'
import type { Workout, WorkoutCategory, WorkoutLevel, WorkoutDuration, MusicVibe } from '../../shared/types'

describe('workouts data', () => {
  describe('data integrity', () => {
    it('should have 50 workouts', () => {
      expect(WORKOUTS).toHaveLength(50)
    })

    it('should have unique IDs for all workouts', () => {
      const ids = WORKOUTS.map((w) => w.id)
      const uniqueIds = new Set(ids)
      expect(uniqueIds.size).toBe(ids.length)
    })

    it('should have all required fields for each workout', () => {
      const requiredFields: (keyof Workout)[] = [
        'id', 'title', 'trainerId', 'category', 'level', 'duration',
        'calories', 'exercises', 'rounds', 'prepTime', 'workTime',
        'restTime', 'equipment', 'musicVibe',
      ]

      WORKOUTS.forEach((workout) => {
        requiredFields.forEach((field) => {
          expect(workout[field]).toBeDefined()
        })
      })
    })
  })

  describe('category distribution', () => {
    const categories: WorkoutCategory[] = ['full-body', 'core', 'upper-body', 'lower-body', 'cardio']

    categories.forEach((category) => {
      it(`should have 10 ${category} workouts`, () => {
        const count = WORKOUTS.filter((w) => w.category === category).length
        expect(count).toBe(10)
      })
    })
  })

  describe('level distribution', () => {
    it('should have Beginner workouts', () => {
      const beginners = WORKOUTS.filter((w) => w.level === 'Beginner')
      expect(beginners.length).toBeGreaterThan(0)
    })

    it('should have Intermediate workouts', () => {
      const intermediates = WORKOUTS.filter((w) => w.level === 'Intermediate')
      expect(intermediates.length).toBeGreaterThan(0)
    })

    it('should have Advanced workouts', () => {
      const advanced = WORKOUTS.filter((w) => w.level === 'Advanced')
      expect(advanced.length).toBeGreaterThan(0)
    })
  })

  describe('duration distribution', () => {
    const durations: WorkoutDuration[] = [4, 8, 12, 20]

    durations.forEach((duration) => {
      it(`should have ${duration}-minute workouts`, () => {
        const count = WORKOUTS.filter((w) => w.duration === duration).length
        expect(count).toBeGreaterThan(0)
      })
    })
  })

  describe('workout structure validation', () => {
    it('should have valid prep times (5-15 seconds)', () => {
      WORKOUTS.forEach((workout) => {
        expect(workout.prepTime).toBeGreaterThanOrEqual(5)
        expect(workout.prepTime).toBeLessThanOrEqual(15)
      })
    })

    it('should have valid work times (15-30 seconds)', () => {
      WORKOUTS.forEach((workout) => {
        expect(workout.workTime).toBeGreaterThanOrEqual(15)
        expect(workout.workTime).toBeLessThanOrEqual(30)
      })
    })

    it('should have valid rest times (5-15 seconds)', () => {
      WORKOUTS.forEach((workout) => {
        expect(workout.restTime).toBeGreaterThanOrEqual(5)
        expect(workout.restTime).toBeLessThanOrEqual(15)
      })
    })

    it('should have at least 1 exercise per workout', () => {
      WORKOUTS.forEach((workout) => {
        expect(workout.exercises.length).toBeGreaterThanOrEqual(1)
      })
    })

    it('should have valid exercise durations matching work time', () => {
      WORKOUTS.forEach((workout) => {
        workout.exercises.forEach((exercise) => {
          expect(exercise.duration).toBe(workout.workTime)
        })
      })
    })

    it('should have valid rounds (4-40)', () => {
      WORKOUTS.forEach((workout) => {
        expect(workout.rounds).toBeGreaterThanOrEqual(4)
        expect(workout.rounds).toBeLessThanOrEqual(40)
      })
    })
  })

  describe('calorie estimation', () => {
    it('should have positive calorie values', () => {
      WORKOUTS.forEach((workout) => {
        expect(workout.calories).toBeGreaterThan(0)
      })
    })

    it('should scale calories with duration', () => {
      const shortWorkouts = WORKOUTS.filter((w) => w.duration === 4)
      const longWorkouts = WORKOUTS.filter((w) => w.duration === 20)

      const avgShortCalories = shortWorkouts.reduce((sum, w) => sum + w.calories, 0) / shortWorkouts.length
      const avgLongCalories = longWorkouts.reduce((sum, w) => sum + w.calories, 0) / longWorkouts.length

      expect(avgLongCalories).toBeGreaterThan(avgShortCalories)
    })
  })

  describe('music vibes', () => {
    const validVibes: MusicVibe[] = ['electronic', 'hip-hop', 'pop', 'rock', 'chill']

    it('should only have valid music vibes', () => {
      WORKOUTS.forEach((workout) => {
        expect(validVibes).toContain(workout.musicVibe)
      })
    })

    validVibes.forEach((vibe) => {
      it(`should have workouts with ${vibe} vibe`, () => {
        const count = WORKOUTS.filter((w) => w.musicVibe === vibe).length
        expect(count).toBeGreaterThan(0)
      })
    })
  })

  describe('equipment field', () => {
    it('should have equipment as an array', () => {
      WORKOUTS.forEach((workout) => {
        expect(Array.isArray(workout.equipment)).toBe(true)
      })
    })

    it('should have at least "No equipment required" for bodyweight workouts', () => {
      const noEquipmentWorkouts = WORKOUTS.filter((w) => 
        w.equipment.some((e) => e.toLowerCase().includes('no equipment'))
      )
      expect(noEquipmentWorkouts.length).toBeGreaterThan(0)
    })
  })

  describe('featured workouts', () => {
    it('should have some featured workouts', () => {
      const featured = WORKOUTS.filter((w) => w.isFeatured)
      expect(featured.length).toBeGreaterThan(0)
    })
  })

  describe('trainer assignments', () => {
    const validTrainers = ['felia', 'felix']

    it('should only have valid trainer IDs', () => {
      WORKOUTS.forEach((workout) => {
        expect(validTrainers).toContain(workout.trainerId)
      })
    })

    validTrainers.forEach((trainer) => {
      it(`should have workouts for trainer ${trainer}`, () => {
        const count = WORKOUTS.filter((w) => w.trainerId === trainer).length
        expect(count).toBeGreaterThan(0)
      })
    })
  })

  describe('duration calculation validation', () => {
    it('should have duration matching rounds and intervals', () => {
      WORKOUTS.forEach((workout) => {
        const totalSeconds = workout.prepTime + (workout.workTime + workout.restTime) * workout.rounds
        const totalMinutes = totalSeconds / 60
        
        expect(Math.abs(totalMinutes - workout.duration)).toBeLessThan(2)
      })
    })
  })
})
