//
//  IAPManager.swift
//  PhoneManager
//
//  Created by edy on 2025/4/30.
//

import Foundation
import UIKit
import StoreKit
import SVProgressHUD

// MARK: - Error Types
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."
        }
    }
}

// 添加一个枚举来表示订阅类型
enum SubscriptionType {
    case none
    case week
    case year
    case lifetime
}

enum PayState {
    case weekSubscribe
    case yearSubscribe
    case nonConsumable
    
    var productId:String{
        switch self {
        case .weekSubscribe:
            return "com.app.phonemanager.week.member.se"
        case .yearSubscribe:
            return "com.app.phonemanager.year.member"
        case .nonConsumable:
            return "com.app.phonemanager.lifetime.member"
        }
    }
}

// MARK: - IAPManager
class IAPManager: NSObject {
    
    static let share = IAPManager()
    private let userDefaults = UserDefaults.standard
    private let productCacheKey = "IAPProductCache"
    private let receiptValidationTimeout: TimeInterval = 30
    private let productRequestTimeout: TimeInterval = 15
    private let alert = PMLoadingHUD.share
    
    var currentVCName:String = ""
    
    
    // MARK: - Properties
    private struct ProductID {
        static let weekMember = "com.app.phonemanager.week.member.se"
        static let lifetimeMember = "com.app.phonemanager.lifetime.member"
        static let yearMember = "com.app.phonemanager.year.member"
        
        static var all: [String] {
            return [weekMember, lifetimeMember,yearMember]
        }
    }
    
    // 周订阅
    private var weekProduct: SKProduct?
    // 永久订阅
    private var lifetimeProduct: SKProduct?
    // 年费订阅
    private var yearProduct: SKProduct?

    private var state: PayState = .weekSubscribe
    //购买操作的完成回调
    private var purchaseCompletion: ((Result<Bool, IAPError>) -> Void)?
    //恢复购买的完成回调
    private var restoreCompletion: ((Result<Bool, IAPError>) -> Void)?
    //获取商品信息的完成回调
    private var productRequestCompletion: (((SKProduct?,SKProduct?,SKProduct?)?) -> Void)?
    
    var isSubscribed = false {
        didSet {
            if isSubscribed != oldValue {
                NotificationCenter.default.post(name: .subscriptionStatusChanged, object: nil)
            }
        }
    }
    
    // 是否展示优惠订阅
    var showYearPage:Bool = false
    // 是否热启动
    var isHotLaunch:Bool = false
    // 订阅状态
    var subscriptionType:SubscriptionType = .none
    
    func config(){}
    

    // MARK: - Initialization
    private override init() {
        super.init()
        SKPaymentQueue.default().add(self)
        
    }
    
    deinit {
        SKPaymentQueue.default().remove(self)
    }
    
    func getSKProductBy(_ type:SubscriptionType) ->SKProduct?{
        switch type {
        case .none:
            return nil
        case .week:
            return weekProduct
        case .year:
            return yearProduct
        case .lifetime:
            return lifetimeProduct
        }
    }
}

// MARK: - Public Methods
extension IAPManager {
    
