//
//  QSLCountdownManager.swift
//  QuickSearchLocation
//
//  Created by Trae AI on 2024-06-30.
//

import Foundation

/// 倒计时类型
enum QSLCountdownType {
    case homeProduct  // 首页商品倒计时
    case trial        // 试用倒计时
}

/// 倒计时管理器代理协议
protocol QSLCountdownManagerDelegate: AnyObject {
    /// 倒计时更新
    /// - Parameters:
    ///   - manager: 倒计时管理器
    ///   - type: 倒计时类型
    ///   - remainingSeconds: 剩余秒数
    func countdownManager(_ manager: QSLCountdownManager, didUpdateCountdown type: QSLCountdownType, remainingSeconds: Int)
    
    /// 倒计时结束
    /// - Parameters:
    ///   - manager: 倒计时管理器
    ///   - type: 倒计时类型
    func countdownManager(_ manager: QSLCountdownManager, didFinishCountdown type: QSLCountdownType)
}

// 使代理方法可选实现
extension QSLCountdownManagerDelegate {
    func countdownManager(_ manager: QSLCountdownManager, didUpdateCountdown type: QSLCountdownType, remainingSeconds: Int) {}
    func countdownManager(_ manager: QSLCountdownManager, didFinishCountdown type: QSLCountdownType) {}
}

/// 倒计时管理器
class QSLCountdownManager {
    
    // MARK: - 单例
    static let shared = QSLCountdownManager()
    private init() {}
    
    // MARK: - 属性
    private var timer: Timer?
    private var isHomeProductCountdownActive = false
    private var isTrialCountdownActive = false
    
    // 倒计时剩余时间（秒）
    private var homeProductRemainingSeconds: Int = 0
    private var trialRemainingSeconds: Int = 0
    
    // 代理集合
    private var delegates = NSHashTable<AnyObject>.weakObjects()
    
    // 倒计时回调（保留原有回调机制作为备选）
    typealias CountdownCallback = (Int) -> Void
    private var homeProductCallback: CountdownCallback?
    private var trialCallback: CountdownCallback?
    
    // 倒计时结束回调（保留原有回调机制作为备选）
    typealias CountdownFinishCallback = () -> Void
    private var homeProductFinishCallback: CountdownFinishCallback?
    private var trialFinishCallback: CountdownFinishCallback?
    
    var selectGood: QSLGoodModel?{
        didSet{
            if(oldValue != nil){
                NotificationCenter.default.post(
                    name: Notification.Name("QSLHomeRefreshCouponViewNoti"),
                    object: nil,
                    userInfo: nil
                )
            }
        }
    }
    
    var trialGood: QSLGoodModel?{
        didSet{
            if(oldValue != nil){
                NotificationCenter.default.post(
                    name: Notification.Name("QSLHomeRefreshCouponViewNoti"),
                    object: nil,
                    userInfo: nil
                )
            }
        }
    }
    
    // MARK: - 代理管理
    
    /// 添加代理
    /// - Parameter delegate: 代理对象
    func addDelegate(_ delegate: QSLCountdownManagerDelegate) {
        delegates.add(delegate)
    }
    
    /// 移除代理
    /// - Parameter delegate: 代理对象
    func removeDelegate(_ delegate: QSLCountdownManagerDelegate) {
        delegates.remove(delegate)
    }
    
    /// 移除所有代理
    func removeAllDelegates() {
        delegates.removeAllObjects()
    }
    
    // MARK: - 公共方法
    
    /// 开始倒计时
    /// - Parameters:
    ///   - type: 倒计时类型
    ///   - seconds: 倒计时秒数
    ///   - callback: 倒计时回调，返回剩余秒数
    ///   - finishCallback: 倒计时结束回调
    /// - Returns: 是否成功开启倒计时
    @discardableResult
    func startCountdown(type: QSLCountdownType, seconds: Int, callback: @escaping CountdownCallback, finishCallback: CountdownFinishCallback? = nil) -> Bool {
        // 检查该类型倒计时是否已结束，如果已结束则不能再开启
        
        switch type {
        case .homeProduct:
            if isHomeProductCountdownActive {
                return false
            }
            homeProductRemainingSeconds = seconds
            homeProductCallback = callback
            homeProductFinishCallback = finishCallback
            isHomeProductCountdownActive = true
        case .trial:
            if isTrialCountdownActive {
                return false
            }
            trialRemainingSeconds = seconds
            trialCallback = callback
            trialFinishCallback = finishCallback
            isTrialCountdownActive = true
        }
        
        // 如果timer不存在，创建timer
        if timer == nil {
            timer = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: #selector(updateCountdown), userInfo: nil, repeats: true)
            RunLoop.current.add(timer!, forMode: .common)
        }
        
        // 立即执行一次回调，更新UI
        executeCallback(for: type)
        
        return true
    }
    
    /// 暂停倒计时
    /// - Parameter type: 倒计时类型
    func pauseCountdown(type: QSLCountdownType) {
        switch type {
        case .homeProduct:
            isHomeProductCountdownActive = false
        case .trial:
            isTrialCountdownActive = false
        }
        
        // 如果两种倒计时都不活跃，则销毁timer
        if !isHomeProductCountdownActive && !isTrialCountdownActive {
            invalidateTimer()
        }
    }
    
