import { describe, it, expect, vi, beforeEach } from 'vitest'
import { dataService } from '../../shared/data/dataService'
import { WORKOUTS, TRAINERS, PROGRAMS, ACHIEVEMENTS } from '../../shared/data'
import type { Workout, Trainer, Program, Achievement } from '../../shared/types'

vi.mock('../../shared/supabase', () => ({
  isSupabaseConfigured: vi.fn(() => false),
  supabase: {
    from: vi.fn(),
    auth: {
      signInAnonymously: vi.fn(),
    },
    storage: {
      from: vi.fn(),
    },
  },
}))

describe('dataService', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  describe('getAllWorkouts', () => {
    it('should return local data when Supabase not configured', async () => {
      const workouts = await dataService.getAllWorkouts()
      
      expect(workouts).toEqual(WORKOUTS)
    })

    it('should return workouts with required properties', async () => {
      const workouts = await dataService.getAllWorkouts()
      
      workouts.forEach((workout: Workout) => {
        expect(workout.id).toBeDefined()
        expect(workout.title).toBeDefined()
        expect(workout.trainerId).toBeDefined()
        expect(workout.duration).toBeDefined()
        expect(workout.calories).toBeDefined()
      })
    })
  })

  describe('getWorkoutById', () => {
    it('should return workout by id', async () => {
      const workout = await dataService.getWorkoutById('1')
      
      expect(workout).toBeDefined()
      expect(workout?.id).toBe('1')
    })

    it('should return undefined for non-existent workout', async () => {
      const workout = await dataService.getWorkoutById('non-existent')
      
      expect(workout).toBeUndefined()
    })
  })

  describe('getWorkoutsByCategory', () => {
    it('should return workouts filtered by category', async () => {
      const workouts = await dataService.getWorkoutsByCategory('full-body')
      
      expect(workouts).toBeDefined()
      expect(Array.isArray(workouts)).toBe(true)
      
      workouts.forEach((workout: Workout) => {
        expect(workout.category).toBe('full-body')
      })
    })

    it('should return empty array for non-existent category', async () => {
      const workouts = await dataService.getWorkoutsByCategory('non-existent')
      
      expect(workouts).toEqual([])
    })
  })

  describe('getWorkoutsByTrainer', () => {
    it('should return workouts filtered by trainer', async () => {
      const workouts = await dataService.getWorkoutsByTrainer('emma')
      
      expect(workouts).toBeDefined()
      expect(Array.isArray(workouts)).toBe(true)
    })
  })

  describe('getFeaturedWorkouts', () => {
    it('should return only featured workouts', async () => {
      const workouts = await dataService.getFeaturedWorkouts()
      
      expect(workouts).toBeDefined()
      workouts.forEach((workout: Workout) => {
        expect(workout.isFeatured).toBe(true)
      })
    })
  })

  describe('getAllTrainers', () => {
    it('should return all trainers', async () => {
      const trainers = await dataService.getAllTrainers()
      
      expect(trainers).toEqual(TRAINERS)
    })

    it('should return trainers with required properties', async () => {
      const trainers = await dataService.getAllTrainers()
      
      trainers.forEach((trainer: Trainer) => {
        expect(trainer.id).toBeDefined()
        expect(trainer.name).toBeDefined()
        expect(trainer.specialty).toBeDefined()
        expect(trainer.color).toBeDefined()
      })
    })
  })

  describe('getTrainerById', () => {
    it('should return trainer by id', async () => {
      const trainer = await dataService.getTrainerById('felia')
      
      expect(trainer).toBeDefined()
      expect(trainer?.id).toBe('felia')
    })

    it('should return undefined for non-existent trainer', async () => {
      const trainer = await dataService.getTrainerById('non-existent')
      
      expect(trainer).toBeUndefined()
    })
  })

  describe('getAllCollections', () => {
    it('should return empty array when Supabase not configured', async () => {
      const collections = await dataService.getAllCollections()
      
      expect(collections).toEqual([])
    })
  })

  describe('getCollectionById', () => {
    it('should return undefined when Supabase not configured', async () => {
      const collection = await dataService.getCollectionById('morning-energizer')
      
      expect(collection).toBeUndefined()
    })

    it('should return undefined for non-existent collection', async () => {
      const collection = await dataService.getCollectionById('non-existent')
      
      expect(collection).toBeUndefined()
    })
  })

  describe('getAllPrograms', () => {
    it('should return all programs', async () => {
      const programs = await dataService.getAllPrograms()
      const programValues = Object.values(programs)
      
      expect(programValues.length).toBe(3)
    })

    it('should return programs with required properties', async () => {
      const programs = await dataService.getAllPrograms()
      const programValues = Object.values(programs)
      
      programValues.forEach((program: Program) => {
        expect(program.id).toBeDefined()
        expect(program.title).toBeDefined()
        expect(program.weeks).toBeDefined()
        expect(Array.isArray(program.weeks)).toBe(true)
      })
    })
  })

  describe('getAchievements', () => {
    it('should return all achievements', async () => {
      const achievements = await dataService.getAchievements()
      
      expect(achievements).toEqual(ACHIEVEMENTS)
    })

    it('should return achievements with required properties', async () => {
      const achievements = await dataService.getAchievements()
      
      achievements.forEach((achievement: Achievement) => {
        expect(achievement.id).toBeDefined()
        expect(achievement.title).toBeDefined()
        expect(achievement.description).toBeDefined()
        expect(achievement.requirement).toBeDefined()
        expect(achievement.type).toBeDefined()
      })
    })
  })
})
