//
//  YHOOSManager.swift
//  galaxy
//
//  Created by EDY on 2024/1/16.
//  Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//

import UIKit
import AliyunOSSiOS
import SmartCodable
import xxtea

struct YHOSSModel: SmartCodable {
    var bucket: String = ""
    var Expiration: String = ""
    var bucketPath: String = ""
    var accessKeyId: String = ""
    var accessKeySecret: String = ""
    var endpoint: String = ""
    var securityToken: String = ""
    
    var id: String {
        return XXTEA.decryptBase64String(to: accessKeyId, stringKey: "galaxyapps")
    }
    
    var secret: String {
        return XXTEA.decryptBase64String(to: accessKeySecret, stringKey: "galaxyapps")
    }
}

class YHOSSManager: NSObject, URLSessionDelegate {
    static let share = YHOSSManager()
    var model: YHOSSModel = YHOSSModel()
    var publicModel: YHOSSModel = YHOSSModel()
    var mProvider: OSSStsTokenCredentialProvider!
    var mClient: OSSClient!
    var publicProvider: OSSStsTokenCredentialProvider!
    var publicClient: OSSClient!
    var fileName: [String] = []
    
    override init() {
    }
    
    func updateToken(completionHandler: (() -> Void)? = nil) {
        if let dateFromString = ISO8601DateFormatter().date(from: YHOSSManager.share.model.Expiration) {
            // 将日期转换为当前日期和时间
            let currentDate = Date()
            // 比较两个日期
            if dateFromString > currentDate {
                completionHandler?()
            } else {
                YHOSSManager.share.getOSSID(completionHandler: completionHandler)
            }
        } else {
            YHOSSManager.share.getOSSID(completionHandler: completionHandler)
        }
    }
    
    func getOSSID(completionHandler: (() -> Void)? = nil) {
        if YHNetworkStatusManager.shared.isNetWorkOK == false {
            return
        }
        
        let param: [String: Any] = ["path": "*"]
        let strUrl = YHBaseUrlManager.shared.curOssURL() + YHAllApiName.OSS.getID
        _ = YHNetRequest.getRequest(url: strUrl, params: param) { [weak self] json, _ in
            // 1. json字符串 转 对象
            guard let self = self else { return }
            guard let dic = json.data?.peel as? [String: Any], let resultModel = YHOSSModel.deserialize(from: dic) else {
                return
            }
            print(resultModel.toJSONString() as Any)
            self.model = resultModel
            self.mProvider = OSSStsTokenCredentialProvider(accessKeyId: self.model.id, secretKeyId: self.model.secret, securityToken: self.model.securityToken)
            self.mClient = OSSClient(endpoint: self.model.endpoint, credentialProvider: self.mProvider)
            if let block = completionHandler {
                block()
            }
        } failBlock: { _ in
            
        }
        
        _ = YHNetRequest.getRequest(url: strUrl, params: param, "5000000") { [weak self] json, _ in
            // 1. json字符串 转 对象
            guard let self = self else { return }
            guard let dic = json.data?.peel as? [String: Any], let resultModel = YHOSSModel.deserialize(from: dic) else {
                return
            }
            self.publicModel = resultModel
            self.publicProvider = OSSStsTokenCredentialProvider(accessKeyId: self.publicModel.id, secretKeyId: self.publicModel.secret, securityToken: self.publicModel.securityToken)
            self.publicClient = OSSClient(endpoint: self.publicModel.endpoint, credentialProvider: self.publicProvider)
        } failBlock: { _ in
        }
    }
    
