//
//  NetworkManager.swift

import Foundation
import UIKit
import Alamofire
import RNCryptor

let kData = "data"
let kMessage = "message"
let kStatus = "status"

class NetworkManager : NSObject{
    
    static let shared : NetworkManager = NetworkManager()
    let userDefaultManager = UserDefaultManager.shared
    let remoteConfig = FIRRemoteManagement.shared
    let reachability = Reachability()
    let baseUrl: String = isProductionMode ? "https://wapi.livepic.cc/api/v2/" : "https://web.appethos.com/liv-pic-widget-backend/public/api/v2/" //"http://172.16.16.189/liv-pic-widget-backend/public/api/v2/" /*"https://web.theappauthors.com/1320-liv-pic-widget-backend/public/api/v2/"*/
    
    func callMultipartPostAPI(apiName : String, method : HTTPMethod = .post, params : [String : AnyObject] = [:], multiPartData : [String : UIImage] = [:],success: @escaping (_ response: Dictionary<String, AnyObject>) -> Void, failure: @escaping (String) -> Void){
        
        do{
            
            let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
            
            let password = self.remoteConfig.cipherKerForAPI
            
            let dataSet = RNCryptor.encrypt(data: jsonData, withPassword: password)
            
            var headers:HTTPHeaders = [
                "Content-Type": "application/json",
            ]
            let data = [API_Param_Name.dataset : dataSet]
            if self.userDefaultManager.loginUserToken.isEmpty == false { //Required to Login
                headers["Authorization"] = "Bearer \(userDefaultManager.loginUserToken)"
            }
            
            var request = URLRequest(url: URL(string: baseUrl + apiName)!)
            request.headers = headers
            request.httpMethod = method.rawValue
            
            AF.upload(multipartFormData: { (multipart) in
                
                for (key, value) in multiPartData{
                    let img = value
                    multipart.append(img.jpegData(compressionQuality: 0.3)!, withName: key, fileName: "image.jpg", mimeType: "image/jpg")

                }
                
                for (key, value) in data{
                    multipart.append(value.base64EncodedData(), withName: key)
                }
                
            }, with: request).responseString { (response) in
                
                switch response.result {
                case .success(let decodedString):
                    debugPrint(decodedString)
                    
                    do {
                        
                        if let responseString = Data(base64Encoded: decodedString){
                            let decrypt = try RNCryptor.decrypt(data: responseString, withPassword: password)
                            
                            do {
                                let json = try JSONSerialization.jsonObject(with: decrypt, options: [.fragmentsAllowed])
                                
                                if let jsonData = json as? [String : AnyObject] {
                                    
                                    debugPrint("✅ ✅ API Name -> \(self.baseUrl + apiName)")
                                    debugPrint("✅ ✅ Params -> \(params)")
                                    debugPrint("✅ ✅ Response -> \(jsonData)")

                                    if jsonData[kStatus] as? Bool == true {
                                        success(jsonData[kData] as? [String : AnyObject] ?? [:])
                                    }
                                    else {
                                        #if MAINTARGET
                                        Utilities.showAlertView(nil, (jsonData[kMessage] as? String) ?? "") { _ in}
                                        #endif
                                        failure((jsonData[kMessage] as? String) ?? "")
                                    }
                                }
                                else {
                                    failure("There is some error occured")
                                }

                            } catch {
                                debugPrint(error)
                                failure("There is some error occured")
                            }
                        }
                    }
                    catch {
                        debugPrint(error.localizedDescription)
                        failure("There is some error occured")
                    }
                case .failure(let error):
                    debugPrint(error)
                    failure("There is some error occured")
                }
            }
        }
        catch{
            debugPrint(error.localizedDescription)
        }
        
    }
    
    //MARK: - POST API -
    
