//
//  KMRequestServerManager.swift
//  PDF Master
//
//  Created by lizhe on 2023/2/22.
//

import Cocoa

enum KMRequestServerErrorCodeType: Int, CaseIterable {
    case unknown = 0 //未知
    case correct = 200 //正确
    case EXCEPTION_MSG_IMAGE_CODE_ERROR = 301
    case EXCEPTION_MSG_USER_NOT_FOUND = 302
    case EXCEPTION_MSG_TOKEN_IS_INVALID = 304
    case EXCEPTION_MSG_DEVICE_NUM_MAX = 305
    case EXCEPTION_MSG_USER_NOT_LOGIN = 306
    case EXCEPTION_MSG_GET_CODE_FAIL = 307
    case EXCEPTION_MSG_GET_TOKEN_FAIL = 308
    case EMAIL_VERIFY_CODE_KEY_ERROR = 309
    case EMAIL_REGISTER_ERROR = 310
    case EXCEPTION_MSG_PASSWORD_ERROR = 311
    case EXCEPTION_MSG_CODE_ACTION_ERROR = 312
    case EXCEPTION_MSG_CODE_SEND_ERROR = 313
    case EXCEPTION_MAIL_CODE_SEND_ERROR = 314
    case VERIFY_CODE_SEND_TOO_QUICKLY = 315
    case EXCEPTION_MSG_EMAIL_EXIST = 316
    case EXCEPTION_MSG_EMAIL_NOT_REGISTER = 317
    case EXCEPTION_MSG_EMAIL_LOGOUT_ING = 318
    case EXCEPTION_MSG_EMAIL_INVALID = 319
    case EXCEPTION_MSG_PASSWORD_NOT_INCONSISTENT = 320
    case EXCEPTION_MSG_PASSWORD_SIZE_MIN = 321
    case EXCEPTION_MSG_PASSWORD_SIZE_MAX = 322
    case EXCEPTION_MSG_PLEASE_ADD_AUTH_CONFIG = 323
    case EXCEPTION_MSG_USER_SUBSCRIPTION_IN_PROGRESS = 324
    case EXCEPTION_MSG_USER_TRAIL_IN_PROGRESS = 325
    case EXCEPTION_TIME_TRANSFER_ERROR = 326
    case EXCEPTION_MSG_PASSWORD_CONTAIN_EMRTY = 327
    case EXCEPTION_MSG_CREATE_ORDER_PARAMETER = 328//,"支付方式异常"),
    case EXCEPTION_MSG_EVENT_IS_CURRENTLY_NOT_SUPPORTED = 329 //, "当前事件暂不支持"),
    case EXCEPTION_MSG_THE_ACCOUNT_IS_ALREADY_LOGGED_IN_ON_OTHER_DEVICES = 330//, "账号已在其他设备登录"),
    case EXCEPTION_MSG_ABNORMAL_USER_STATUS = 331 //,"当前邮箱已被停用或者处于注销中状态"),
    case EXCEPTION_MSG_APP_STORE_TICKET_VALIDATION_FAILED = 332 //"AppStore票据验证失败"),
    case EXCEPTION_MSG_APP_STORE_TICKET_VALIDATION_NEED_TO_RETRY = 333// "AppStore票据验证需要重试"),
    case EXCEPTION_MSG_REPEAT_SUBSCRIPTION = 334 //"用户已订阅该产品"
    case EXCEPTION_MSG_RESTORING_PURCHASES_IS_NOT_CURRENTLY_SUPPORTED = 335 //"恢复购买暂不支持"),
    case EXCEPTION_MSG_USER_TRANSACTION_CANCELED_OR_FAILED = 336 //"用户交易取消或失败")
    case EXCEPTION_MSG_CURRENT_ORDER_NOT_RECORDED = 337 //"当前订单未记录,请稍后重试"),
    case EXCEPTION_MSG_THE_SAME_USER = 338//"同一用户,无需处理"),
    case EXCEPTION_MSG_THIRD_PAY_ID_ILLEGAL = 339//"thirdPayId非法"),
    case EXCEPTION_MSG_ORDER_DOES_NOT_EXIST = 340// "订单不存在"),
    case EXCEPTION_MSG_THE_ORDER_STATUS_IS_ABNORMAL = 341// "订单状态异常"),
    case EXCEPTION_MSG_TRANSACTION_ID_REPEAT = 342 //"transactionId重复"),
    
    case EMAIL_VERIFY_CODE_KEY_ERROR2 = 700
    
