//
//  MP_IAPManager.swift
//  relax.offline.mp3.music
//
//  Created by Mr.Zhou on 2024/7/29.
//

import UIKit
import StoreKit
///内部购买项目管理器
class MP_IAPManager: NSObject {
    ///单例
    static let shared = MP_IAPManager()
    ///产品ID（根据开关获取）
    private var productIdentifiers:[String] = ["1weekvip","1yearvip","lifetimevip"]
    ///产品请求(根据ID获取产品信息)
    private var productsRequest:SKProductsRequest?
    ///可用产品组
    private var availableProducts:[SKProduct] = []
    
    override init() {
        super.init()
        SKPaymentQueue.default().add(self)
    }
    deinit {
        SKPaymentQueue.default().remove(self)
    }
    ///执行产品请求
    func requestProducts() {
        guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
            //无网络
            print("无网络状况，无法获得产品")
            return
        }
        //清空可用产品
        availableProducts = []
        //将产品ID转为Set集合
        let setStrings:Set<String> = Set(productIdentifiers)
        //初始化产品请求
        productsRequest = SKProductsRequest(productIdentifiers: setStrings)
        //实现请求代理
        productsRequest?.delegate = self
        //开始执行请求
        productsRequest?.start()
    }
    ///对指定产品进行购买
    func purchaseProduct(_ index:Int) {
        //检索用户选择的产品
        guard availableProducts.indices.contains(index) else {
            //越界了，说明广告总数出了问题，重新请求
            MP_HUD.onlytext("Try again!", delay: 1.0, completion: nil)
            requestProducts()
            return
        }
        let id = productIdentifiers[index]
        if  let product = availableProducts.first(where: {$0.productIdentifier == id}) {
            //将产品转为交易项
            let payment = SKPayment(product: product)
            //将交易项添加进购买线程中
            SKPaymentQueue.default().add(payment)
            MP_HUD.loading()
        }
    }
    ///用户重新检索交易
    func restorePurchases() {
        MP_HUD.loading()
        //更新信息
        SKPaymentQueue.default().restoreCompletedTransactions()
    }
    ///系统自动检索
    func systemRestorePurchases() {
        let receiptURL = Bundle.main.appStoreReceiptURL
        guard let receipt = try? Data(contentsOf: receiptURL!) else {
            // 收据不存在
            print("没有收据，广告默认开")
            //不能调用AppStore,默认使用广告
            MP_AdMobManager.shared.setOpenAdStatus(true)
            return
        }
        //收据，重置交易记录
        SKPaymentQueue.default().restoreCompletedTransactions()
    }
    ///启动时检索是否购买了广告
    func startLunchStatus() {
        //判断是否存在用户收据
        let receiptURL = Bundle.main.appStoreReceiptURL
        guard let receipt = try? Data(contentsOf: receiptURL!) else {
            // 收据不存在
            print("没有收据，广告默认开")
            //不能调用AppStore,默认使用广告
            MP_AdMobManager.shared.setOpenAdStatus(true)
            return
        }
        //有收据
        print("有收据，开始检索本地信息")
        reloadOpenStatus()
    }
    ///更新广告状态
    func reloadOpenStatus() {
        //更新广告开关状态
        if isProductPurchased(productId: productIdentifiers[0]) || isProductPurchased(productId: productIdentifiers[1]) || isProductPurchased(productId: productIdentifiers[2]){
            //设置广告开关为关
            MP_AdMobManager.shared.setOpenAdStatus(false)
        }else {
            MP_AdMobManager.shared.setOpenAdStatus(true)
        }
    }
    
}
//MARK: - SKProductsRequestDelegate
extension MP_IAPManager: SKProductsRequestDelegate, SKPaymentTransactionObserver {
    ///产品请求回调执行
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        //获得可用产品
        availableProducts = response.products
        //判空
        guard availableProducts.isEmpty == false else {
            //无可用产品
            print("无可用产品")
            return
        }
        //产品可用,检索产品内容
        for (index, item) in availableProducts.enumerated() {
            print("第\(index)号产品--\(item)")
        }
    }
    ///产品请求失败
    func request(_ request: SKRequest, didFailWithError error: any Error) {
        print("Failed to fetch products: \(error.localizedDescription)")
    }
    ///当交易的状况发生变化后
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        //遍历交易项
        transactions.forEach { item in
            //检索每笔交易的情况
            switch item.transactionState {
            case .purchasing://交易中
                break
            case .purchased://用户已经付款了
                complete(transaction: item)
            case .failed://交易失败了
               fail(transaction: item)
            case .restored://交易重置
                restore(transaction: item)
            case .deferred://等待外部操作
                break
            @unknown default:
                break
            }
        }
    }
    ///重置交易状况
    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        print("已重启交易")
        MP_HUD.hideNow()
        //确定用户是否购买过订单
        if queue.transactions.isEmpty {
            //用户ID没有购买过任何与当前产品有关的交易
            print("没有购买产品/交易已过期")
            productIdentifiers.forEach { item in
                cleanPurchase(productId: item)
            }
            MP_AdMobManager.shared.setOpenAdStatus(true)
        }
    }
    func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: any Error) {
        print("重启交易失败")
        MP_HUD.error("The current transaction failed, \(error.localizedDescription)", delay: 1.0, completion: nil)
        //清理所有的VIP信息
        productIdentifiers.forEach { item in
            cleanPurchase(productId: item)
        }
        MP_AdMobManager.shared.setOpenAdStatus(true)
    }
    //存入交易信息值
    private func storePurchase(productId: String) {
        if isProductPurchased(productId: productId) == false {
            var purchasedProducts = UserDefaults.standard.array(forKey: "PurchasedProducts") as? [String] ?? []
            purchasedProducts.append(productId)
            UserDefaults.standard.set(purchasedProducts, forKey: "PurchasedProducts")
        }
    }
    //检索用户是否购买该产品VIP产品
    private func isProductPurchased(productId: String) -> Bool {
        let purchasedProducts = UserDefaults.standard.array(forKey: "PurchasedProducts") as? [String] ?? []
        return purchasedProducts.contains(productId)
    }
    //清理对应的广告ID
    private func cleanPurchase(productId: String) {
        if isProductPurchased(productId: productId) {
            var purchasedProducts = UserDefaults.standard.array(forKey: "PurchasedProducts") as? [String] ?? []
            purchasedProducts.removeAll(where: {$0 == productId})
            UserDefaults.standard.set(purchasedProducts, forKey: "PurchasedProducts")
        }
    }
    ///交易完成
    private func complete(transaction: SKPaymentTransaction) {
        MP_HUD.success("Successfully purchased", delay: 1.0, completion: nil)
        print("Transaction completed successfully.")
        validateReceipt { [weak self] status in
            guard let self = self else {return}
            if status {
                // 存储购买信息
                self.storePurchase(productId: transaction.payment.productIdentifier)
                SKPaymentQueue.default().finishTransaction(transaction)
                //更新广告开关状态
                reloadOpenStatus()
            }
        }
    }
    //重启交易
    private func restore(transaction: SKPaymentTransaction) {
        print("Transaction restored.")
        validateReceipt { [weak self] status in
            guard let self = self else {return}
            if status {
                // 存储购买信息
                self.storePurchase(productId: transaction.payment.productIdentifier)
                SKPaymentQueue.default().finishTransaction(transaction)
                //更新广告开关状态
                reloadOpenStatus()
            }
        }
    }
    ///交易失败
    private func fail(transaction: SKPaymentTransaction) {
        //检索错误
        if let error = transaction.error as NSError? {
            if error.code != SKError.paymentCancelled.rawValue {
                MP_HUD.error("The current transaction failed, \(error.localizedDescription)", delay: 1.0, completion: nil)
            } else {
                MP_HUD.onlytext("The current transaction has been canceled", delay: 1.0, completion: nil)
            }
        }
    }
    //获取收据信息
    func fetchReceipt() -> String? {
        guard let receiptURL = Bundle.main.appStoreReceiptURL else { return nil }
        guard let receiptData = try? Data(contentsOf: receiptURL) else { return nil }
        return receiptData.base64EncodedString(options: [])
    }
    //验证收据信息
    func validateReceipt(completion: @escaping (Bool) -> Void) {
        guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
            completion(false)
            return
        }
        //获取收据信息
        guard let receiptString = fetchReceipt() else {
            completion(false)
            return
        }
        //生成请求参数
        let requestDictionary = ["receipt-data": receiptString,
                                 "password": "d29627e4f78b4b50a0ce5166acd8aa9f" ]
        guard JSONSerialization.isValidJSONObject(requestDictionary) else {
            completion(false)
            return
        }
        
        do {
            let requestData = try JSONSerialization.data(withJSONObject: requestDictionary)
            #if DEBUG
            let validationURLString = "https://sandbox.itunes.apple.com/verifyReceipt"
            #else
            let validationURLString = "https://buy.itunes.apple.com/verifyReceipt"
            #endif
            guard let validationURL = URL(string: validationURLString) else {
                completion(false)
                return
            }
            //创建请求
            var request = URLRequest(url: validationURL)
            request.httpMethod = "POST"
            request.cachePolicy = .reloadIgnoringCacheData
            request.httpBody = requestData
            //设置会话
            let session = URLSession.shared
            //执行任务
            let task = session.dataTask(with: request) { data, response, error in
                guard error == nil, let data = data else {
                    completion(false)
                    return
                }
                
                do {
                    if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
                        print("Receipt validation response: \(jsonResponse)")
                        if let status = jsonResponse["status"] as? Int {
                            if status == 0 {
                                completion(true)
                            } else if status == 21007 {
                                self.validateReceiptInSandbox(receiptString: receiptString, completion: completion)
                            } else {
                                print("Receipt validation failed with status: \(status)")
                                completion(false)
                            }
                        } else {
                            completion(false)
                        }
                    } else {
                        completion(false)
                    }
                } catch {
                    completion(false)
                }
            }
            task.resume()
        } catch {
            completion(false)
        }
    }
    func validateReceiptInSandbox(receiptString: String, completion: @escaping (Bool) -> Void) {
        let requestDictionary = ["receipt-data": receiptString,
                                 "password": "d29627e4f78b4b50a0ce5166acd8aa9f"]
        guard JSONSerialization.isValidJSONObject(requestDictionary) else {
            completion(false)
            return
        }
        
        do {
            let requestData = try JSONSerialization.data(withJSONObject: requestDictionary)
            let validationURLString = "https://sandbox.itunes.apple.com/verifyReceipt"
            guard let validationURL = URL(string: validationURLString) else {
                completion(false)
                return
            }
            
            var request = URLRequest(url: validationURL)
            request.httpMethod = "POST"
            request.cachePolicy = .reloadIgnoringCacheData
            request.httpBody = requestData
            
            let session = URLSession.shared
            let task = session.dataTask(with: request) { data, response, error in
                guard error == nil, let data = data else {
                    completion(false)
                    return
                }
                do {
                    if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
                        print("Sandbox receipt validation response: \(jsonResponse)")
                        
                        if let status = jsonResponse["status"] as? Int, status == 0 {
                            completion(true)
                        } else {
                            completion(false)
                        }
                    } else {
                        completion(false)
                    }
                } catch {
                    completion(false)
                }
            }
            task.resume()
        } catch {
            completion(false)
        }
    }
}
