import UIKit

/// 推送点击路由能力，允许生命周期管理器与 UIKit 导航解耦并支持测试替身。
@MainActor
protocol PushRouting: AnyObject {
    /// 绑定当前 Scene 的主窗口。
    func attach(window: UIWindow)

    /// 处理一次通知点击；未登录时暂存到登录成功后继续。
    func handle(destination: PushDestination, requestIdentifier: String)

    /// 主界面建立后执行尚未完成的通知路由。
    func routePendingIfPossible()

    /// 清除退出登录前遗留的待处理路由。
    func resetPendingRoute()
}

/// 集中式推送路由器，负责冷启动去重、登录等待和跨 Tab 导航。
@MainActor
final class PushRouteCoordinator: PushRouting {
    /// 全局推送路由器。
    static let shared = PushRouteCoordinator()

    /// 等待登录或主界面建立后执行的一次性推送路由。
    private struct PendingRoute {
        let destination: PushDestination
        let requestIdentifier: String
    }

    private weak var window: UIWindow?
    private var pendingRoute: PendingRoute?
    private var handledRequestIdentifiers: [String] = []
    private let appStore: AppStore

    /// 创建路由器并注入应用状态。
    init(appStore: AppStore = .shared) {
        self.appStore = appStore
    }

    /// 绑定当前 Scene 的主窗口。
    func attach(window: UIWindow) {
        self.window = window
    }

    /// 处理通知点击；相同 request identifier 只执行一次。
    func handle(destination: PushDestination, requestIdentifier: String) {
        let identifier = requestIdentifier.trimmingCharacters(in: .whitespacesAndNewlines)
        if !identifier.isEmpty, handledRequestIdentifiers.contains(identifier) {
            return
        }
        markHandled(identifier)

        let route = PendingRoute(destination: destination, requestIdentifier: identifier)
        guard appStore.session.isLoggedIn, mainTabController != nil else {
            pendingRoute = route
            return
        }
        perform(route)
    }

    /// 登录完成、根页面切换后继续执行最后一次待处理路由。
    func routePendingIfPossible() {
        guard appStore.session.isLoggedIn,
              mainTabController != nil,
              let route = pendingRoute
        else { return }
        pendingRoute = nil
        perform(route)
    }

    /// 用户退出登录时丢弃之前账号尚未执行的跳转。
    func resetPendingRoute() {
        pendingRoute = nil
    }

    private var mainTabController: MainTabBarController? {
        window?.rootViewController as? MainTabBarController
    }

    private func perform(_ route: PendingRoute) {
        guard let mainTabController else {
            pendingRoute = route
            return
        }

        mainTabController.dismiss(animated: false)
        mainTabController.openPushDestination(route.destination)
    }

    private func markHandled(_ identifier: String) {
        guard !identifier.isEmpty else { return }
        handledRequestIdentifiers.append(identifier)
        if handledRequestIdentifiers.count > 50 {
            handledRequestIdentifiers.removeFirst(handledRequestIdentifiers.count - 50)
        }
    }
}
