//
//  IAPViewModel.swift
//  SpeakEasyLearnEnglish
//
//  Created by edy on 2025/7/18.
//

import UIKit
import StoreKit

enum IAPError: Error {
    
    case noProductsFound
    case purchaseFailure(Error?)
    case receiptValidationFailure(Error?)
    case networkError(Error?)
    case userCancelled
    case restoreFailed(Error?)
    
    var localizedDescription: String {
        switch self {
        case .noProductsFound:
            return "No available goods for purchase were found."
        case .purchaseFailure:
            return "Purchase failed"
        case .receiptValidationFailure:
            return "Order verification failed."
        case .networkError:
            return "Network connection error"
        case .userCancelled:
            return "User cancels the purchase."
        case .restoreFailed:
            return "Failed to restore purchase."
        }
    }
}


class IAPViewModel: NSObject {
    
    enum IAPProductState:Int {
        case week = 0
        case year = 1
    }
    
    var all: [String] = [SpeakIAPWeekIdentifier,SpeakIAPYearIdentifier]
    
    static let share = IAPViewModel()
    private let userDefaults = UserDefaults.standard
    private let productCacheKey = "IAPProductCache"
    private let IAPProductMemerCache = "IAPProductMemerCache"
    private let receiptValidationTimeout: TimeInterval = 30
    private let productRequestTimeout: TimeInterval = 15
    private let alert = SpeakAlertHUD.share
    
    var currentVCName:String = ""
    
    var isSubscriptionVerify = false
    
    /** 订阅 */
    var IAPProducts:[SKProduct?]?
    
    private var state: IAPProductState = .week
    
    //购买操作的完成回调
    private var purchaseCompletion: ((Result<Bool, IAPError>) -> Void)?
    //恢复购买的完成回调
    private var restoreCompletion: ((Result<Bool, IAPError>) -> Void)?
    //获取商品信息的完成回调
    private var productRequestCompletion: (([SKProduct?]?) -> Void)?
    
    var isSubscribed = false {
        didSet {
            if isSubscribed != oldValue {
                NotificationCenter.default.post(name: .subscriptionStatusChanged, object: nil)
            }
        }
    }
    
    // 订阅状态
    var subscriptionType:Int = -1
    
    // MARK: - Initialization
    private override init() {
        super.init()
        SKPaymentQueue.default().add(self)
    }
    
    deinit {
        SKPaymentQueue.default().remove(self)
    }
}


extension IAPViewModel {
    
    // 获取订阅内购商品信息
    func fetchProducts(completion: @escaping (([SKProduct?]?) -> Void)) {
        // 先检查缓存
        if let cachedProducts = getCachedProducts() {
            // 后台更新最新数据
            var SKProducts:[SKProduct?] = []
            for productid in all {
                let sk = cachedProducts.filter { $0.productIdentifier == productid }.first
                SKProducts.append(sk)
            }
            IAPProducts = SKProducts
            completion(SKProducts)
        }
        productRequestCompletion = completion
        let request = SKProductsRequest(productIdentifiers: Set(all))
        request.delegate = self
        request.start()
        
        BackgroundTaskManager.share.startTask()
        DispatchQueue.global().asyncAfter(deadline: .now() + productRequestTimeout) { [weak self] in
            guard let weakSelf = self else { return }
            request.cancel()
            weakSelf.productRequestCompletion?(nil)
            BackgroundTaskManager.share.endTask()
        }
    }
    
            
    // 验证订阅
    func checkSubscriptionState(completion: @escaping (_ isSubscribed: Bool, _ subscriptionType: Int, _ expiresDate: Date?) -> Void) {
        verifyReceiptWithApple { result in
            switch result {
            case .success(let receipt):
                let status = self.checkSubscriptionStatus(receiptInfo: receipt)
                DispatchQueue.main.async {
                    completion(status.isActive, status.subscriptionType, status.expiresDate)
                    self.isSubscribed = status.isActive
                    self.subscriptionType = status.subscriptionType
                    if self.isSubscribed {
                        APIReportManager.shared.startReport(type: .page_show("SpeakSubscribeding"))
                    }
                    #if DEBUG
                    if let expDate = status.expiresDate {
                        let formatter = DateFormatter()
                        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
                        Print("订阅状态：\(status.isActive ? "已订阅" : "未订阅")，订阅类型：\(status.subscriptionType)，到期时间：\(formatter.string(from: expDate))")
                    }
                    #endif
                }
            case .failure(_):
                self.refreshReceipt()
                completion(false, -1, nil)
            }
        }
    }
    
