//
//  YHNetRequest.swift
//  galaxy
//
//  Created by EDY on 2023/12/20.
//

import Foundation
import Alamofire
import CryptoSwift
import UIKit
import CoreServices
//class YHNetErrorModel {
//    var responseStatusCode: Int = 0
//    var responseStatusCodeStr: String = ""
//    var errResponseMsg: String = ""
//    var errReaponseCode: String = ""
//    var errReaponseTimeOutCode: Int = 0
//    var responseErrorType: NetResponseErrorType = .failType
//}

//定义客户端通用的错误码
public enum YHErrorCode : Int32 {
    case success = 0
    case networkFail = -1
    case unknowError = -10000
    case dictParseError = -10001
    case tokenInvalidError = 20001 // 登录token失效
    case forceUpdate = 10025  // 强制更新版本
    case peopleMatchBlackList = 20005 // 人脉匹配黑名单
    case unregisterError = 20007  //手机号已注销
    
    public func description() -> String {
        switch self {
        case .success:
            return "成功"
        case .networkFail:
            return "网络不可用"
        case .unknowError:
            return "未知错误"
        case .dictParseError:
            return "字典解析错误"
        case .tokenInvalidError:
            return "登录token失效"
        case .forceUpdate:
            return "强制更新版本"
        case .unregisterError:
            return "手机号已注销"
        default:
            return "未知"
        }
    }
}


public struct YHErrorModel {
    var errorCode : Int32 = YHErrorCode.unknowError.rawValue
    var errorMsg : String = YHErrorCode.unknowError.description()
}

class YHNetRequest: NSObject {
    ///成功回调
    typealias SuccessHandlerType = (([String:Any],Int) ->Void)
    typealias SuccessResultType = ((NetWorkBaseModel,Int) ->Void)
    ///失败回调
    typealias FailureHandlerType = ((YHErrorModel) -> Void)
    ///请求类型
    private var requestType: HTTPMethod = .post
    ///  URL
    private var url: String?
    ///  参数
    private var params: [String:Any]?
    ///  成功的回调
    private var success: SuccessResultType?
    ///  失败的回调
    private var failure: FailureHandlerType?
    ///  headers 设置
    private var headers: HTTPHeaders?
    ///  数据请求
    private var httpRequest: DataRequest?
    private var businessCode: String = "4001001"

    override init() {
        super.init()
        
        headers = YHNetRequest.getCommonHeaders()
    }
    
    static func getCommonHeaders() -> HTTPHeaders {
        var requestHeader = HTTPHeaders()
        
        requestHeader.add(name:"Conatent-Type",value:"application/json")
        requestHeader.add(name:"Accept",value:"application/json")
        
        requestHeader.add(name:"appid",value:"1")
        let dateStr = String(Date().timeIntervalSince1970)
        requestHeader.add(name:"timestamp",value:dateStr)
        
        requestHeader.add(name:"app_platform",value:"iOS")
        requestHeader.add(name:"app_os",value:"iOS")
        let version = UIDevice.appVersion()
        requestHeader.add(name:"app_version",value:version)
        requestHeader.add(name:"app_channel",value:"appStore")
        
        requestHeader.add(name:"app_phoneModel",value:UIDevice.iPhoneModelName())
        requestHeader.add(name:"os_version_name",value:UIDevice.iPhoneVersion())
        
        requestHeader.add(name:"pass",value:"")
        
        let appkey = "958364f87222c200a72414f492bf0e26"
        let signOrgiString = "appid=" + "1" + "&" + "timestamp=" + dateStr + "&" + "appkey=" + appkey
        let sign = signOrgiString.md5()
        print("sign = \(sign)")
        
        requestHeader.add(name:"sign",value:sign)
        requestHeader.add(name: "token", value: YHLoginManager.shared.userModel?.token ?? "-")
        if !YHLoginManager.shared.deviceTokenModel.registerId.isEmpty {
            requestHeader.add(name: "device-id", value: YHLoginManager.shared.deviceTokenModel.registerId)
        }
        return requestHeader
    }
    
    func businessCode(_ code: String) -> Self {
        self.businessCode = code
        return self
    }
    
    ///  链式语法
    func url(_ url:String?) -> Self{
        self.url = url ?? ""
        return self
    }
    ///  请求类型
    func requestType(_ type: HTTPMethod) -> Self {
        self.requestType = type
        return self
    }
    ///请求参数
    func params(_ params: [String:Any]?) -> Self {
        self.params = params
        return self
    }
    ///成功
    func success(_ handler:@escaping SuccessResultType) -> Self {
        self.success = handler
        return self
    }
    ///失败
    func failed(_ handler:@escaping FailureHandlerType) -> Self {
        self.failure = handler
        return self
    }
    ///获取包头
    func getHeader() -> HTTPHeaders {
        var requestHeader = HTTPHeaders()
        if let header = headers {
            requestHeader = header
        } else {
            requestHeader.add(name:"Conatent-Type",value:"application/json")
            requestHeader.add(name:"Accept",value:"application/json")
        }
        return requestHeader
    }
    