    static func typeOfMessage(type: KMRequestServerErrorCodeType?) -> String {
        var result: String = ""
        switch type {
        case .EXCEPTION_MSG_IMAGE_CODE_ERROR:
            result = "Graphic verification code error"
        case .EXCEPTION_MSG_USER_NOT_FOUND:
            result = "Email address is not registered"
        case .EXCEPTION_MSG_TOKEN_IS_INVALID:
            result = "Invalid token or token has expired"
        case .EXCEPTION_MSG_DEVICE_NUM_MAX:
            result = "You have reached the maximum number of devices, please log out of other devices and log in again."
        case .EXCEPTION_MSG_USER_NOT_LOGIN:
            result = "User is not logged in. Please log in and try again."
        case .EXCEPTION_MSG_GET_CODE_FAIL:
            result = "Failed to obtain authorization code"
        case .EXCEPTION_MSG_GET_TOKEN_FAIL:
            result = "Failed to obtain token"
        case .EMAIL_VERIFY_CODE_KEY_ERROR:
            result = "Email code error"
        case .EMAIL_REGISTER_ERROR:
            result = "Register error"
        case .EXCEPTION_MSG_PASSWORD_ERROR:
            result = "Wrong password. You can check whether the letter is uppercase or lowercase."
        case .EXCEPTION_MSG_CODE_ACTION_ERROR:
            result = "Incorrect code"
        case .EXCEPTION_MSG_CODE_SEND_ERROR:
            result = "Code send error"
        case .EXCEPTION_MAIL_CODE_SEND_ERROR:
            result = "Mail send error"
        case .VERIFY_CODE_SEND_TOO_QUICKLY:
            result = "Enter an existing verification code" //result = "Too many codes sent, please try again later."
        case .EXCEPTION_MSG_EMAIL_EXIST:
            result = "This email is already registered, please log in."
        case .EXCEPTION_MSG_EMAIL_NOT_REGISTER:
            result = "This account is not registered, click Sign Up to create a new account."
        case .EXCEPTION_MSG_EMAIL_LOGOUT_ING:
            result = "Your account is currently being canceled and cannot be logged in. If you have any questions, please contact customer service."
        case .EXCEPTION_MSG_EMAIL_INVALID:
            result = "Please enter the correct email format"
        case .EXCEPTION_MSG_PASSWORD_NOT_INCONSISTENT:
            result = "Wrong password. You can check whether the letter is uppercase or lowercase." //result = "Passwords are different. Please re-enter them."
        case .EXCEPTION_MSG_PASSWORD_SIZE_MIN:
            result = "Password must be 6-24 characters" //result = "At least 6 characters"
        case .EXCEPTION_MSG_PASSWORD_SIZE_MAX:
            result = "Password must be 6-24 characters" //result = "Up to 24 characters"
        case .EXCEPTION_MSG_PLEASE_ADD_AUTH_CONFIG:
            result = "Please add auth config"
        case .EXCEPTION_MSG_USER_SUBSCRIPTION_IN_PROGRESS:
            result = "You are still in the subscription and cannot cancel account. Please click Cancel Account after the subscription period ends."
        case .EXCEPTION_MSG_USER_TRAIL_IN_PROGRESS:
            result = "You are still in the subscription and cannot cancel account. Please click Cancel Account after the trial expired."
        case .EXCEPTION_TIME_TRANSFER_ERROR:
            result = "Time conversion failure"
        case .EMAIL_VERIFY_CODE_KEY_ERROR2:
            result = "Email code error"
        case .EXCEPTION_MSG_PASSWORD_CONTAIN_EMRTY:
            result = "Spaces are not allowed in password" //result = "The password cannot contain Spaces"
        case .EXCEPTION_MSG_CREATE_ORDER_PARAMETER:
            result = "Abnormal payment method"
        case .EXCEPTION_MSG_EVENT_IS_CURRENTLY_NOT_SUPPORTED:
            result = "The current event is not supported"
        case .EXCEPTION_MSG_THE_ACCOUNT_IS_ALREADY_LOGGED_IN_ON_OTHER_DEVICES:
            result = "Your account has been logged into another device."
        case .EXCEPTION_MSG_ABNORMAL_USER_STATUS:
            result = "This email account is no longer available or canceled."
        case .EXCEPTION_MSG_APP_STORE_TICKET_VALIDATION_FAILED:
            result = "AppStore receipt verification failed."
        case .EXCEPTION_MSG_APP_STORE_TICKET_VALIDATION_NEED_TO_RETRY:
            result = "Please re-verify the receipt."
        case .EXCEPTION_MSG_REPEAT_SUBSCRIPTION:
            result = "Users have already subscribed to PDF Master."
        case .EXCEPTION_MSG_RESTORING_PURCHASES_IS_NOT_CURRENTLY_SUPPORTED:
            result = "Restoring purchases may not work due to the temporary problem with the App Store system."
        case .EXCEPTION_MSG_USER_TRANSACTION_CANCELED_OR_FAILED:
            result = "Payment Cancelled or Failed."
        case .EXCEPTION_MSG_CURRENT_ORDER_NOT_RECORDED:
            result = "The current order is not recorded, please try again later."
        case .EXCEPTION_MSG_THE_SAME_USER:
            result = "Same user, no processing required."
        case .EXCEPTION_MSG_THIRD_PAY_ID_ILLEGAL:
            result = "ThirdPayID illegal"
        case .EXCEPTION_MSG_ORDER_DOES_NOT_EXIST:
            result = "This order does not exist."
        case .EXCEPTION_MSG_THE_ORDER_STATUS_IS_ABNORMAL:
            result = "This order status is abnormal."
        case .EXCEPTION_MSG_TRANSACTION_ID_REPEAT:
            result = "Duplicate TransactionID"
        case .unknown:
            result = ""
        case .correct:
            result = ""
            
        default:
            result = "Network error"
        }
        return result
    }
}