    /// 订阅
    func purchase(_ state: IAPProductState, completion: @escaping (Result<Bool, IAPError>) -> Void) {
        if let skproduct = IAPProducts?[safe: state.rawValue] {
            self.state = state
            self.purchaseCompletion = completion
            
            APIReportManager.shared.startReport(type: .apple_billing_click, ext: ["productId":skproduct?.productIdentifier,"from":self.currentVCName])
            
            let payment:SKPayment = SKPayment(product: skproduct!)
            SKPaymentQueue.default().add(payment)
            alert.show()
        }else{
            completion(.failure(.noProductsFound))
        }
    }
    
    func restore(_ state: IAPProductState = .week, completion: @escaping (Result<Bool, IAPError>) -> Void) {
        self.state = state
        self.restoreCompletion = completion
        SKPaymentQueue.default().restoreCompletedTransactions()
        alert.show()
    }
    
}

// MARK: - SKPaymentTransactionObserver
extension IAPViewModel: SKPaymentTransactionObserver {
    
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        guard let transaction = transactions.first else { return }
        Print("交易状态变化：\(transaction.transactionState.rawValue)")
        Print("商品ID：\(transaction.payment.productIdentifier)")
        if let error = transaction.error {
            Print("错误信息：\(error.localizedDescription)")
        }
        handlePurchaseResult(transaction)
    }
    
    /** 恢复购买 */
    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        // 刷新订阅状态
        checkSubscriptionState { [weak self] isSubscribed,type,expiresDate in
            guard let self = self else { return }
            // 更新恢复购买的结果
            if isSubscribed {
                self.restoreCompletion?(.success(true))
            } else {
                self.restoreCompletion?(.failure(.restoreFailed(nil)))
            }
            self.alert.disMiss()
        }
    }
    
    /** 恢复失败 */
    func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
        restoreCompletion?(.failure(.restoreFailed(error)))
        alert.disMiss()
    }
    
    /** 刷新收据 */
    func refreshReceipt() {
        let request = SKReceiptRefreshRequest()
        request.delegate = self
        request.start()
    }
}

extension IAPViewModel {
    
    func checkSubscriptionStatus(receiptInfo: [String: Any]) -> (isActive: Bool, isTrial: Bool, subscriptionType: Int, expiresDate: Date?) {
         // 首先检查 in_app 购买记录
         if let receipt = receiptInfo["receipt"] as? [String: Any],
            let inAppPurchases = receipt["in_app"] as? [[String: Any]] {
             // 检查是否存在永久商品购买记录
             let hasValidLifetimePurchase = inAppPurchases.contains { purchase in
                 let productId = purchase["product_id"] as? String
                 let cancelled = purchase["cancellation_date"] != nil
                 let ownershipType = purchase["in_app_ownership_type"] as? String
                 
                 return productId == "1" && !cancelled &&
                        ownershipType == "PURCHASED"
             }
             
             if hasValidLifetimePurchase {
                 print("检测到有效的永久商品购买记录")
                 return (true, false, -10, nil)
             }
         }
         
         // 如果没有永久商品，继续检查订阅
         guard let latestReceiptInfo = receiptInfo["latest_receipt_info"] as? [[String: Any]] else {
             print("没有找到任何购买记录")
             return (false, false, -1, nil)
         }
         
         // 按过期时间排序，确保获取最新的订阅记录
         let sortedReceipts = latestReceiptInfo.sorted { receipt1, receipt2 in
             let date1 = getExpiryDate(from: receipt1) ?? Date.distantPast
             let date2 = getExpiryDate(from: receipt2) ?? Date.distantPast
             return date1 > date2
         }
         
         guard let lastReceipt = sortedReceipts.first else {
             return (false, false, -1, nil)
         }
         
         // 解析试用期状态
         let isTrial = (lastReceipt["is_trial_period"] as? String) == "true"
         
         // 获取过期时间和退款状态
         let expiresDate = getExpiryDate(from: lastReceipt)
         let isCancelled = lastReceipt["cancellation_date"] != nil
         let isActive = !isCancelled && (expiresDate?.compare(Date()) == .orderedDescending)
         
         // 确定订阅类型
         let productId = lastReceipt["product_id"] as? String

         var subscriptionType: Int = -1
         for (idx,product) in all.enumerated() {
             if product == productId {
                 subscriptionType = idx
                 break
             }
         }
         return (isActive, isTrial, subscriptionType, expiresDate)
     }