    func putObject(image: UIImage, _ isPublic: Bool = false, callBackBlock: @escaping (_ success: String?, _ error: YHErrorModel?) -> Void) {
        let request = OSSPutObjectACLRequest()
        let size = picMaxSize
        DispatchQueue.global().async {
            guard let imageData = image.compressOriginalImage(size) else {
                DispatchQueue.main.async {
                    callBackBlock(nil, YHErrorModel())
                }
                return
            }
            
            request.uploadingData = imageData
            if isPublic {
                request.bucketName = self.publicModel.bucket
            } else {
                request.bucketName = self.model.bucket
            }
            let timestamp = Date().timeIntervalSince1970
            let randomInt = Int.random(in: 1...100) // 随机生成1到10之间的整数
            let name = "\(UInt64(timestamp))" + "\(randomInt)" + ".jpg"
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyyMMdd"
            let currentDateMMdd = dateFormatter.string(from: Date())
            // self.fileName.append(name)
            if isPublic {
                request.acl = "public-read-write"
                request.objectKey = "5000000" + "/" + currentDateMMdd + "/" + "\(name)"
            } else {
                request.objectKey = "4001001" + "/" + currentDateMMdd + "/" + "\(name)"
            }
            request.contentDisposition = "inline"
            request.uploadProgress = { (bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) in
                printLog("bytesSent:\(bytesSent),totalBytesSent:\(totalBytesSent),totalBytesExpectedToSend:\(totalBytesExpectedToSend)")
            }
            var task = OSSTask<AnyObject>()
            if isPublic {
                task = self.publicClient.putObject(request)
            } else {
                task = self.mClient.putObject(request)
            }
            
            task.continue({ (t) -> Any? in
                let result = t
                if result.error != nil {
                    callBackBlock(nil, YHErrorModel())
//                    self.fileName.removeFirst()
                } else {
                    let dateFormatter = DateFormatter()
                    dateFormatter.dateFormat = "yyyyMMdd"
                    let currentDateMMdd = dateFormatter.string(from: Date())
                    var string = ""
                    if isPublic {
                        string = "https://" + self.publicModel.bucket + "." + "oss-cn-shenzhen.aliyuncs.com/" + "5000000" + "/" + currentDateMMdd + "/" + "\(name)"
                    } else {
                        string = "https://" + self.model.bucket + "." + "oss-cn-shenzhen.aliyuncs.com/" + "4001001" + "/" + currentDateMMdd + "/" + "\(name)"
                    }
                    callBackBlock(string.getPrivateUrl(), YHErrorModel())
//                    self.fileName.removeFirst()
                }
                return
            }).waitUntilFinished()
        }
    }
    
    func putFile(file: String, _ isPublic: Bool = false, callBackBlock: @escaping (_ success: String?, _ error: YHErrorModel?) -> Void) {
        let request = OSSPutObjectACLRequest()
        guard let fileData = try? Data(contentsOf: URL(string: file) ?? URL(fileURLWithPath: "")) else {
            callBackBlock(nil, YHErrorModel())
            return
        }
        DispatchQueue.global().async {
            let fileExtension = URL(fileURLWithPath: file).pathExtension.lowercased()
            request.uploadingData = fileData
            if isPublic {
                request.bucketName = self.publicModel.bucket
            } else {
                request.bucketName = self.model.bucket
            }
            let timestamp = Date().timeIntervalSince1970
            let name = "\(UInt64(timestamp))" + ".\(fileExtension)"
            self.fileName.append(name)
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyyMMdd"
            let currentDateMMdd = dateFormatter.string(from: Date())
            if isPublic {
                request.acl = "public-read-write"
                request.objectKey = "5000000" + "/" + currentDateMMdd + "/" + "\(name)"
            } else {
                request.objectKey = "4001001" + "/" + currentDateMMdd + "/" + "\(name)"
            }
            request.contentDisposition = "inline"
            request.uploadProgress = { (bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) in
                printLog("bytesSent:\(bytesSent),totalBytesSent:\(totalBytesSent),totalBytesExpectedToSend:\(totalBytesExpectedToSend)")
            }
            var task = OSSTask<AnyObject>()
            if isPublic {
                task = self.publicClient.putObject(request)
            } else {
                task = self.mClient.putObject(request)
            }
            
            task.continue({ (t) -> Any? in
                let result = t
                if result.error != nil {
                    let error: NSError = (task.error)! as NSError
                    _ = error.description
                    callBackBlock(nil, YHErrorModel())
                    self.fileName.removeFirst()
                } else {
                    let dateFormatter = DateFormatter()
                    dateFormatter.dateFormat = "yyyyMMdd"
                    let currentDateMMdd = dateFormatter.string(from: Date())
                    var string = ""
                    if isPublic {
                        string = "https://" + self.publicModel.bucket + "." + "oss-cn-shenzhen.aliyuncs.com/" + "5000000" + "/" + currentDateMMdd + "/" + "\(self.fileName.first ?? "")"
                    } else {
                        string = "https://" + self.model.bucket + "." + "oss-cn-shenzhen.aliyuncs.com/" + "4001001" + "/" + currentDateMMdd +  "/" + "\(self.fileName.first ?? "")"
                    }
                    callBackBlock(string.getPrivateUrl(), YHErrorModel())
                    self.fileName.removeFirst()
                }
                return
            }).waitUntilFinished()
        }
    }
    