enum KMVerifyCodeType: String, CaseIterable {
    case unknown = "" //
    case register = "user_register" // 注册
    case logOff = "user_log_off" //注销
    case resetPassword = "user_reset_password" //重置密码
}

enum KMVerifyEmailType: String, CaseIterable {
    case login = "1" // 登录
    case register = "2" //注册
}

struct Result {
    var result: NSDictionary = [:]
    var message: String = ""
    var code : Int = 200
    var error: NSError?
}

typealias KMRequestServerComplete = (_ success: Bool, _ result: Result?) -> Void


class KMRequestServerManager: NSObject {
    static let manager = KMRequestServerManager()
    
    var loginAlert: NSAlert? = nil
}

//MARK: - 会员
extension KMRequestServerManager {
    /**
     @abstract 获取验证码
     @param verifyCodeType 验证入口类型
     @param email 邮箱
     */
    func getVerifyCode(verifyCodeType: KMVerifyCodeType, email: String, complete: @escaping KMRequestServerComplete) {
        let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/getVerifyCode"
        let params: [String: Any] = ["action": verifyCodeType.rawValue,
                                     "appId": "16",
                                     "receiver": email,
                                     "type": "0"]

        KMRequestServer.requestServer.request(urlString: urlString, method: .get, params: params) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                complete(true, result)
            } else {
                complete(false, result)
            }
        }
    }
    
    /**
     @abstract 注册
     @param userName  用户账号(邮箱)
     @param verifyCode 验证码
     */
    func register(userName: String, password: String, verifyCode: String, complete: @escaping (_ success: Bool, _ requestData: KMLightMemberToken?, _ result: Result) -> Void) {
        let uuid: String = GetHardwareUUID() ?? ""
        let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/emailRegister"
        let params: [String: Any] = ["appId": "16",
                                     "deviceSign": uuid,
                                     "password": password,
                                     "platformType": "0",
                                     "username": userName,
                                     "verifyCode": verifyCode,
                                     "model": "Mac"]

        KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
        } completion: { [unowned self] task, responseObject, error in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                //解析数据
                KMLightMemberToken.parseData(data: result.result) { data in
                    //登录成功
                    KMLightMemberManager.manager.logIn()
                    complete(true, data, result)
                }
            } else {
                complete(false, nil, result)
            }
        }
    }
    
    /**
     @abstract 注销
     @param verifyCode  验证码
     */
    func logOff(verifyCode: String, complete: @escaping KMRequestServerComplete) {
        let token: String = KMLightMemberManager.manager.token.access_token
        if token == "" {
            return
        }
        
        var urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/user/logOffForUser"
//        let params = ["code":verifyCode]
        urlString = urlString + (NSString(format: "?code=%@&appId=%@", verifyCode, "16") as String)
        KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: nil) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
            requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                //登出
                KMLightMemberCache.cache.clean()
                KMLightMemberManager.manager.logOut()
                complete(true, result)
            } else {
                complete(false, result)
            }
        }
    }
    
    /**
     @abstract 登录
     @param email  邮箱
     @param password 密码
     */
    func login(email: String, password: String, complete: @escaping (_ success: Bool, _ requestData: KMLightMemberToken?, _ result: Result?) -> Void) {
        var urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/emailLogin"
        let uuid: String = GetHardwareUUID() ?? ""
//        let params: [String: String] = ["appId": "16",
//                                        "deviceSign": uuid,
//                                        "email": email,
//                                        "password": password,
//                                        "platformType": "0"]

        urlString = urlString + (NSString(format: "?appId=16&deviceSign=%@&email=%@&password=%@&platformType=0&model=%@", uuid, email, password, "Mac") as String)
        KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: nil) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                //解析数据
                KMLightMemberToken.parseData(data: result.result) { data in
                    //登录成功
                    KMLightMemberManager.manager.logIn()
                    complete(true, data, nil)
                }
            } else {
                complete(false, nil, result)
            }
        }
    }
    
    /**
     @abstract 登出
     */
    func logout(complete: @escaping KMRequestServerComplete) {
        let token: String = KMLightMemberManager.manager.token.access_token
        if token == "" {
            return
        }
        let uuid: String = GetHardwareUUID() ?? ""
        var urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/user/logout"
        
//        let params: [String: Any] = ["deviceSign": uuid,
//                                     "appId": "16"]
        
        urlString = urlString + (NSString(format: "?appId=16&deviceSign=%@", uuid) as String)
        
        KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: nil) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
            requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
        } completion: { [unowned self] (task, responseObject, error) in
            //登出成功
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                //登出
                KMLightMemberManager.manager.logOut()
                complete(true, result)
            } else {
                complete(false, result)
            }
        }
    }
    
    /**
     @abstract 修改密码
     @param url  源文件url
     @param data 数据
     @retrun document
     */
    func resetPassword(account: String, firstPassword: String, secondPassword: String, verifyCode: String, complete: @escaping KMRequestServerComplete) {
        let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/resetPassword"
        let params: [String: Any] = ["account": account,
                                     "appId": "16",
                                     "firstPassword": firstPassword,
                                     "platformType": "0",
                                     "secondPassword": secondPassword,
                                     "verifyCode": verifyCode]

        KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                complete(true, result)
            } else {
                complete(false, result)
            }
        }
    }

    /**
     @abstract 获取用户信息
     */
    func getUserInfo(complete: @escaping (_ success: Bool, _ data: KMLightMemberUserInfo?, _ result: Result?, _ isLocal: Bool) -> Void) {
        let token: String = KMLightMemberManager.manager.token.access_token
        if token == "" {
            complete(false , nil, Result(message: "token 不存在", code: 304), false)
            return
        }
        //先拿缓存数据 再请求新数据
        let cacheData = KMLightMemberCache.cache.readData()
        if cacheData.count != 0 {
            KMLightMemberUserInfo.parseData(data: cacheData, needSave: false) { data in
                complete(true ,data, nil, true)
            }
        }
        
        let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/user/me"

        KMRequestServer.requestServer.request(urlString: urlString, method: .get, params: nil) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
            requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                //解析数据
                KMLightMemberUserInfo.parseData(data: responseObject as! NSDictionary) { data in
                    KMLightMemberManager.manager.reloadUserInfo()
                    complete(true, data, nil, false)
                }
            } else {
                complete(false, nil, result, false)
            }
        }
    }
    
    func getUserInfo2() async throws -> (Bool, Result) {
        let token: String = KMLightMemberManager.manager.token.access_token
        if token == "" {
            return (false, Result())
        }

        if #available(macOS 10.15, *) {
            return try await withCheckedThrowingContinuation { continuation in
                let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/user/me"
                KMRequestServer.requestServer.request(urlString: urlString, method: .get, params: nil) { requestSerializer in
                    requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
                    requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
                } completion: { [unowned self] (task, responseObject, error) in
                    let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
                    DispatchQueue.main.async {
                        if result.code == 200 {
                            //解析数据
                            KMLightMemberUserInfo.parseData(data: responseObject as! NSDictionary) { data in
                                KMLightMemberManager.manager.reloadUserInfo()
                                continuation.resume(returning: (true, result))
                            }
                        } else {
                            continuation.resume(returning: (false, result))
                        }
                    }
                }
            }
        } else {
            // Fallback on earlier versions
            return (true, Result())
        }
    }
    
    /**
     @abstract 验证码验证是否正确
     @param account  用户账号(邮箱)
     @param verifyCode 验证码
     @retrun verifyCodeType 验证码入口类型
     */
    func verificationCode(account: String, verifyCode: String, verifyCodeType: KMVerifyCodeType, complete: @escaping KMRequestServerComplete) {
        let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/isEmailCodeValid"
        let params: [String: Any] = ["account": account,
                                     "code": verifyCode,
                                     "type": verifyCodeType.rawValue,
                                     "appId": "16"]

        KMRequestServer.requestServer.request(urlString: urlString, method: .get, params: params) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                complete(true, result)
            } else {
                complete(false, result)
            }
        }
    }
    
    /**
     @abstract 邮箱验证
     @param account  用户账号(邮箱)
     @param verifyCodeType 验证码
     @retrun verifyCodeType 验证码入口类型
     */
    func verificationEmail(userName: String, verifyEmailType: KMVerifyEmailType, complete: @escaping KMRequestServerComplete) {
        let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/validUser"
        let params: [String: Any] = ["appId": "16",
                                     "username": userName,
                                     "platformType": "0",
                                     "validType": verifyEmailType.rawValue]

        KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                complete(true, result)
            } else {
                complete(false, result)
            }
        }
    }
}