    // 辅助方法：解析过期时间
    private func getExpiryDate(from receipt: [String: Any]) -> Date? {
        if let expiresDateMs = receipt["expires_date_ms"] as? String,
           let timeInterval = TimeInterval(expiresDateMs) {
            return Date(timeIntervalSince1970: timeInterval / 1000.0)
        } else if let expiresDateString = receipt["expires_date"] as? String {
            let formatter = ISO8601DateFormatter()
            return formatter.date(from: expiresDateString)
        }
        return nil
    }
    
}


// MARK: - Private Methods
private extension IAPViewModel {
        
    func getCachedProducts() -> [SKProduct]? {
        guard let cache = userDefaults.object(forKey: productCacheKey) as? [[String: Any]] else {
            return nil
        }
        return cache.compactMap { item -> SKProduct? in
            let product = SKProduct()
            product.setValue(item["productIdentifier"] as? String, forKey: "productIdentifier")
            product.setValue(item["localizedTitle"] as? String, forKey: "localizedTitle")
            product.setValue(item["localizedDescription"] as? String, forKey: "localizedDescription")
            product.setValue(NSDecimalNumber(value: item["price"] as? Double ?? 0), forKey: "price")
            product.setValue(Locale(identifier: item["priceLocale"] as? String ?? ""), forKey: "priceLocale")
            return product
        }
    }
    
    func cacheProducts(_ products: [SKProduct]) {
        let cache = products.map { product -> [String: Any] in
            return [
                "productIdentifier": product.productIdentifier,
                "localizedTitle": product.localizedTitle,
                "localizedDescription": product.localizedDescription,
                "price": product.price.doubleValue,
                "priceLocale": product.priceLocale.identifier,
            ]
        }
        userDefaults.set(cache, forKey: productCacheKey)
    }
    
    func handlePurchaseResult(_ transaction: SKPaymentTransaction) {
        switch transaction.transactionState {
        case .purchased:
            verifyPurchase(transaction)
        case .failed:
            handleFailedTransaction(transaction)
        case .purchasing:
            Print("购买处理中...")
        case .restored:
            restore { _ in
                
            }
        default:
            break
        }
    }
    
    func verifyPurchase(_ transaction: SKPaymentTransaction) {
        verifyReceiptWithApple { [weak self] result in
            guard let self = self else { return }
            switch result {
            case .success(let receipt):
                let status = self.checkSubscriptionStatus(receiptInfo: receipt)
                self.isSubscribed = status.isActive
                if status.isActive {
                    
                     if transaction.transactionState == .purchased {
                         AdRevenueTracker().purchasingSuccessReport(type: self.state.rawValue)
                         self.purchaseCompletion?(.success(true))
                     } else {
                         self.restoreCompletion?(.success(true))
                     }
                 } else {
                     // 订阅状态验证失败
                     if transaction.transactionState == .purchased {
                         self.purchaseCompletion?(.failure(.receiptValidationFailure(nil)))
                     } else {
                         self.restoreCompletion?(.failure(.receiptValidationFailure(nil)))
                     }
                 }

            case .failure(let error):
                if transaction.transactionState == .purchased {
                    self.purchaseCompletion?(.failure(.receiptValidationFailure(error)))
                } else {
                    self.restoreCompletion?(.failure(.receiptValidationFailure(error)))
                }
            }
            
            self.alert.disMiss()
            SKPaymentQueue.default().finishTransaction(transaction)
        }
    }
    
