import { supabase, isSupabaseConfigured } from '../supabase'
import { WORKOUTS, TRAINERS, COLLECTIONS, PROGRAMS, ACHIEVEMENTS } from './index'
import type { Workout, Trainer, Collection, Program } from '../types'
import type { Database } from '../supabase/database.types'

type WorkoutRow = Database['public']['Tables']['workouts']['Row']
type TrainerRow = Database['public']['Tables']['trainers']['Row']
type CollectionRow = Database['public']['Tables']['collections']['Row']
type CollectionWorkoutRow = Database['public']['Tables']['collection_workouts']['Row']
type ProgramRow = Database['public']['Tables']['programs']['Row']
type ProgramWorkoutRow = Database['public']['Tables']['program_workouts']['Row']

function mapWorkoutFromDB(row: WorkoutRow): Workout {
  return {
    id: row.id,
    title: row.title,
    trainerId: row.trainer_id,
    category: row.category,
    level: row.level,
    duration: row.duration as 4 | 8 | 12 | 20,
    calories: row.calories,
    rounds: row.rounds,
    prepTime: row.prep_time,
    workTime: row.work_time,
    restTime: row.rest_time,
    equipment: row.equipment,
    musicVibe: row.music_vibe,
    exercises: row.exercises,
    thumbnailUrl: row.thumbnail_url ?? undefined,
    videoUrl: row.video_url ?? undefined,
    isFeatured: row.is_featured,
  }
}

function mapTrainerFromDB(row: TrainerRow): Trainer {
  return {
    id: row.id,
    name: row.name,
    specialty: row.specialty,
    color: row.color,
    avatarUrl: row.avatar_url ?? undefined,
    workoutCount: row.workout_count,
  }
}

function mapCollectionFromDB(
  row: CollectionRow,
  workoutIds: string[]
): Collection {
  return {
    id: row.id,
    title: row.title,
    description: row.description,
    icon: row.icon,
    workoutIds,
    gradient: row.gradient ? (row.gradient as [string, string]) : undefined,
  }
}

function mapProgramFromDB(
  row: ProgramRow,
  workoutIds: string[]
): Program {
  return {
    id: row.id,
    title: row.title,
    description: row.description,
    weeks: row.weeks,
    workoutsPerWeek: row.workouts_per_week,
    level: row.level,
    workoutIds,
  }
}

class SupabaseDataService {
  async getAllWorkouts(): Promise<Workout[]> {
    if (!isSupabaseConfigured()) {
      return WORKOUTS
    }

    const { data, error } = await supabase
      .from('workouts')
      .select('*')
      .order('created_at', { ascending: false })

    if (error) {
      console.error('Error fetching workouts:', error)
      return WORKOUTS
    }

    return data?.map(mapWorkoutFromDB) ?? WORKOUTS
  }

  async getWorkoutById(id: string): Promise<Workout | undefined> {
    if (!isSupabaseConfigured()) {
      return WORKOUTS.find((w: Workout) => w.id === id)
    }

    const { data, error } = await supabase
      .from('workouts')
      .select('*')
      .eq('id', id)
      .single()

    if (error || !data) {
      console.error('Error fetching workout:', error)
      return WORKOUTS.find((w: Workout) => w.id === id)
    }

    return mapWorkoutFromDB(data)
  }

  async getWorkoutsByCategory(category: string): Promise<Workout[]> {
    if (!isSupabaseConfigured()) {
      return WORKOUTS.filter((w: Workout) => w.category === category)
    }

    const { data, error } = await supabase
      .from('workouts')
      .select('*')
      .eq('category', category)

    if (error) {
      console.error('Error fetching workouts by category:', error)
      return WORKOUTS.filter((w: Workout) => w.category === category)
    }

    return data?.map(mapWorkoutFromDB) ?? WORKOUTS.filter((w: Workout) => w.category === category)
  }

  async getWorkoutsByTrainer(trainerId: string): Promise<Workout[]> {
    if (!isSupabaseConfigured()) {
      return WORKOUTS.filter((w: Workout) => w.trainerId === trainerId)
    }

    const { data, error } = await supabase
      .from('workouts')
      .select('*')
      .eq('trainer_id', trainerId)

    if (error) {
      console.error('Error fetching workouts by trainer:', error)
      return WORKOUTS.filter((w: Workout) => w.trainerId === trainerId)
    }

    return data?.map(mapWorkoutFromDB) ?? WORKOUTS.filter((w: Workout) => w.trainerId === trainerId)
  }