//MARK: - 订阅
extension KMRequestServerManager {
    //创建订单
    func createOrder(productId: String, userId: String, complete: @escaping (_ success: Bool, _ orderId: String?, _ result: Result?) -> Void) {
        let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-website/pay/appStoreCreateOrder"
        let params: [String: Any] = ["productId": productId,
                                     "paymentMethod": "APPLE_PAY",
                                     "userId": userId,
                                     "appId": "16"]
        
        let token: String = KMLightMemberManager.manager.token.access_token
        if token == "" {
            complete(false, "", Result())
            return
        }
        KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
            requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                complete(true, result.result["id"] as! String, result)
            } else {
                complete(false, "", result)
            }
        }
    }
    
    //
    func restore(productId: String, userId: String, complete: @escaping (_ success: Bool, _ orderId: String?, _ result: Result?) -> Void) {
        let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-website/pay/appStoreCreateOrder"
        let params: [String: Any] = ["productId": productId,
                                     "paymentMethod": "APPLE_PAY",
                                     "userId": userId,
                                     "appId": "16"]
        
        let token: String = KMLightMemberManager.manager.token.access_token
        if token == "" {
            complete(false, "", Result())
            return
        }
        KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
            requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                complete(true, result.result["id"] as! String, result)
            } else {
                complete(false, "", result)
            }
        }
    }
    
    func parseVerification(applePayProductId: String, orderId: String, receipt: String, restore: Int = 0, complete: @escaping KMRequestServerComplete) {
        let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-website/pay/appStoreOrderSucceed"
        let params: [String: Any] = ["applePayProductId": applePayProductId,
                                     "orderId": orderId,
                                     "receipt": receipt,
                                     "restore": restore]
        KMPrint("二次验证上传数据:\(params)")
        let token: String = KMLightMemberManager.manager.token.access_token
        if token == "" {
            complete(false, Result())
            return
        }
        KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
            requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                complete(true, result)
            } else {
                complete(false, result)
            }
        }
    }
    
    func checkDeviceStatus(complete: @escaping KMRequestServerComplete) {
        var urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/checkDeviceStatus"
        
        let uuid: String = GetHardwareUUID() ?? ""
//        let params: [String: Any] = ["appId": "16",
//                                     "deviceSign": uuid]
        urlString = urlString + (NSString(format: "?appId=16&deviceSign=%@", uuid) as String)
        KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: nil) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                complete(true, result)
            } else {
                complete(false, result)
            }
        }
    }
    
    func appStoreEquityVerification(applePayProductId: String, receipt: String, complete: @escaping KMRequestServerComplete) {
        let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-website/pay/appStoreEquityVerification"
        
        let params: [String: Any] = ["applePayProductId": applePayProductId,
                                     "paymentMethod": "APPLE_PAY",
                                     "receipt": receipt
                                    ]
        KMPrint("票据信息上传数据:\(params)")
        var token: String = KMLightMemberManager.manager.token.access_token
        if token == "" {
            complete(false, Result())
            return
        }
        
        KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
            requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                complete(true, result)
            } else {
                complete(false, result)
            }
        }
    }
    
    func appStoreBuyComplete(applePayProductId: String, receipt: String, isPurchase: Bool = false, complete: @escaping KMRequestServerComplete) {
        let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-website/pay/appStoreBuyComplete"
        let userId = KMLightMemberManager.manager.info.id 
        let params: [String: Any] = ["applePayProductId": applePayProductId,
                                     "paymentMethod": "APPLE_PAY",
                                     "receipt": receipt,
                                     "appId": "16",
                                     "productId": "21",
                                     "userId": userId
                                    ]
        KMPrint("票据信息上传数据:\(params)")
        KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
        } completion: { [unowned self] (task, responseObject, error) in
            let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error)
            if result.code == 200 {
                complete(true, result)
            } else {
                complete(false, result)
            }
        }
    }
}

