//
//  DataStore.swift
//  Werkout_ios
//
//  Created by Trey Tartt on 6/19/23.
//

import Foundation
import SwiftUI

class DataStore: ObservableObject {
    enum DataStoreStatus {
        case loading
        case idle
    }
    
    static let shared = DataStore()
    
    public private(set) var allWorkouts: [Workout]?
    public private(set) var allMuscles: [Muscle]?
    public private(set) var allEquipment: [Equipment]?
    public private(set) var allExercise: [Exercise]?
    public private(set) var allNSFWVideos: [NSFWVideo]?
    
    @Published public private(set) var status = DataStoreStatus.idle
    
    private let fetchAllDataQueue = DispatchGroup()
        
    public func randomVideoFor(gender: String) -> String? {
        return allNSFWVideos?.filter({
            $0.genderValue.lowercased() == gender.lowercased()
        }).randomElement()?.videoFile ?? nil
    }
    
    public var nsfwGenderOptions: [String]? {
        let values = self.allNSFWVideos?.map({
            $0.genderValue
        })
        if let values = values {
            return Array(Set(values))
        }
        return nil
    }
    
    public var workoutsUniqueUsers: [RegisteredUser]? {
        guard let workouts = allWorkouts else {
            return nil
        }
        
        let users = workouts.compactMap({ $0.registeredUser })
        return Array(Set(users))
    }
    
    public func fetchAllData(completion: @escaping (() -> Void)) {
        status = .loading
        
        fetchAllDataQueue.enter()
        fetchAllDataQueue.enter()
        fetchAllDataQueue.enter()
        fetchAllDataQueue.enter()
        fetchAllDataQueue.enter()
        
        fetchAllDataQueue.notify(queue: .main) {
            self.status = .idle
            completion()
        }
        
        AllWorkoutFetchable().fetch(completion: { result in
            switch result {
            case .success(let model):
                self.allWorkouts = model
            case .failure(let error):
                print(error)
            }
            self.fetchAllDataQueue.leave()
        })
        
        AllMusclesFetchable().fetch(completion: { result in
            switch result {
            case .success(let model):
                self.allMuscles = model.sorted(by: {
                    $0.name < $1.name
                })
            case .failure(let error):
                print(error)
            }
            self.fetchAllDataQueue.leave()
        })
        
        AllEquipmentFetchable().fetch(completion: { result in
            switch result {
            case .success(let model):
                self.allEquipment = model.sorted(by: {
                    $0.name < $1.name
                })
            case .failure(let error):
                print(error)
            }
            self.fetchAllDataQueue.leave()
        })
        
        AllExerciseFetchable().fetch(completion: { result in
            switch result {
            case .success(let model):
                self.allExercise = model.sorted(by: {
                    $0.name < $1.name
                })
            case .failure(let error):
                print(error)
            }
            self.fetchAllDataQueue.leave()
        })
        
        AllNSFWVideosFetchable().fetch(completion: { result in
            switch result {
            case .success(let model):
                self.allNSFWVideos = model
            case .failure(let error):
                print(error)
            }
            self.fetchAllDataQueue.leave()
        })
    }
    
    
    func setupFakeData() {
        allWorkouts = PreviewData.allWorkouts()
        allMuscles = PreviewData.parseMuscle()
        allEquipment = PreviewData.parseEquipment()
        allExercise = PreviewData.parseExercises()
    }
}