    func handleFailedTransaction(_ transaction: SKPaymentTransaction) {
        alert.disMiss()
        
        if let error = transaction.error as? SKError {
            switch error.code {
            case .paymentCancelled:
                purchaseCompletion?(.failure(.userCancelled))
            default:
                purchaseCompletion?(.failure(.purchaseFailure(error)))
            }
        } else {
            purchaseCompletion?(.failure(.purchaseFailure(transaction.error)))
        }
        SKPaymentQueue.default().finishTransaction(transaction)
    }
    
    func verifyReceiptWithApple(completion: @escaping (Result<[String: Any], Error>) -> Void) {
        guard let receiptURL = Bundle.main.appStoreReceiptURL,
              let receiptData = try? Data(contentsOf: receiptURL) else {
            completion(.failure(IAPError.receiptValidationFailure(nil)))
            return
        }
        
        let requestData: [String: Any] = [
            "receipt-data": receiptData.base64EncodedString(),
            "password": "e2ce70505a40450f8a3d96cc4ad197c6",
            "exclude-old-transactions": true
        ]
        
        let productionURL = URL(string: "https://buy.itunes.apple.com/verifyReceipt")!
        var request = URLRequest(url: productionURL)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = try? JSONSerialization.data(withJSONObject: requestData)
        request.timeoutInterval = receiptValidationTimeout
        
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            if let error = error {
                completion(.failure(error))
                return
            }
            
            guard let data = data,
                  let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
                completion(.failure(IAPError.receiptValidationFailure(nil)))
                return
            }
            
            if let status = json["status"] as? Int, status == 21007 {
                // 沙盒环境验证
                self.verifySandboxReceipt(receiptData: receiptData, completion: completion)
            } else {
                completion(.success(json))
            }
        }
        task.resume()
    }
    
    func verifySandboxReceipt(receiptData: Data, completion: @escaping (Result<[String: Any], Error>) -> Void) {
        let requestData: [String: Any] = [
            "receipt-data": receiptData.base64EncodedString(),
            "password": "e2ce70505a40450f8a3d96cc4ad197c6",
            "exclude-old-transactions": true
        ]
        
        let sandboxURL = URL(string: "https://sandbox.itunes.apple.com/verifyReceipt")!
        var request = URLRequest(url: sandboxURL)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = try? JSONSerialization.data(withJSONObject: requestData)
        request.timeoutInterval = receiptValidationTimeout
        
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            if let error = error {
                completion(.failure(error))
                return
            }
            
            guard let data = data,
                  let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
                completion(.failure(IAPError.receiptValidationFailure(nil)))
                return
            }
            
            completion(.success(json))
        }
        task.resume()
    }

}

// MARK: - SKProductsRequestDelegate
extension IAPViewModel: SKProductsRequestDelegate {
    
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        let products = response.products
        guard !products.isEmpty else {
            productRequestCompletion?(nil)
            BackgroundTaskManager.share.endTask()
            return
        }
        
        // 拿到请求下来的商品信息
        var SKProducts:[SKProduct] = []
        for id in all {
            if let sk = products.filter({ $0.productIdentifier == id }).first {
                SKProducts.append(sk)
            }
        }
        // 缓存
        if SKProducts.count > 0 {
            IAPProducts = SKProducts
            cacheProducts(SKProducts)
        }

        DispatchQueue.main.async { [weak self] in
            self?.productRequestCompletion?(SKProducts)
            BackgroundTaskManager.share.endTask()
        }
    }
    
    func request(_ request: SKRequest, didFailWithError error: Error) {
        productRequestCompletion?(nil)
        BackgroundTaskManager.share.endTask()
    }
}


class BackgroundTaskManager {
    
    static let share = BackgroundTaskManager()
    
    private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
    
    func startTask() {
        backgroundTaskID = UIApplication.shared.beginBackgroundTask { [weak self] in
            self?.endTask() // 超时强制终止
        }
    }
    
    func endTask() {
        guard backgroundTaskID != .invalid else { return }
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
    }
}