//MARK: - AI
extension KMRequestServerManager {
    /**
     @abstract 翻译上传
     @param file  文件路径
     @param version 版本号
     */
    func aiTranslationFileUpload(file: String, version: String, complete: @escaping KMRequestServerComplete) {
        
        let infoDictionary = Bundle .main.infoDictionary!
        let userInfo = KMLightMemberCache.cache.readData(type: .info)
        let majorVersion = infoDictionary["CFBundleShortVersionString"]
        let urlString = KMAIServerConfig().aiTranslationURL + "/v1/translate/fileUpload"
        let fileData = FileManager.default.contents(atPath: file)
        let params: [String: Any] = ["file": fileData,
                                     "projectId": "2",
                                     "version": version,
                                     "userId": userInfo["id"] as Any]
        KMRequestServer.requestServer.aiTranslation(urlString: urlString, params: params) { formData in
            let fileURL = URL(fileURLWithPath: file)
            try? formData.appendPart(withFileURL: fileURL, name: "file", fileName: fileURL.lastPathComponent, mimeType: "application/octet-stream")
        } requestSerializer: { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
        } completion: { task, responseObject, error in
            if responseObject != nil {
                let data: NSDictionary = responseObject!["data"] as? NSDictionary ?? [:]
                let code: String = responseObject!["code"] as? String ?? "06005"
                let message: String = responseObject!["msg"] as? String ?? "unknown error"
                let error = NSError(domain: message, code: Int(code)!)
                let result = Result(result: data,message: message,code: Int(code)!, error: error)
                if result.code == 200 {
                    complete(true, result)
                } else {
                    complete(false, result)
                }
            } else {
                let error = NSError(domain: "unknown error", code: 404)
                let result = Result(result: [:],message: "unknown error",code: 404, error: error)
                complete(false, result)
            }
        }
    }
    