    func callPostAPI(apiName : String, method : HTTPMethod = .post, params : [String : AnyObject] = [:], success: @escaping (_ response: Dictionary<String, AnyObject>, _ message : String) -> Void, failure: @escaping (String) -> Void){
        
        do{
            
            let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
            
            let password = self.remoteConfig.cipherKerForAPI
            
            let dataSet = RNCryptor.encrypt(data: jsonData, withPassword: password)
            
            var headers:HTTPHeaders = [
                "Content-Type": "application/json",
            ]
            
            if self.userDefaultManager.loginUserToken.isEmpty == false { //Required to Login
                headers["Authorization"] = "Bearer \(userDefaultManager.loginUserToken)"
            }
            
            var request = URLRequest(url: URL(string: baseUrl + apiName)!)
            request.headers = headers
            request.httpMethod = method.rawValue
            request.httpBody = Data(dataSet.base64EncodedString().utf8)
                  
            AF.request(request).responseString { (response) in
                
                switch response.result {
                case .success(let decodedString):
                    debugPrint(decodedString)
                    
                    do {
                        
                        if let responseString = Data(base64Encoded: decodedString){
                            let decrypt = try RNCryptor.decrypt(data: responseString, withPassword: password)
                            debugPrint("decrypted data ============ ",decrypt)
                            
                            do {
                                let json = try JSONSerialization.jsonObject(with: decrypt, options: [.fragmentsAllowed])
                                debugPrint("decrypted text ============ ",json)
                                
                                if let jsonData = json as? [String : AnyObject] {

                                    debugPrint("✅ ✅ API Name -> \(self.baseUrl + apiName)")
                                    debugPrint("✅ ✅ Params -> \(params)")
                                    debugPrint("✅ ✅ Response -> \(jsonData)")

                                    if jsonData[kStatus] as? Bool == true {
                                        success(jsonData[kData] as? [String : AnyObject] ?? [:], jsonData[kMessage] as? String ?? "")
                                    }
                                    else {
                                        failure((jsonData[kMessage] as? String) ?? "")
//                                        #if MAINTARGET
//                                        Utilities.showAlertView(nil, (jsonData[kMessage] as? String) ?? "") { _ in}
//                                        #endif
                                    }
                                }
                                else {
                                    failure("There is some error occured")
                                }

                            } catch {
                                debugPrint(error)
                                failure("There is some error occured")
                            }
                        }
                    }
                    catch {
                        debugPrint(error.localizedDescription)
                        failure("There is some error occured")
                    }
                case .failure(let error):
                    debugPrint(error)
                    failure("There is some error occured")
                }
            }
        }
        catch{
            debugPrint(error.localizedDescription)
        }
    }
    
    //MARK: - GET API -
    
    func callGetAPI(apiName : String, method : HTTPMethod = .get, params : [String : AnyObject] = [:], success: @escaping (_ response: Dictionary<String, AnyObject>, _ message : String) -> Void, failure: @escaping (String) -> Void){
        
        do{
            
            let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
            
            let password = "mnTy9JzI8xHTUZ72uOOOdYfOmBzLcx7E"
            
            let dataSet = RNCryptor.encrypt(data: jsonData, withPassword: password)
            
            var headers:HTTPHeaders = [
                "Content-Type": "application/json",
            ]
            
            if self.userDefaultManager.loginUserToken.isEmpty == false { //Required to Login
                headers["Authorization"] = "Bearer \(userDefaultManager.loginUserToken)"
            }
            
            var request = URLRequest(url: URL(string: baseUrl + apiName + "?\(dataSet.base64EncodedString().utf8)")!)
            request.headers = headers
            request.httpMethod = method.rawValue
                  
            AF.request(request).responseString { (response) in
                
                switch response.result {
                case .success(let decodedString):
                    debugPrint(decodedString)
                    
                    do {
                        
                        if let responseString = Data(base64Encoded: decodedString){
                            
                            let decrypt = try RNCryptor.decrypt(data: responseString, withPassword: password)
                            debugPrint("decrypted data ============ ",decrypt)
                            
                            do {
                                let json = try JSONSerialization.jsonObject(with: decrypt, options: [.fragmentsAllowed])
                                debugPrint("decrypted text ============ ",json)
                                
                                if let jsonData = json as? [String : AnyObject] {

                                    debugPrint("✅ ✅ API Name -> \(self.baseUrl + apiName)")
                                    debugPrint("✅ ✅ Params -> \(params)")
                                    debugPrint("✅ ✅ Response -> \(jsonData)")

                                    if jsonData[kStatus] as? Bool == true {
                                        success(jsonData[kData] as? [String : AnyObject] ?? [:], jsonData[kMessage] as? String ?? "")
                                    }
                                    else {
                                        failure((jsonData[kMessage] as? String) ?? "")
                                    }
                                }
                                else {
                                    failure("There is some error occured")
                                }

                            } catch {
                                debugPrint(error.localizedDescription)
                                failure("There is some error occured")
                            }
                        }
                    }
                    catch {
                        debugPrint(error.localizedDescription)
                        failure("There is some error occured")
                    }
                case .failure(let error):
                    debugPrint(error)
                    failure("There is some error occured")
                }
            }
        }
        catch{
            debugPrint(error.localizedDescription)
            
        }
    }
}
