//
//  UserStore.swift
//  Werkout_ios
//
//  Created by Trey Tartt on 6/25/23.
//

import Foundation

class UserStore: ObservableObject {
    static let userNameKeychainValue = "username"
    static let passwordKeychainValue = "password"
    
    static let userDefaultsRegisteredUserKey = "registeredUserKey"
    static let shared = UserStore()
    
    @Published public private(set) var registeredUser: RegisteredUser?
    
    var plannedWorkouts = [PlannedWorkout]()
    
    init(registeredUser: RegisteredUser? = nil) {
        self.registeredUser = registeredUser
        if let data = UserDefaults.standard.data(forKey: UserStore.userDefaultsRegisteredUserKey),
           let model = try? JSONDecoder().decode(RegisteredUser.self, from: data) {
            self.registeredUser = model
        }
    }
    
    public var token: String? {
        guard let token = registeredUser?.token else {
            return nil
        }
        return "Token \(token)"
    }
    
    func login(postData: [String: Any], completion: @escaping (Bool)-> Void) {
        LoginFetchable(postData: postData).fetch(completion: { result in
            switch result {
            case .success(let model):
                if let email = postData["email"] as? String,
                   let password = postData["password"] as? String,
                   let data = password.data(using: .utf8) {
                    try? KeychainInterface.save(password: data,
                                           account: email)
                }
                
                DispatchQueue.main.async {
                    self.registeredUser = model
                    let data = try! JSONEncoder().encode(model)
                    UserDefaults.standard.set(data, forKey: UserStore.userDefaultsRegisteredUserKey)
                    completion(true)
                }
            case .failure(let failure):
                completion(false)
            }
        })
    }
    
    public func refreshUserData() {
        RefreshUserInfoFetcable().fetch(completion: { result in
            switch result {
            case .success(let registeredUser):
                DispatchQueue.main.async {
                    if let data = try? JSONEncoder().encode(registeredUser) {
                        UserDefaults.standard.set(data, forKey: UserStore.userDefaultsRegisteredUserKey)
                    }
                    if let data = UserDefaults.standard.data(forKey: UserStore.userDefaultsRegisteredUserKey),
                       let model = try? JSONDecoder().decode(RegisteredUser.self, from: data) {
                        self.registeredUser = model
                    }
                }
            case .failure(let failure):
                fatalError()
            }
        })
    }
    
    func logout() {
        self.registeredUser = nil
        UserDefaults.standard.set(nil, forKey: UserStore.userDefaultsRegisteredUserKey)
        DispatchQueue.main.async {
            NotificationCenter.default.post(name: NSNotification.Name("CreatedNewWorkout"), object: nil, userInfo: nil)
        }
    }
    
    func setFakeUser() {
        self.registeredUser = PreviewData.parseRegisterdUser()
    }
    
    func fetchPlannedWorkouts() {
        PlannedWorkoutFetchable().fetch(completion: { result in
            switch result {
            case .success(let models):
                self.plannedWorkouts = models
            case .failure(let failure):
                UserStore.shared.logout()
//                fatalError("shit broke")
            }
        })
    }
    
    func plannedWorkoutFor(date: Date) -> PlannedWorkout? {
        for plannedWorkout in plannedWorkouts {
            if let plannedworkoutDate = plannedWorkout.date {
                if Calendar.current.isDate(date, equalTo: plannedworkoutDate, toGranularity: .day) {
                    return plannedWorkout
                }
            }
        }
        return nil
    }
    
    func setTreyDevRegisterdUser() {
        self.registeredUser = RegisteredUser(id: 1, firstName: "t", lastName: "t", image: nil, nickName: "t", token: "15d7565cde9e8c904ae934f8235f68f6a24b4a03", email: nil, hasNSFWToggle: nil)
    }
}