    /**
     @abstract 文件翻译
     @param fileKey  文件Key
     @param from 初始语言
     @param to 结束语言
     @param version 应用版本
     */
    func aiTranslationFileTranslateHandle(fileKey: String, from: String, to: String, version: String, complete: @escaping KMRequestServerComplete) {
        
        let infoDictionary = Bundle .main.infoDictionary!
        let userInfo = KMLightMemberCache.cache.readData(type: .info)
        let majorVersion = infoDictionary["CFBundleShortVersionString"]
        let urlString = KMAIServerConfig().aiTranslationURL + "/v1/translate/fileTranslateHandle"
        if userInfo.count > 0 {
            var semaphore = DispatchSemaphore (value: 0)

            let parameters = String(format: "{\r\n    \"fileKey\": \"%@\",\r\n    \"from\": \"%@\",\r\n    \"to\": \"%@\",\r\n    \"version\": \"%@\",\r\n    \"projectId\": \"2\",\r\n    \"userId\": \"%@\"\r\n}", fileKey, from, to, version, userInfo["id"] as! String)
            let postData = parameters.data(using: .utf8)

            var request = URLRequest(url: URL(string: urlString)!,timeoutInterval: Double.infinity)
            request.addValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
            request.addValue("application/json", forHTTPHeaderField: "Content-Type")

            request.httpMethod = "POST"
            request.httpBody = postData

            let task = URLSession.shared.dataTask(with: request) { data, response, error in
               guard let data = data else {
                   KMPrint(String(describing: error))
                  semaphore.signal()
                  return
               }
                let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary ?? [:]
                if jsonObject != nil {
                    let data1: NSDictionary = jsonObject!["data"] as? NSDictionary ?? [:]
                    let code: String = jsonObject!["code"] as? String ?? "06005"
                    let message: String = jsonObject!["msg"] as? String ?? "unknown error"
                    let error = NSError(domain: message, code: Int(code)!)
                    let result = Result(result: data1,message: message,code: Int(code)!, error: error)
                    if result.code == 200 {
                        complete(true, result)
                    } else {
                        complete(false, result)
                    }

                } else {
                    let error = NSError(domain: "unknown error", code: 404)
                    let result = Result(result: [:],message: "unknown error",code: 404, error: error)
                    complete(false, result)
                }
               semaphore.signal()
            }
            
            task.resume()
            semaphore.wait()
        }
    }