    func getPublic(url: String, callBackBlock: @escaping (_ success: String?, _ error: YHErrorModel?) -> Void) {
    
        DispatchQueue.global().async {
            
            let bucketName = self.getBucket(url)
            
            guard let resultUrl = URL(string: url) else { return }
            var objectKey = resultUrl.path
            objectKey.removeFirst()

            let task = self.mClient.presignConstrainURL(withBucketName: bucketName, withObjectKey: objectKey, withExpirationInterval: 60 * 5)
            task.continue({ (t) -> Any? in
                let result = t
                if result.error != nil {
                    let error: NSError = (task.error)! as NSError
                    _ = error.description
                    callBackBlock(nil, YHErrorModel())
                } else {
                    guard let string = result.result as? String else { return }
                    callBackBlock(string, YHErrorModel())
                }
                return
            }).waitUntilFinished()
        }
    }
    
    func getBucket(_ url: String) -> String {
        if url.contains("test-bucket-v1-pub.oss-cn-shenzhen.aliyuncs.com") {
            return "test-bucket-v1-pub"
        } else if url.contains("prod-bucket-v1.oss-cn-shenzhen.aliyuncs.com") {
            return "prod-bucket-v1"
        } else if url.contains("prod-bucket-v1-pub.oss-cn-shenzhen.aliyuncs.com") {
            return "prod-bucket-v1-pub"
        } else if url.contains("test-bucket-v1.oss-cn-shenzhen.aliyuncs.com") {
            return "test-bucket-v1"
        } else if url.contains("test-cdn.galaxy-immi.com") {
            return "test-bucket-v1"
        } else if url.contains("test-cdn-pub.galaxy-immi.com") {
            return "test-bucket-v1-pub"
        } else if url.contains("cdnfile.galaxy-immi.com") {
            return "galaxy-immi-cdn"
        } else if url.contains("upload.cdn.galaxy-immi.com") || url.contains("upload-cdn.galaxy-immi.com") {
            return "galaxy-immi-mp"
        } else if url.contains("cache.galaxy-immi.com") {
            return "galaxy-immi"
        } else if url.contains("galaxy-hkjoin-cdn.galaxy-immi.com") {
            return "galaxy-hkjoin"
        } else if url.contains("galaxy-dwp-cdn.galaxy-immi.com") {
            return "galaxy-dwp"
        } else if url.contains("galaxy-immi-mp.oss-cn-shenzhen.aliyuncs.com") {
            return "galaxy-filecvt"
        } else if url.contains("yinhe-test.oss-cn-shenzhen.aliyuncs.com") {
            return "yinhe-test"
        } else if url.contains("file.galaxy-immi.com") {
            return "galaxy-file"
        } else if url.contains("galaxy-smartwriting.oss-cn-shenzhen.aliyuncs.com") {
            return "galaxy-smartwriting"
        } else if url.contains("galaxy-dwp2.oss-cn-shenzhen.aliyuncs.com") {
            return "galaxy-dwp2"
        } else if url.contains("galaxy-diy.oss-cn-shenzhen.aliyuncs.com") {
            return "galaxy-diy"
        } else if url.contains("test-hk-bucket.oss-cn-hongkong.aliyuncs.com") {
            return "test-hk-bucket"
        } else if url.contains("prod-hk-bucket.oss-cn-hongkong.aliyuncs.com") {
            return "prod-hk-bucket"
        } else if url.contains("prod-cdn.galaxy-immi.com") {
            return "prod-bucket-v1"
        } else if url.contains("prod-cdn-pub.galaxy-immi.com") {
            return "prod-bucket-v1-pub"
        } else if url.contains("galaxy-filecenter.galaxy-immi.com") {
            return "galaxy-filecenter"
        } else {
#if DEBUG
        printLog("OSS找不到正确的Bucket" )
#endif
            return ""
        }
    }
}