  async getFeaturedWorkouts(): Promise<Workout[]> {
    if (!isSupabaseConfigured()) {
      return WORKOUTS.filter((w: Workout) => w.isFeatured)
    }

    const { data, error } = await supabase
      .from('workouts')
      .select('*')
      .eq('is_featured', true)

    if (error) {
      console.error('Error fetching featured workouts:', error)
      return WORKOUTS.filter((w: Workout) => w.isFeatured)
    }

    return data?.map(mapWorkoutFromDB) ?? WORKOUTS.filter((w: Workout) => w.isFeatured)
  }

  async getAllTrainers(): Promise<Trainer[]> {
    if (!isSupabaseConfigured()) {
      return TRAINERS
    }

    const { data, error } = await supabase
      .from('trainers')
      .select('*')

    if (error) {
      console.error('Error fetching trainers:', error)
      return TRAINERS
    }

    return data?.map(mapTrainerFromDB) ?? TRAINERS
  }

  async getTrainerById(id: string): Promise<Trainer | undefined> {
    if (!isSupabaseConfigured()) {
      return TRAINERS.find((t: Trainer) => t.id === id)
    }

    const { data, error } = await supabase
      .from('trainers')
      .select('*')
      .eq('id', id)
      .single()

    if (error || !data) {
      console.error('Error fetching trainer:', error)
      return TRAINERS.find((t: Trainer) => t.id === id)
    }

    return mapTrainerFromDB(data)
  }

  async getAllCollections(): Promise<Collection[]> {
    if (!isSupabaseConfigured()) {
      return COLLECTIONS
    }

    const { data: collectionsData, error: collectionsError } = await supabase
      .from('collections')
      .select('*')

    if (collectionsError) {
      console.error('Error fetching collections:', collectionsError)
      return COLLECTIONS
    }

    const { data: workoutLinks, error: linksError } = await supabase
      .from('collection_workouts')
      .select('*')
      .order('sort_order')

    if (linksError) {
      console.error('Error fetching collection workouts:', linksError)
      return COLLECTIONS
    }

    const workoutIdsByCollection: Record<string, string[]> = {}
    workoutLinks?.forEach((link: CollectionWorkoutRow) => {
      if (!workoutIdsByCollection[link.collection_id]) {
        workoutIdsByCollection[link.collection_id] = []
      }
      workoutIdsByCollection[link.collection_id].push(link.workout_id)
    })

    return collectionsData?.map((row: CollectionRow) =>
      mapCollectionFromDB(row, workoutIdsByCollection[row.id] || [])
    ) ?? COLLECTIONS
  }

  async getCollectionById(id: string): Promise<Collection | undefined> {
    if (!isSupabaseConfigured()) {
      return COLLECTIONS.find((c: Collection) => c.id === id)
    }

    const { data: collection, error: collectionError } = await supabase
      .from('collections')
      .select('*')
      .eq('id', id)
      .single()

    if (collectionError || !collection) {
      console.error('Error fetching collection:', collectionError)
      return COLLECTIONS.find((c: Collection) => c.id === id)
    }

    const { data: workoutLinks, error: linksError } = await supabase
      .from('collection_workouts')
      .select('workout_id')
      .eq('collection_id', id)
      .order('sort_order')

    if (linksError) {
      console.error('Error fetching collection workouts:', linksError)
      return COLLECTIONS.find((c: Collection) => c.id === id)
    }

    const workoutIds = workoutLinks?.map((link: { workout_id: string }) => link.workout_id) || []
    return mapCollectionFromDB(collection, workoutIds)
  }

  async getAllPrograms(): Promise<Program[]> {
    if (!isSupabaseConfigured()) {
      return PROGRAMS
    }

    const { data: programsData, error: programsError } = await supabase
      .from('programs')
      .select('*')

    if (programsError) {
      console.error('Error fetching programs:', programsError)
      return PROGRAMS
    }

    const { data: workoutLinks, error: linksError } = await supabase
      .from('program_workouts')
      .select('*')
      .order('week_number')
      .order('day_number')

    if (linksError) {
      console.error('Error fetching program workouts:', linksError)
      return PROGRAMS
    }

    const workoutIdsByProgram: Record<string, string[]> = {}
    workoutLinks?.forEach((link: ProgramWorkoutRow) => {
      if (!workoutIdsByProgram[link.program_id]) {
        workoutIdsByProgram[link.program_id] = []
      }
      workoutIdsByProgram[link.program_id].push(link.workout_id)
    })

    return programsData?.map((row: ProgramRow) =>
      mapProgramFromDB(row, workoutIdsByProgram[row.id] || [])
    ) ?? PROGRAMS
  }

  async getAchievements() {
    return ACHIEVEMENTS
  }
}

export const dataService = new SupabaseDataService()