    /**
     @abstract 内容翻译
     @param q  选中
     @param from 初始语言
     @param to 结束语言
     @param version 应用版本
     */
    func aiTranslationTextTrans(q: String, from: String, to: String, version: String, complete: @escaping KMRequestServerComplete) {
        
        let infoDictionary = Bundle .main.infoDictionary!
        let userInfo = KMLightMemberCache.cache.readData(type: .info)
        let majorVersion = infoDictionary["CFBundleShortVersionString"]
        let urlString = KMAIServerConfig().aiTranslationURL + "/v1/translate/textTrans"
        if userInfo.count > 0 {
            var semaphore = DispatchSemaphore (value: 0)
            
            var escapedString = q
            if q.contains("\n") || q.contains("\r") {
                escapedString = q.replacingOccurrences(of: "\n", with: "\\n")
                escapedString = escapedString.replacingOccurrences(of: "\r", with: "\\r")
            } else if q.contains("\u{2028}") {
                
            }
            escapedString = String(data: escapedString.data(using: .utf8)!, encoding: .utf8)!
    //        let escapedString = String(data: q.data(using: .utf8)!, encoding: .utf8)!
            let parameters = String(format: "{\r\n    \"q\": \"%@\",\r\n    \"from\": \"%@\",\r\n    \"to\": \"%@\",\r\n    \"version\": \"%@\",\r\n    \"projectId\": \"2\",\r\n    \"userId\": \"%@\"\r\n}", escapedString, from, to, version, userInfo["id"] as! String)

            let postData = parameters.data(using: .utf8)

            var request = URLRequest(url: URL(string: urlString)!,timeoutInterval: Double.infinity)
            request.addValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
            request.addValue("application/json", forHTTPHeaderField: "Content-Type")

            request.httpMethod = "POST"
            request.httpBody = postData

            let task = URLSession.shared.dataTask(with: request) { data, response, error in
               guard let data = data else {
                   KMPrint(String(describing: error))
                  semaphore.signal()
                  return
               }
                let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary ?? [:]
                if jsonObject != nil {
                    let data1: NSDictionary = jsonObject!["data"] as? NSDictionary ?? [:]
                    let code: String = jsonObject!["code"] as? String ?? "06005"
                    let message: String = jsonObject!["msg"] as? String ?? "unknown error"
                    let error = NSError(domain: message, code: Int(code)!)
                    let result = Result(result: data1,message: message,code: Int(code)!, error: error)
                    if result.code == 200 {
                        complete(true, result)
                    } else {
                        complete(false, result)
                    }
                } else {
                    let error = NSError(domain: "unknown error", code: 404)
                    let result = Result(result: [:],message: "unknown error",code: 404, error: error)
                    complete(false, result)
                }
               semaphore.signal()
            }
            
            task.resume()
            semaphore.wait()
        }
    }
    
    /**
     @abstract重写 & 纠错
     @param content  内容
     @param version 版本号
     */
    func aiRewriting(content: String, version: String, state: KMAIRewritingState, complete: @escaping KMRequestServerComplete) {
        
        let userInfo = KMLightMemberCache.cache.readData(type: .info)
        var urlString = KMAIServerConfig().aiRewritingURL + "/api/rewrite"
        if state == .AIErrorCorrection {
            urlString = KMAIServerConfig().aiRewritingURL + "/api/correct-typos"
        }
        let params: [String: Any] = ["project_id": 2,
                                     "content": content,
                                     "version": version,
                                     "user_id": userInfo["id"] as Any]
        
        KMRequestServer.requestServer.aiRewriting(urlString: urlString, params: params) { formData in
            
        } requestSerializer: { requestSerializer in
            requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
        } completion: { task, responseObject, error in
            if responseObject != nil {
                let data: NSDictionary = responseObject!["data"] as? NSDictionary ?? [:]
                let code: String = responseObject!["code"] as? String ?? "06005"
                let message: String = responseObject!["message"] as? String ?? "unknown error"
                let error = NSError(domain: message, code: Int(code)!)
                let result = Result(result: data,message: message,code: Int(code)!, error: error)
                if result.code == 200 {
                    complete(true, result)
                } else {
                    complete(false, result)
                }
            } else {
                let error = NSError(domain: "unknown error", code: 404)
                let result = Result(result: [:],message: "unknown error",code: 404, error: error)
                complete(false, result)
            }
        }
    }

}