    ///开始请求
    func startRequest() -> Request? {
        if YHNetworkStatusManager.shared.isNetWorkOK == false {
            DispatchQueue.main.async {
                YHHUD.flash(message: "网络不可用，请检查网络设置")
                guard let errorBlock = self.failure else { return }
                let errorModel = YHErrorModel(errorCode: 0, errorMsg: "网络不可用，请检查网络设置")
                errorBlock(errorModel)
                return
            }
            return httpRequest
        }
        
        var requestHeaders = getHeader()
        
//#if DEBUG
//        printLog("网络请求头数据：" )
//        printLog(requestHeaders)
//#endif
        
        ///不使用缓存
        AF.sessionConfiguration.requestCachePolicy = .reloadIgnoringCacheData
        AF.sessionConfiguration.timeoutIntervalForRequest = 20
        
        let encoding = (self.requestType == .get ? URLEncoding(destination: .queryString) : JSONEncoding()) as ParameterEncoding
        requestHeaders.add(name:"businessCode",value: businessCode)
        httpRequest = AF.request(self.url!, method: self.requestType,parameters: self.params, encoding:encoding, headers: requestHeaders, interceptor: nil, requestModifier: nil)
        
        httpRequest?.responseString(completionHandler: { string in
#if DEBUG
            print("================================begin")
            print("网络请求接口:\n" + (self.url ?? ""))
            print("网络请求头数据如下:")
            print(requestHeaders)
            print("业务参数:")
            
            if let param = self.params {
                print(param)
            }
            print("网络请求返回数据:\n \(string)")
            print("********************************end")
#endif
            
            self.completeHandle(string: string)
        })
        
        return httpRequest
    }
    
    ///开始请求
    func uploadRequest(_ headers: HTTPHeaders,_ image: UIImage) -> Request? {
        if YHNetworkStatusManager.shared.isNetWorkOK == false {
            DispatchQueue.main.async {
                YHHUD.flash(message: "网络不可用，请检查网络设置")
                guard let errorBlock = self.failure else { return }
                let errorModel = YHErrorModel(errorCode: 0, errorMsg: "网络不可用，请检查网络设置")
                errorBlock(errorModel)
                return
            }
            return httpRequest
        }
        
        
        let size = picMaxSize
        guard let imageData = image.compressOriginalImage(size) else { return httpRequest }
        

#if DEBUG
        let tttt = Double(imageData.count)/1024.0/1024.0
        let ssss = String(format: "%.2f", tttt)
        YHHUD.flash(message: "实际大小：" + ssss + " M")
#endif
        
        let multipartFormData = MultipartFormData()
        
        // 将图片添加到multipartFormData中
        multipartFormData.append(imageData, withName: "file", fileName: "image.jpg", mimeType: "image/jpeg")
        
        // 发送POST请求
        let uploadRequest = AF.upload(multipartFormData: multipartFormData, to: self.url!, headers: headers)
        
        uploadRequest.responseString(completionHandler: { string in
            self.completeHandle(string: string)
        })
        
        return uploadRequest
    }
    
    func uploadFileRequest(_ headers: HTTPHeaders, _ url: String) -> Request? {
        if YHNetworkStatusManager.shared.isNetWorkOK == false {
            DispatchQueue.main.async {
                YHHUD.flash(message: "网络不可用，请检查网络设置")
                guard let errorBlock = self.failure else { return }
                let errorModel = YHErrorModel(errorCode: 0, errorMsg: "网络不可用，请检查网络设置")
                errorBlock(errorModel)
                return
            }
            return httpRequest
        }
        
        guard let fileData = try? Data(contentsOf: URL(string: url) ?? URL(fileURLWithPath: "")) else {
            return httpRequest
        }
        
        let fileExtension = URL(fileURLWithPath: url).pathExtension.lowercased()
        let fileUTI = mimeType(for: url)
#if DEBUG
        printLog("\(fileExtension)-------\(fileUTI ?? "")")
#endif
        let multipartFormData = MultipartFormData()
        
        // 将图片添加到multipartFormData中
        multipartFormData.append(fileData, withName: "file", fileName: "image.\(fileExtension)", mimeType: fileUTI)
        
        // 发送POST请求
        let uploadRequest = AF.upload(multipartFormData: multipartFormData, to: self.url!, headers: headers)
        
        uploadRequest.responseString(completionHandler: { string in
            self.completeHandle(string: string)
        })
        
        return uploadRequest
    }
    