    // 获取订阅内购商品信息
    func fetchProducts(completion: @escaping ((SKProduct?,SKProduct?,SKProduct?)?) -> Void) {
        // 先检查缓存
        if let cachedProducts = getCachedProducts() {
            // 后台更新最新数据
            self.weekProduct = cachedProducts.filter{$0.productIdentifier == ProductID.weekMember}.first
            self.lifetimeProduct = cachedProducts.filter{$0.productIdentifier == ProductID.lifetimeMember}.first
            self.yearProduct = cachedProducts.filter{$0.productIdentifier == ProductID.yearMember}.first
            
            completion((self.weekProduct,self.lifetimeProduct,self.yearProduct))
            refreshProducts()
        }
        
        productRequestCompletion = completion
        let request = SKProductsRequest(productIdentifiers: Set(ProductID.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: SubscriptionType, _ expiresDate: Date?) -> Void) {
        verifyReceiptWithApple { result in
            switch result {
            case .success(let receipt):
               // print("收据信息：\(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 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, .none, nil)
            }
        }
    }
    
    func purchase(_ state: PayState = .weekSubscribe, completion: @escaping (Result<Bool, IAPError>) -> Void) {
       
       
        if state == .weekSubscribe,weekProduct == nil{
            completion(.failure(.noProductsFound))
            return
        }
        
        if state == .yearSubscribe,yearProduct == nil{
            completion(.failure(.noProductsFound))
            return
        }
        
        if state == .nonConsumable,lifetimeProduct == nil{
            completion(.failure(.noProductsFound))
            return
        }
        guard SKPaymentQueue.canMakePayments() else{
            return
        }
        
        self.state = state
        self.purchaseCompletion = completion
        
        
        var payment:SKPayment = SKPayment()
        
        switch state{
        case .weekSubscribe:
            payment = SKPayment(product: weekProduct!)
        case .yearSubscribe:
            payment = SKPayment(product: yearProduct!)
        case .nonConsumable:
            payment = SKPayment(product: lifetimeProduct!)
        }
        
        APIReportManager.shared.startReport(type: .apple_billing_click, ext: ["productId":payment.productIdentifier,"from":currentVCName])
        
        SKPaymentQueue.default().add(payment)
        alert.show("Processing the purchase request...", "")
    }
    
    func restore(_ state: PayState = .weekSubscribe, completion: @escaping (Result<Bool, IAPError>) -> Void) {
        self.state = state
        self.restoreCompletion = completion
        SKPaymentQueue.default().restoreCompletedTransactions()
        alert.show("Restoring purchase...", "")
    }
}

// MARK: - Private Methods
private extension IAPManager {
    
    func refreshProducts() {
        let request = SKProductsRequest(productIdentifiers: Set())
        request.delegate = self
        request.start()
    }
    
    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: status.subscriptionType)
                         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": "3cbeb6f5ace84f5b98571263da74c192",
            "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": "3cbeb6f5ace84f5b98571263da74c192",
            "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 IAPManager: SKProductsRequestDelegate {
    
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        let products = response.products
        guard !products.isEmpty else {
            productRequestCompletion?(nil)
            BackgroundTaskManager.share.endTask()
            return
        }
        // 拿到请求下来的商品信息
        self.weekProduct = products.filter{$0.productIdentifier == ProductID.weekMember}.first
        self.lifetimeProduct = products.filter{$0.productIdentifier == ProductID.lifetimeMember}.first
        self.yearProduct = products.filter{$0.productIdentifier == ProductID.yearMember}.first
        // 缓存
        if let week = self.weekProduct,let life = self.lifetimeProduct,let year = self.yearProduct{
            cacheProducts([week,life,year])
        }

        DispatchQueue.main.async { [weak self] in
            guard let weakSelf = self else { return }
            self?.productRequestCompletion?((weakSelf.weekProduct,weakSelf.lifetimeProduct,weakSelf.yearProduct))
            BackgroundTaskManager.share.endTask()
        }
    }
    
    func request(_ request: SKRequest, didFailWithError error: Error) {
        productRequestCompletion?(nil)
        BackgroundTaskManager.share.endTask()
    }
}

// MARK: - SKPaymentTransactionObserver
extension IAPManager: 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 IAPManager{
    
    func checkSubscriptionStatus(receiptInfo: [String: Any]) -> (isActive: Bool, isTrial: Bool, subscriptionType: SubscriptionType, 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 == ProductID.lifetimeMember && 
                        !cancelled && 
                        ownershipType == "PURCHASED"
             }
             
             if hasValidLifetimePurchase {
                 print("检测到有效的永久商品购买记录")
                 return (true, false, .lifetime, nil)
             }
         }
         
         // 如果没有永久商品，继续检查订阅
         guard let latestReceiptInfo = receiptInfo["latest_receipt_info"] as? [[String: Any]] else {
             print("没有找到任何购买记录")
             return (false, false, .none, 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, .none, 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
         let subscriptionType: SubscriptionType
         switch productId {
         case ProductID.weekMember:
             subscriptionType = .week
         case ProductID.yearMember:
             subscriptionType = .year
         case ProductID.lifetimeMember:
             subscriptionType = .lifetime
         default:
             subscriptionType = .none
         }
         
         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: - Notification Names
extension Notification.Name {
    static let subscriptionStatusChanged = Notification.Name("IAPSubscriptionStatusChanged")
}