//MARK: - 数据处理
extension KMRequestServerManager {
    func dealData(responseObject: NSDictionary?, error: NSError?) -> Result {
        var dic: NSDictionary = [:]
        if (error == nil && responseObject != nil) {
            dic = responseObject!
        } else {
            var info = responseObject
            if (error != nil) {
                let data = error!.userInfo["com.alamofire.serialization.response.error.data"]
                
                if (data != nil) {
                    info = try?JSONSerialization.jsonObject(with: data as? Data ?? Data(), options: JSONSerialization.ReadingOptions.mutableLeaves) as? NSDictionary
                }
                dic = info ?? [:]
            }
        }
        
        let result: NSDictionary = dic["result"] as? NSDictionary ?? [:]
        var code: Int = dic["code"] as? Int ?? 0
        let message: String = dic["msg"] as? String ?? "unknown error"
        let error = NSError(domain: message, code: code)
        if result.count == 0 && responseObject != nil && code == 0 {
            code = 200
        }
        
        if code == 318 {
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1, execute: {
                let alert = NSAlert()
                alert.messageText = NSLocalizedString("Unable to Log in", comment: "")
                alert.informativeText = NSLocalizedString("Your account is currently being canceled and cannot be logged in. If you have any questions, please contact us at support@pdfreaderpro.com", comment: "")
                alert.addButton(withTitle: NSLocalizedString("Contact Us", comment: ""))
                alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
                var window = NSWindow.currentWindow()
                if window != nil {
                    alert.beginSheetModal(for: window) { result in
                        if (result == .alertFirstButtonReturn) {
                            //                    KMMailHelper.newEmail(withContacts: "support@pdfreaderpro.com", andSubjects: "")
                            //                    NSWorkspace.shared.launchApplication("Mailto:support@pdfreaderpro.com")
                            //                    NSWorkspace.shared.open(URL(string: "mailto:support@pdfreaderpro.com")!)
                            NSWorkspace.shared.open(URL(string: "https://www.pdfreaderpro.com/contact")!)
                            //                    let service = NSSharingService(named: NSSharingService.Name.composeEmail)
                            //                    service?.recipients = ["support@pdfreaderpro.com"]
                            //                    service?.subject = "Test Mail"
                            //                    service?.perform(withItems: ["Test Mail body"])
                        } else if result == .alertSecondButtonReturn {
                            return
                        }
                    }
                }
            })
        }
        
        if code == 304 {
            self.checkDeviceStatus { success, result in
                
            }
        }
        
        if code == 330 {
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2, execute: { [unowned self] in
                if loginAlert == nil {
                    loginAlert = NSAlert()
                    loginAlert?.messageText = NSLocalizedString("Please Log in again", comment: "")
                    loginAlert?.informativeText = NSLocalizedString("Your account has been logged into another device. If it was not done by you, please change your password as soon as possible.", comment: "")
                    loginAlert?.addButton(withTitle: NSLocalizedString("Change Password", comment: ""))
                    loginAlert?.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
                    var window = NSWindow.currentWindow()
                    if window != nil {
                        loginAlert?.beginSheetModal(for: window) { result in
                            if (result == .alertFirstButtonReturn) {
                                if KMLoginWindowController.fetchSampleController() == nil {
                                    KMLoginWindowController.show(window: window)
                                }
                            } else if result == .alertSecondButtonReturn {
                                self.loginAlert = nil
                                return
                            }
                            self.loginAlert = nil
                        }
                    } else {
                        self.loginAlert = nil
                    }
                }
            })
        }
        
        if code == 343 {
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2, execute: { [unowned self] in
                var window = NSWindow.currentWindow()
                let _ = KMAccountExceptionWindowController.show(window: window)
                KMLightMemberManager.manager.logOut()
            })
        }
        
//        if code == 500 {
//            let alert = NSAlert()
//            alert.messageText = NSLocalizedString(message, comment: "")
//            alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
//            if NSApp.mainWindow != nil {
//                alert.beginSheetModal(for: NSApp.mainWindow!)
//            } else {
//                alert.runModal()
//            }
//        }
        
        KMPrint(dic)
        return Result(result: result,message: message,code: code, error: error)
    }
}

extension NSWindow {
    static func currentWindow() -> NSWindow {
        var window = NSApp.mainWindow
        if NSApp.mainWindow?.sheets.first != nil {
            window = NSApp.mainWindow?.sheets.first
        }
        if window == nil {
            window = NSApplication.shared.windows.first
        }
        return window ?? NSWindow()
    }
}