import { supabase, isSupabaseConfigured } from '../../shared/supabase'
import type { Database } from '../../shared/supabase/database.types'

type WorkoutInsert = Database['public']['Tables']['workouts']['Insert']
type WorkoutUpdate = Database['public']['Tables']['workouts']['Update']
type TrainerInsert = Database['public']['Tables']['trainers']['Insert']
type TrainerUpdate = Database['public']['Tables']['trainers']['Update']
type CollectionInsert = Database['public']['Tables']['collections']['Insert']
type CollectionWorkoutInsert = Database['public']['Tables']['collection_workouts']['Insert']

export class AdminService {
  private checkConfiguration(): boolean {
    if (!isSupabaseConfigured()) {
      throw new Error('Supabase is not configured. Please set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY')
    }
    return true
  }

  // Workouts
  async createWorkout(workout: Omit<WorkoutInsert, 'id' | 'created_at' | 'updated_at'>): Promise<string> {
    this.checkConfiguration()
    
    const { data, error } = await supabase
      .from('workouts')
      .insert(workout as any)
      .select('id')
      .single()

    if (error) {
      throw new Error(`Failed to create workout: ${error.message}`)
    }

    return (data as any).id
  }

  async updateWorkout(id: string, workout: WorkoutUpdate): Promise<void> {
    this.checkConfiguration()

    const { error } = await (supabase
      .from('workouts') as any)
      .update({ ...workout, updated_at: new Date().toISOString() })
      .eq('id', id)

    if (error) {
      throw new Error(`Failed to update workout: ${error.message}`)
    }
  }

  async deleteWorkout(id: string): Promise<void> {
    this.checkConfiguration()

    const { error } = await supabase
      .from('workouts')
      .delete()
      .eq('id', id)

    if (error) {
      throw new Error(`Failed to delete workout: ${error.message}`)
    }
  }

  // Trainers
  async createTrainer(trainer: Omit<TrainerInsert, 'id' | 'created_at' | 'updated_at'>): Promise<string> {
    this.checkConfiguration()

    const { data, error } = await supabase
      .from('trainers')
      .insert(trainer as any)
      .select('id')
      .single()

    if (error) {
      throw new Error(`Failed to create trainer: ${error.message}`)
    }

    return (data as any).id
  }

  async updateTrainer(id: string, trainer: TrainerUpdate): Promise<void> {
    this.checkConfiguration()

    const { error } = await (supabase
      .from('trainers') as any)
      .update({ ...trainer, updated_at: new Date().toISOString() })
      .eq('id', id)

    if (error) {
      throw new Error(`Failed to update trainer: ${error.message}`)
    }
  }

  async deleteTrainer(id: string): Promise<void> {
    this.checkConfiguration()

    const { error } = await supabase
      .from('trainers')
      .delete()
      .eq('id', id)

    if (error) {
      throw new Error(`Failed to delete trainer: ${error.message}`)
    }
  }

  // Collections
  async createCollection(
    collection: Omit<CollectionInsert, 'id' | 'created_at' | 'updated_at'>,
    workoutIds: string[]
  ): Promise<string> {
    this.checkConfiguration()

    const { data: collectionData, error: collectionError } = await supabase
      .from('collections')
      .insert(collection as any)
      .select('id')
      .single()

    if (collectionError) {
      throw new Error(`Failed to create collection: ${collectionError.message}`)
    }

    const collectionWorkouts: CollectionWorkoutInsert[] = workoutIds.map((workoutId, index) => ({
      collection_id: (collectionData as any).id,
      workout_id: workoutId,
      sort_order: index,
    }))

    const { error: linkError } = await supabase
      .from('collection_workouts')
      .insert(collectionWorkouts as any)

    if (linkError) {
      throw new Error(`Failed to link workouts to collection: ${linkError.message}`)
    }

    return (collectionData as any).id
  }

  async updateCollectionWorkouts(collectionId: string, workoutIds: string[]): Promise<void> {
    this.checkConfiguration()

    const { error: deleteError } = await supabase
      .from('collection_workouts')
      .delete()
      .eq('collection_id', collectionId)

    if (deleteError) {
      throw new Error(`Failed to remove existing workouts: ${deleteError.message}`)
    }

    const collectionWorkouts: CollectionWorkoutInsert[] = workoutIds.map((workoutId, index) => ({
      collection_id: collectionId,
      workout_id: workoutId,
      sort_order: index,
    }))

    const { error: insertError } = await supabase
      .from('collection_workouts')
      .insert(collectionWorkouts as any)

    if (insertError) {
      throw new Error(`Failed to add new workouts: ${insertError.message}`)
    }
  }

  // Storage
  async uploadVideo(file: File, path: string): Promise<string> {
    this.checkConfiguration()

    const { error: uploadError } = await supabase.storage
      .from('videos')
      .upload(path, file)

    if (uploadError) {
      throw new Error(`Failed to upload video: ${uploadError.message}`)
    }

    const { data: { publicUrl } } = supabase.storage
      .from('videos')
      .getPublicUrl(path)

    return publicUrl
  }

  async uploadThumbnail(file: File, path: string): Promise<string> {
    this.checkConfiguration()

    const { error: uploadError } = await supabase.storage
      .from('thumbnails')
      .upload(path, file)

    if (uploadError) {
      throw new Error(`Failed to upload thumbnail: ${uploadError.message}`)
    }

    const { data: { publicUrl } } = supabase.storage
      .from('thumbnails')
      .getPublicUrl(path)

    return publicUrl
  }

  async uploadAvatar(file: File, path: string): Promise<string> {
    this.checkConfiguration()

    const { error: uploadError } = await supabase.storage
      .from('avatars')
      .upload(path, file)

    if (uploadError) {
      throw new Error(`Failed to upload avatar: ${uploadError.message}`)
    }

    const { data: { publicUrl } } = supabase.storage
      .from('avatars')
      .getPublicUrl(path)

    return publicUrl
  }

  async deleteVideo(path: string): Promise<void> {
    this.checkConfiguration()

    const { error } = await supabase.storage
      .from('videos')
      .remove([path])

    if (error) {
      throw new Error(`Failed to delete video: ${error.message}`)
    }
  }

  async deleteThumbnail(path: string): Promise<void> {
    this.checkConfiguration()

    const { error } = await supabase.storage
      .from('thumbnails')
      .remove([path])

    if (error) {
      throw new Error(`Failed to delete thumbnail: ${error.message}`)
    }
  }

  // Admin authentication
  async signIn(email: string, password: string): Promise<void> {
    this.checkConfiguration()

    const { error } = await supabase.auth.signInWithPassword({
      email,
      password,
    })

    if (error) {
      throw new Error(`Authentication failed: ${error.message}`)
    }
  }

  async signOut(): Promise<void> {
    await supabase.auth.signOut()
  }

  async getCurrentUser() {
    const { data: { user } } = await supabase.auth.getUser()
    return user
  }

  async isAdmin(): Promise<boolean> {
    const user = await this.getCurrentUser()
    if (!user) return false

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

    return !error && !!data
  }
}

export const adminService = new AdminService()