    /// 恢复倒计时
    /// - Parameter type: 倒计时类型
    /// - Returns: 是否成功恢复倒计时
    @discardableResult
    func resumeCountdown(type: QSLCountdownType) -> Bool {
        switch type {
        case .homeProduct:
            if homeProductRemainingSeconds <= 0 {
                return false
            }
            isHomeProductCountdownActive = true
        case .trial:
            if trialRemainingSeconds <= 0 {
                return false
            }
            isTrialCountdownActive = true
        }
        
        // 如果timer不存在，创建timer
        if timer == nil {
            timer = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: #selector(updateCountdown), userInfo: nil, repeats: true)
            RunLoop.current.add(timer!, forMode: .common)
        }
        
        return true
    }
    
    /// 停止倒计时
    /// - Parameter type: 倒计时类型
    func stopCountdown(type: QSLCountdownType) {
        switch type {
        case .homeProduct:
            isHomeProductCountdownActive = false
            homeProductRemainingSeconds = 0
            homeProductCallback = nil
            homeProductFinishCallback = nil
        case .trial:
            isTrialCountdownActive = false
            trialRemainingSeconds = 0
            trialCallback = nil
            trialFinishCallback = nil
        }
        
        // 如果两种倒计时都不活跃，则销毁timer
        if !isHomeProductCountdownActive && !isTrialCountdownActive {
            invalidateTimer()
        }
    }
    
    /// 获取剩余时间
    /// - Parameter type: 倒计时类型
    /// - Returns: 剩余秒数
    func getRemainingSeconds(for type: QSLCountdownType) -> Int {
        switch type {
        case .homeProduct:
            return homeProductRemainingSeconds
        case .trial:
            return trialRemainingSeconds
        }
    }
    
    /// 是否正在倒计时
    /// - Parameter type: 倒计时类型
    /// - Returns: 是否正在倒计时
    func isCountdownActive(for type: QSLCountdownType) -> Bool {
        switch type {
        case .homeProduct:
            return isHomeProductCountdownActive
        case .trial:
            return isTrialCountdownActive
        }
    }
    
    // MARK: - 私有方法
    
    /// 更新倒计时
    @objc private func updateCountdown() {
        // 更新首页商品倒计时
        if isHomeProductCountdownActive {
            if homeProductRemainingSeconds > 0 {
                homeProductRemainingSeconds -= 1
                executeCallback(for: .homeProduct)
                notifyDelegatesCountdownUpdated(type: .homeProduct, remainingSeconds: homeProductRemainingSeconds)
            }
            
            // 检查是否结束
            if homeProductRemainingSeconds <= 0 {
                isHomeProductCountdownActive = false
                homeProductFinishCallback?()
                homeProductCallback = nil
                homeProductFinishCallback = nil
                notifyDelegatesCountdownFinished(type: .homeProduct)
            }
        }
        
        // 更新试用倒计时
        if isTrialCountdownActive {
            if trialRemainingSeconds > 0 {
                trialRemainingSeconds -= 1
                executeCallback(for: .trial)
                notifyDelegatesCountdownUpdated(type: .trial, remainingSeconds: trialRemainingSeconds)
            }
            
            // 检查是否结束
            if trialRemainingSeconds <= 0 {
                isTrialCountdownActive = false
                trialFinishCallback?()
                trialCallback = nil
                trialFinishCallback = nil
                notifyDelegatesCountdownFinished(type: .trial)
            }
        }
        
        // 如果两种倒计时都不活跃，则销毁timer
        if !isHomeProductCountdownActive && !isTrialCountdownActive {
            invalidateTimer()
        }
    }
    
    /// 执行倒计时回调
    /// - Parameter type: 倒计时类型
    private func executeCallback(for type: QSLCountdownType) {
        switch type {
        case .homeProduct:
            homeProductCallback?(homeProductRemainingSeconds)
        case .trial:
            trialCallback?(trialRemainingSeconds)
        }
    }
    
    /// 通知代理倒计时更新
    /// - Parameters:
    ///   - type: 倒计时类型
    ///   - remainingSeconds: 剩余秒数
    private func notifyDelegatesCountdownUpdated(type: QSLCountdownType, remainingSeconds: Int) {
        for case let delegate as QSLCountdownManagerDelegate in delegates.allObjects {
            delegate.countdownManager(self, didUpdateCountdown: type, remainingSeconds: remainingSeconds)
        }
    }
    
    /// 通知代理倒计时结束
    /// - Parameter type: 倒计时类型
    private func notifyDelegatesCountdownFinished(type: QSLCountdownType) {
        for case let delegate as QSLCountdownManagerDelegate in delegates.allObjects {
            delegate.countdownManager(self, didFinishCountdown: type)
        }
    }
    
    /// 销毁定时器
    private func invalidateTimer() {
        timer?.invalidate()
        timer = nil
    }
}
