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

import UIKit
import AliyunOSSiOS

class YHOSSModel: YHBaseModel {
    var bucket: String = ""
    var Expiration: String = ""
    var bucketPath: String = ""
    var accessKeyId: String = ""
    var accessKeySecret: String = ""
    var endpoint: String = ""
    var securityToken: String = ""
}

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
        let _ = YHNetRequest.getRequest(url: strUrl, params: param) { [weak self] json, code in
            //1. json字符串 转 对象
            guard let self = self else { return }
            let dic = json.data
            guard let resultModel = YHOSSModel.deserialize(from: dic as? Dictionary) else {
                return
            }
            self.model = resultModel
            self.mProvider = OSSStsTokenCredentialProvider(accessKeyId: self.model.accessKeyId, secretKeyId: self.model.accessKeySecret, securityToken: self.model.securityToken)
            self.mClient = OSSClient(endpoint: self.model.endpoint, credentialProvider: self.mProvider)
            if let block = completionHandler {
                block()
            }
        } failBlock: { err in
        }
        
        let _ = YHNetRequest.getRequest(url: strUrl, params: param, "5000000") { [weak self] json, code in
            //1. json字符串 转 对象
            guard let self = self else { return }
            let dic = json.data
            guard let resultModel = YHOSSModel.deserialize(from: dic as? Dictionary) else {
                return
            }
            self.publicModel = resultModel
            self.publicProvider = OSSStsTokenCredentialProvider(accessKeyId: self.publicModel.accessKeyId, secretKeyId: self.publicModel.accessKeySecret, securityToken: self.publicModel.securityToken)
            self.publicClient = OSSClient(endpoint: self.publicModel.endpoint, credentialProvider: self.publicProvider)
        } failBlock: { err in
        }
    }
    
    func putObject(image: UIImage, _ isPublic: Bool = false, callBackBlock:@escaping (_ success: String?, _ error:YHErrorModel?)->()) {
        let request = OSSPutObjectACLRequest()
        let size = Int(2 * 1024 * 1024)
        guard let imageData = image.compressOriginalImage(size) else {
            callBackBlock(nil, YHErrorModel())
            return
        }

        DispatchQueue.global().async {
            
            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) -> Void 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 + "/" + "\(self.fileName.first ?? "")"
                    } else {
                        string = "https://" + self.model.bucket + "." + "oss-cn-shenzhen.aliyuncs.com/" + "4001001" + "/" + currentDateMMdd + "/" + "\(self.fileName.first ?? "")"
                    }
                    callBackBlock(string, YHErrorModel())
                    self.fileName.removeFirst()
                }
                return
            }).waitUntilFinished()
        }
    }
    
    func putFile(file: String, _ isPublic: Bool = false, callBackBlock:@escaping (_ success: String?, _ error:YHErrorModel?)->()) {
        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) -> Void 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, YHErrorModel())
                    self.fileName.removeFirst()
                }
                return
            }).waitUntilFinished()
        }
    }
    
    func getPublic(url: String, callBackBlock:@escaping (_ success: String?, _ error:YHErrorModel?)->()) {
    
        DispatchQueue.global().async {
            
            let bucketName = self.getBucket(url)
            let pathComponents = url.pathComponents
            var objectKey = ""
            for i in 0..<pathComponents.count {
                if i == 0 || i == 1 {
                    
                } else if i == pathComponents.count - 1 {
                    objectKey = objectKey + pathComponents[i]
                } else {
                    objectKey = objectKey + pathComponents[i] + "/"
                }
            }
            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 {
                    let string = result.result as! String
                    callBackBlock(string, YHErrorModel())
                }
                return
            })
        }
    }
    
    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 DEBUG
        printLog("OSS找不到正确的Bucket" )
#endif
            return ""
        }
    }
}