    func mimeType(for path: String) -> String? {
        let url = URL(fileURLWithPath: path)
        let pathExtension = url.pathExtension
        
        if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue() {
            if let mimeType = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
                return mimeType as String
            }
        }
        return nil
    }
    
    
    /// 请求response完成处理
    func completeHandle(string: AFDataResponse<String>) {
        let responseResult = string.result
        var statusCode = string.response?.statusCode ?? 0
        let errorResponseMsg = string.error?.localizedDescription ?? ""
        let resultValue = string.value ?? ""
        let serverDict = resultValue.toDictionary()
        switch responseResult {
        case .success:
            break
        case .failure:
            if let underyingError = string.error?.asAFError?.underlyingError {
                if let urlError = underyingError as? URLError {
                    switch urlError.code{
                    case.timedOut:
                        statusCode = urlError.code.rawValue
                    case.cannotConnectToHost:
                        statusCode = urlError.code.rawValue
                    case.cannotFindHost:
                        statusCode = urlError.code.rawValue
                    case.unsupportedURL:
                        statusCode = urlError.code.rawValue
                    default:
                        break
                    }
                }
            }
            break
        }
        
        if statusCode == 200 {
            DispatchQueue.main.async {
                
//                printLog(serverDict)
                guard let obj = NetWorkBaseModel.deserialize(from: serverDict) else {
                    print("解析出错了。 兄弟")
                    guard let errorBlock = self.failure else { return }
                    let errorModel = YHErrorModel(errorCode: Int32(statusCode), errorMsg: errorResponseMsg)
                    errorBlock(errorModel)
                    return
                }
                
                if obj.code == YHErrorCode.forceUpdate.rawValue { // 强制版本升级
                    DispatchQueue.main.async {
                        YHAppVersionForceUpdateView.alertView().show()
                        // 发送强制更新通知
                        NotificationCenter.default.post(name: YhConstant.YhNotification.didForceUpgradeNotifiction, object: nil)
                        YHHUD.hide()
                        guard let errorBlock = self.failure else { return }
                        let errorModel = YHErrorModel(errorCode: Int32(statusCode), errorMsg: errorResponseMsg)
                        errorBlock(errorModel)
                    }
                    return
                }
                
                if obj.code == YHErrorCode.tokenInvalidError.rawValue {
                    DispatchQueue.main.async {
                        YHLoginManager.shared.clearUserInfo()
                        YHHUD.flash(message: "登录状态失效")
                        // 发送清空所有红点通知
                        NotificationCenter.default.post(name: YhConstant.YhNotification.didMarkAllMessagesReadedNotifiction, object: nil)
                        UIViewController.current?.navigationController?.popToRootViewController(animated: false)
                        goTabBarBy(tabType: .home)
                        YHHUD.hide()
                        guard let errorBlock = self.failure else { return }
                        let errorModel = YHErrorModel(errorCode: Int32(statusCode), errorMsg: errorResponseMsg)
                        errorBlock(errorModel)
                    }
                    return
                }
                
                DispatchQueue.main.async {
                    guard let suclock = self.success else { return }
                    suclock(obj, statusCode)
                }
            }
        } else {
            guard let errorBlock = self.failure else { return }
            if statusCode == 502 {
                YHHUD.flash(message: "502 Bad")
            }
            
            let errorModel = YHErrorModel(errorCode: Int32(statusCode), errorMsg: errorResponseMsg)
            errorBlock(errorModel)
        }
    }
}

extension YHNetRequest {
    class func getRequest(url:String, params:[String:Any] = [:], _ businessCode: String = "4001001", successBlock: SuccessResultType!, failBlock: FailureHandlerType!) -> Request? {
        return YHNetRequest().businessCode(businessCode).url(url).requestType(.get).params(params).success(successBlock).failed(failBlock).startRequest()
    }
    
    class func postRequest(url:String, params:[String:Any] = [:], _ businessCode: String = "4001001", successBlock: SuccessResultType!, failBlock: FailureHandlerType!) -> Request? {
        return YHNetRequest().businessCode(businessCode).url(url).requestType(.post).params(params).success(successBlock).failed(failBlock).startRequest()
    }
    
    
    class func putRequest(url:String, params:[String:Any] = [:], _ businessCode: String = "4001001", successBlock: SuccessResultType!, failBlock: FailureHandlerType!) -> Request? {
        return YHNetRequest().businessCode(businessCode).url(url).requestType(.put).params(params).success(successBlock).failed(failBlock).startRequest()
    }
    
    class func uplaodRequest(url:String, headers:HTTPHeaders, image: UIImage, _ businessCode: String = "4001001", successBlock: SuccessResultType!, failBlock: FailureHandlerType!) -> Request? {
        return YHNetRequest().businessCode(businessCode).url(url).success(successBlock).failed(failBlock).uploadRequest(headers, image)
    }
    
    class func uplaodFileRequest(url:String, headers:HTTPHeaders, fileUrl: String, _ businessCode: String = "4001001", successBlock: SuccessResultType!, failBlock: FailureHandlerType!) -> Request? {
        return YHNetRequest().businessCode(businessCode).url(url).success(successBlock).failed(failBlock).uploadFileRequest(headers, fileUrl)
    }
}
