//
//  APIDataManager.swift

import Foundation
import UIKit
import Alamofire

class APIDataManager {
    
    static let shared = APIDataManager()
    let userDefaultManager = UserDefaultManager.shared
    
    //MARK: - SignIn With Number -
    
    func callSignInWithNumberAPI(contry_code : String, phone_no : String, success: @escaping (_ response: (Bool), _ message : String) -> Void, failure: @escaping (String) -> Void){
        
        let params = [API_Param_Name.phone : phone_no as AnyObject,
                      API_Param_Name.country_code : contry_code as AnyObject,
                      API_Param_Name.device_unique_id : getUUIDFromKeychain() as AnyObject,
                      API_Param_Name.device_token : self.userDefaultManager.deviceToken as AnyObject,
                      API_Param_Name.device_type : Device.DEVICE_TYPE as AnyObject,
                      API_Param_Name.device_name : Device.DEVICE_NAME as AnyObject,
                      API_Param_Name.ip : Device.deviceIP as AnyObject,
                      API_Param_Name.app_version : version as AnyObject,
                      API_Param_Name.OTP_key : Constant.OTP_value as AnyObject]
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.signin_with_number, method: .post, params: params) { response,message  in
                
                //            if response.data != nil{
                if response.count != 0{
                    self.userDefaultManager.loginUserToken = response["token"] as? String ?? ""
                    success(true, message)
                }
                else{
                    success(false, message)
                }
                
            } failure: { (error) in
                success(false, error)
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    func callSignInNumberAPI(contry_code : String, phone_no : String, success: @escaping (_ response: (Bool), _ message : String) -> Void, failure: @escaping (String) -> Void){
        
        let params = [API_Param_Name.phone : phone_no as AnyObject,
                      API_Param_Name.country_code : contry_code as AnyObject,
                      API_Param_Name.device_unique_id : getUUIDFromKeychain() as AnyObject,
                      API_Param_Name.device_token : self.userDefaultManager.deviceToken as AnyObject,
                      API_Param_Name.device_type : Device.DEVICE_TYPE as AnyObject,
                      API_Param_Name.device_name : Device.DEVICE_NAME as AnyObject,
                      API_Param_Name.ip : Device.deviceIP as AnyObject,
                      API_Param_Name.app_version : version as AnyObject,
                      API_Param_Name.otp_count : 1 as AnyObject]//Constant.OTP_value as AnyObject]
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.login, method: .post, params: params) { response,message  in
                
                //            if response.data != nil{
                if response.count != 0{
                    self.userDefaultManager.loginUserToken = response["token"] as? String ?? ""
                    success(true, message)
                }
                else{
                    success(false, message)
                }
                
            } failure: { (error) in
                success(false, error)
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    //MARK: - Auto Login -
    
    func callAutoLoginAPI(){
        let params = [API_Param_Name.device_unique_id : getUUIDFromKeychain() as AnyObject,
                      API_Param_Name.device_token : self.userDefaultManager.deviceToken as AnyObject,
                      API_Param_Name.device_type : Device.DEVICE_TYPE as AnyObject,
                      API_Param_Name.device_name : Device.DEVICE_NAME as AnyObject,
                      API_Param_Name.ip : Device.deviceIP as AnyObject,
                      API_Param_Name.app_version : version as AnyObject]
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.auto_log_in, method: .post, params: params) { response,message  in
                
                do {
                    if let jsonData = try? JSONSerialization.data(withJSONObject: response as Any) {
                        
                        let decoder = JSONDecoder()
                        let dataModel = try decoder.decode(UserInfoAPIModel.self, from: jsonData)
                        debugPrint("dataModel",dataModel)
                        
                        
                        let jsonData = try JSONEncoder().encode(dataModel)
                        self.userDefaultManager.loginUserData = jsonData
                        
                    }
                } catch {
                    debugPrint("Sign in Parse Error: ",error)
                }
                
            } failure: { (error) in
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    //MARK: - User Logout -
    
    func callUserLogout(completion: @escaping (Bool,String)-> ()){
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.logout) { success, message  in
                debugPrint(success)
                completion(true,message)
            } failure: { (error) in
                completion(false,error)
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    //MARK: - Delete User -
    
    func callDeleteAccount(completion: @escaping (Bool,String)-> ()){
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.deleteAccount) { success, message  in
                debugPrint(success)
                completion(true,message)
            } failure: { (error) in
                completion(false,error)
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    //MARK: - Country Code API -
    
    func getCountryNameList(success: @escaping (_ response: [CountryListModel]) -> (), failure: @escaping (String) -> Void){
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callGetAPI(apiName: APIName.country_code, method: .get, params: [:]) { response,message  in
                do {
                    if let jsonData = try? JSONSerialization.data(withJSONObject: response as Any) {
                        
                        let decoder = JSONDecoder()
                        let dataModel = try decoder.decode(CountryCodeAPIDataModel.self, from: jsonData)
                        debugPrint("dataModel",dataModel)
                        if let countryData = dataModel.country_list{
                            success(countryData)
                        }
                        else{
                            failure("There is some error occured")
                        }
                    }
                } catch {
                    debugPrint("Get Country Code Parse Error: ",error)
                }
            } failure: { error in
                
                failure("Error message: \(error)")
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    //MARK: - OTP verification -
    
    func getOTPVerificationAPI(otp : String, completion: @escaping (User?) -> ()){
        
        let params = [API_Param_Name.otp : otp as AnyObject]
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.otp_verification, method: .post, params: params) { response,message  in
                
                do {
                    if let jsonData = try? JSONSerialization.data(withJSONObject: response as Any) {
                        
                        let decoder = JSONDecoder()
                        let dataModel = try decoder.decode(UserInfoAPIModel.self, from: jsonData)
                        debugPrint("dataModel",dataModel)
                        if dataModel.user?.is_profile_completed ?? false{
                            let jsonData = try JSONEncoder().encode(dataModel)
                            self.userDefaultManager.loginUserData = jsonData
                        }
                        completion(dataModel.user)
                    }
                } catch {
                    debugPrint("Sign in Parse Error: ",error)
                }
                
            } failure: { (error) in
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    
    func getOTPVerificationFirebase(completion: @escaping (User?) -> ()){
        
        let params = [API_Param_Name.number_is_verified : 1 as AnyObject]
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.user_verification_status, method: .post, params: params) { response,message  in
                
                do {
                    if let jsonData = try? JSONSerialization.data(withJSONObject: response as Any) {
                        
                        let decoder = JSONDecoder()
                        let dataModel = try decoder.decode(UserInfoAPIModel.self, from: jsonData)
                        debugPrint("dataModel",dataModel)
                        if dataModel.user?.is_profile_completed ?? false{
                            let jsonData = try JSONEncoder().encode(dataModel)
                            self.userDefaultManager.loginUserData = jsonData
                        }
                        completion(dataModel.user)
                    }
                } catch {
                    debugPrint("Sign in Parse Error: ",error)
                }
                
            } failure: { (error) in
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    //MARK: Resend OTP
    
    func resendOTPAPI(Success : @escaping(_ success: Bool,_ message: String) -> ()){
        
        let params = [API_Param_Name.OTP_key : Constant.OTP_value as AnyObject]
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.resend_otp, method: .post, params: params) { response,message  in
                debugPrint(response)
                if response.count != 0{
                    Success(true,message)
                }
                else{
                    Success(false,message)
                }
                
            } failure: { (error) in
                Success(false,error)
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    //MARK: - Get Pending Friend Request -
    
    func getPendingFriendRequest(completion: @escaping (_ success: [PendingFriendReqListModel]) -> (), failure: @escaping (String) -> Void){
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callGetAPI(apiName: APIName.pending_friend_request) { response,message  in
                do {
                    if let jsonData = try? JSONSerialization.data(withJSONObject: response as Any) {
                        
                        let decoder = JSONDecoder()
                        let dataModel = try decoder.decode(PendingFriendRequestAPIModel.self, from: jsonData)
                        debugPrint("dataModel",dataModel)
                        completion(dataModel.pending_friends_request)
                    }
                } catch {
                    debugPrint("Get Pending Request Parse Error: ",error)
                }
            } failure: { (error) in
                failure("Error message: \(error)")
            }
        }
        else{
            failure("Internet is not available")
        }
    }
    
    //MARK: - Get Friend Request -
    
    func getFriendRequest(completion: @escaping (_ success: [ReceivedReqListModel]) -> (), failure: @escaping (String) -> Void){
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callGetAPI(apiName: APIName.received_friend_request) { response,message  in
                do {
                    if let jsonData = try? JSONSerialization.data(withJSONObject: response as Any) {
                        
                        let decoder = JSONDecoder()
                        let dataModel = try decoder.decode(FriendReqAPIModel.self, from: jsonData)
                        debugPrint("dataModel",dataModel)
                        completion(dataModel.received_friends_request)
                    }
                } catch {
                    debugPrint("Get Friend Request Parse Error: ",error)
                }
            } failure: { (error) in
                failure("Error message: \(error)")
            }
        }
        else{
            failure("Internet is not available")
        }
    }
    
    //MARK: - Accept & Reject friend Req -
    
    func callAcceptAndRejectReqAPI(requestId: Int, status: String, completion : @escaping (Bool,String) -> ()){
        let params = [API_Param_Name.request_id: requestId as AnyObject, API_Param_Name.status: status as AnyObject]
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.accept_friend_request, method: .post, params: params) { response,message  in
                debugPrint(response)
                completion(true,message)
            } failure: { (error) in
                debugPrint("Error message: \(error)")
                completion(false,error)
            }
        }
    }
    
    //MARK: - Image Upload -
    
    func getImageUploadAPI(friendIds : String, image: UIImage, completion : @escaping(Bool) -> ()){
        
        let params = [API_Param_Name.friend_id : friendIds as AnyObject]
        let multipartData = [API_Param_Name.image : image]
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callMultipartPostAPI(apiName: APIName.send_image, method: .post, params: params, multiPartData: multipartData) { response in
                debugPrint(response)
                completion(true)
            } failure: { (error) in
                completion(false)
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    //MARK: - Friend List -
    
    func getFriendListAPI(completion: @escaping (_ success: [FriendListModel]) -> (), failure: @escaping (String) -> Void){
        
        if Reachability.isInternetAvailable{
            var arrFriendList = [String]()
            NetworkManager.shared.callPostAPI(apiName: APIName.friend_list) { response,message  in
                do {
                    if let jsonData = try? JSONSerialization.data(withJSONObject: response as Any) {
                        
                        let decoder = JSONDecoder()
                        let dataModel = try decoder.decode(FriendListAPIModel.self, from: jsonData)
                        debugPrint("dataModel",dataModel)
                        for data in dataModel.friend_list{
                            arrFriendList.append(data.full_name ?? "")
                        }
                        self.userDefaultManager.friendList = arrFriendList
                        completion(dataModel.friend_list)
                    }
                } catch {
                    debugPrint("Friend List Parse Error: ",error)
                }
            } failure: { (error) in
                failure("Error message: \(error)")
            }
        }
        else{
            failure("Internet is not available")
        }
    }
    
    //MARK: - Send Friend Request -
    
    func callSendFriendRequestAPI(phonoNo : String, countryCode: String, completion: @escaping(Bool) -> ()){
        
        let params = [API_Param_Name.phone : phonoNo as AnyObject, API_Param_Name.country_code : countryCode as AnyObject]
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.send_friend_request, method: .post, params: params) { response,message  in
                
    //            if response.status != nil{
                    completion(true)
    //            }
            } failure: { (error) in
                completion(false)
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    //MARK: - Get History -
    
    func getWidgetHistory(completion : @escaping ([HistoryListModel]) -> ()){
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callGetAPI(apiName: APIName.widget_image_list) { response,message  in
                
                do {
                    if let jsonData = try? JSONSerialization.data(withJSONObject: response as Any) {
                        
                        let decoder = JSONDecoder()
                        let dataModel = try decoder.decode(HistoryAPIModel.self, from: jsonData)
                        debugPrint("dataModel",dataModel)
                        completion(dataModel.widget_history)
                                            
                    }
                } catch {
                    debugPrint("Get History Parse Error: ",error)
                }
                
            } failure: { (error) in
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    //MARK: - Resend Image -
    
    func resendImageAPI(frinedIds : String, imageId: String, completion : @escaping(Bool,String) -> ()){
        
        let params = [API_Param_Name.friend_id : frinedIds as AnyObject, API_Param_Name.image_id : imageId as AnyObject]
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.resend_image, method: .post, params: params) { response,message  in
                debugPrint(response)
                completion(true,message)
            } failure: { (error) in
                completion(false,error)
                debugPrint("Error message: \(error)")
            }
        }
    }
    
    //MARK: - Unfriend API -
    
    func unfriendAPI(friendId : Int, completion: @escaping(Bool,String) -> ()){
        let params = [API_Param_Name.unfriend_id : friendId as AnyObject]
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.unfriend, method: .post, params: params) { response,message  in
                debugPrint(response)
                completion(true,message)
            } failure: { (error) in
                debugPrint("Error message: \(error)")
                completion(false,error)
            }
        }
    }
            
    //MARK: - Update Profile -
    
    func getUpdateProfileAPI(firstName: String, lastName: String, completion: @escaping (Bool,String) -> ()){
        
        let params = [API_Param_Name.first_name : firstName as AnyObject, API_Param_Name.last_name : lastName as AnyObject]
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.update_profile, method: .post, params: params) { response,message  in
                
                do {
                    if let jsonData = try? JSONSerialization.data(withJSONObject: response as Any) {
                        
                        let decoder = JSONDecoder()
                        let dataModel = try decoder.decode(UserInfoAPIModel.self, from: jsonData)
                        debugPrint("dataModel",dataModel)
                        
                        
                        let jsonData = try JSONEncoder().encode(dataModel)
                        self.userDefaultManager.loginUserData = jsonData
                        completion(true,message)
                    }
                } catch {
                    debugPrint("Sign in Parse Error: ",error)
                }
                
            } failure: { (error) in
                completion(false,error)
                debugPrint("Error Message :", error)
            }
        }
    }
    
    //MARK: - Delete Image from History -
    
    func deleteImageHistory(imageId : String, completion : @escaping(Bool,String)->()){
        
        let params = [API_Param_Name.image_id : imageId as AnyObject]
        
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callPostAPI(apiName: APIName.delete_image, method: .post, params: params) { response,message  in
                debugPrint(response)
                completion(true,message)
            } failure: { (error) in
                completion(false,error)
                debugPrint("Error Message :", error)
            }
        }
    }
    
    //MARK: - Get last sent friend list -
    
    func getLastSentFriendList(completion : @escaping([LastSentFriendModel]) -> ()){
        if Reachability.isInternetAvailable{
            NetworkManager.shared.callGetAPI(apiName: APIName.get_sent_friend_list) { response,message  in
                do {
                    if let jsonData = try? JSONSerialization.data(withJSONObject: response as Any) {
                        
                        let decoder = JSONDecoder()
                        let dataModel = try decoder.decode(LastSentFriendAPIModel.self, from: jsonData)
                        debugPrint("dataModel",dataModel)
                        
                        completion(dataModel.image)
                    }
                } catch {
                    debugPrint("Last sent Friend list Parse Error: ",error)
                }
            } failure: { (error) in
                debugPrint("Error Message :", error)
            }
        }
    }
    
    //MARK: - Get History with paggination -
    func getHistoryList(current_page : Int, page_limit : Int, completion : @escaping (HistoryAPIModel) -> ()){
        if Reachability.isInternetAvailable{
            
            let params = [API_Param_Name.page : current_page as AnyObject, API_Param_Name.per_page_limite : page_limit as AnyObject]
            
            NetworkManager.shared.callPostAPI(apiName: APIName.get_status_history, method: .post, params: params) { response,message  in
                
                do {
                    if let jsonData = try? JSONSerialization.data(withJSONObject: response as Any) {
                        
                        let decoder = JSONDecoder()
                        let dataModel = try decoder.decode(HistoryAPIModel.self, from: jsonData)
                        print("dataModel",dataModel)
                        completion(dataModel)
                                            
                    }
                } catch {
                    debugPrint("Get History Parse Error: ",error)
                }
                
            } failure: { (error) in
                debugPrint("Error Message :", error)
            }
        }
    }
    
    //MARK: - Update Device Token -
    
    func updateDeviceToken(){
        if Reachability.isInternetAvailable{
            
            let params = [API_Param_Name.device_token : self.userDefaultManager.deviceToken as AnyObject]
            
            NetworkManager.shared.callPostAPI(apiName: APIName.update_device_token, method: .post, params: params) { response,message  in
                debugPrint(response)
            } failure: { (error) in
                debugPrint("Error Message :", error)
            }
        }
    }
    
    //MARK: - Cancle Pending Request -
    
    func canclePendingRequest(requestId : Int, completion: @escaping(Bool,String) -> ()){
        if Reachability.isInternetAvailable{
            let params = [API_Param_Name.request_id : requestId as AnyObject]
            
            NetworkManager.shared.callPostAPI(apiName: APIName.cancel_pending_request, method: .post, params: params) { response,message  in
                completion(true,message)
            } failure: { (error) in
                debugPrint("Error Message :", error)
                completion(false,error)
            }
        }
    }
}
