//
//  AppCoordinator.swift
//  ylgamehall
//
//  应用导航协调器：管理 Lobby ↔ SubGame ↔ Overlay 三层栈。
//
//  契约约束（Design §2.4.3 栈深 ≤ 3）：
//    - 大厅 + 子游戏 + 弹层（threeView）最多 3 层
//    - 防止 H5 误调 SwitchOverGameData 死循环 push（msext 同款 first_Time 节流）
//
//  与 msext 一对一行为：
//    - SwitchOverGameData 节流：2s 内不重复触发
//    - OpenurlTitleData 节流：3s 内不重复触发（msext first_Time 等价）
//    - subGameDidReturn 通知：子游戏 / 弹层 pop 时发，父层（大厅 / 子游戏）监听并 callback getWebdata
//

import UIKit

/// 子游戏 push 请求（从 H5 SwitchOverGameData 入参解析）
public struct SubGameRequest: Sendable {
    public let gameDir:     String   // Gamedirectory，子游戏在 Caches 下的目录名
    public let gameStart:   String   // 子游戏入口（通常等于 gameDir，msext 行为）
    public let downloadURL: String   // gamedownloadurl 子游戏 zip 下载地址
    public let webData:     String   // 子游戏初始数据（H5 透传）

    public init(gameDir: String, gameStart: String, downloadURL: String, webData: String) {
        self.gameDir = gameDir
        self.gameStart = gameStart
        self.downloadURL = downloadURL
        self.webData = webData
    }
}

/// 弹层 push 请求（从 H5 OpenurlTitleData 入参解析）
public struct OverlayRequest: Sendable {
    public let url:         String   // 待加载 HTTP URL
    public let title:       String   // 弹层标题（msext 历史：nav 默认隐藏，title 仅信息性）
    public let webData:     String   // data：业务数据透传给 threeView 内 H5
    public let orientation: Int      // 0=竖屏 / 1=横屏（landscape-only app 忽略，预留契约字段）

    public init(url: String, title: String, webData: String, orientation: Int) {
        self.url = url
        self.title = title
        self.webData = webData
        self.orientation = orientation
    }
}

/// 子容器（子游戏 / 弹层）pop 回父层通知。
/// msext 同款 "backgameDatatwo"：threeView 和 gameController 共用一个名字，
/// 父层（大厅 / 子游戏）监听后转 `getWebdata` 反向 callback。
public extension Notification.Name {
    /// 子游戏 / 弹层 pop 返回时发出，userInfo["data"] = 调 backgameData 时传入的字符串
    static let subGameDidReturn = Notification.Name("ylgamehall.subGameDidReturn")
}

@MainActor
public final class AppCoordinator {

    public static let shared = AppCoordinator()

    /// SwitchOverGameData 节流：2 秒内连续触发视为重复（msext first_Time 等价）
    private var lastSwitchAt: Date?
    /// OpenurlTitleData 节流：3 秒内连续触发视为重复（契约 §3.1 ［15］ first_Time 等价）
    private var lastOverlayAt: Date?

    /// 当前可见 WebContainer（大厅）— 用于 push 子游戏
    public weak var navigationController: UINavigationController?

    public init() {}

    /// 大厅触发 SwitchOverGameData。节流命中或栈深 ≥ 2 时不触发。
    /// 返回 true 表示 push 成功（或调度中），false 表示被忽略。
    @discardableResult
    public func showSubGame(_ request: SubGameRequest) -> Bool {
        // 节流：2s 内重复调用直接吞
        if let last = lastSwitchAt, Date().timeIntervalSince(last) < 2 {
            return false
        }
        // 栈深约束：当前最多大厅 + 子游戏 = 2 层
        guard let nav = navigationController,
              nav.viewControllers.count < 2
        else {
            return false
        }
        lastSwitchAt = Date()

        // push 子游戏前停大厅背景音（msext NewRootVC.m:549-552 等价）。
        // AudioPlayer 是 app 内单一背景音通道，stop 后子游戏可自由 loopBackground 覆盖。
        AudioPlayer.shared.stopAllBackground()

        let subGame = SubGameViewController(request: request)
        diagLog("[coordinator] push 子游戏（栈深 \(nav.viewControllers.count) → \(nav.viewControllers.count + 1)）")
        nav.pushViewController(subGame, animated: true)
        return true
    }

    /// 子游戏 pop 回大厅。data 是 H5 调 backgameData 时传入的字符串，
    /// 通过通知派发给大厅 WebContainer，由大厅触发 `getWebdata` 反向 callback。
    public func popSubGame(returningData data: String) {
        diagLog("[coordinator] pop 子游戏回大厅")
        navigationController?.popViewController(animated: true)
        NotificationCenter.default.post(
            name: .subGameDidReturn,
            object: nil,
            userInfo: ["data": data]
        )
    }

    /// 大厅 / 子游戏触发 OpenurlTitleData。节流命中或栈深已满（3 层）时不触发。
    /// 返回 true 表示 push 成功，false 表示被忽略。
    @discardableResult
    public func showOverlay(_ request: OverlayRequest) -> Bool {
        // 节流：3s 内重复调用直接吞（msext first_Time 等价）
        if let last = lastOverlayAt, Date().timeIntervalSince(last) < 3 {
            return false
        }
        // 栈深约束：最多 Lobby + SubGame + Overlay = 3 层
        guard let nav = navigationController,
              nav.viewControllers.count < 3
        else {
            return false
        }
        lastOverlayAt = Date()

        let overlay = OverlayViewController(request: request)
        nav.pushViewController(overlay, animated: true)
        return true
    }

    /// 弹层 pop 回父层（大厅 / 子游戏）。
    /// - data == nil：`settings.finishweb()` 路径，仅 pop，不发 backgameDatatwo
    /// - data != nil：`settings.backgameData(data)` 路径，pop + 发 .subGameDidReturn 通知
    public func popOverlay(returningData data: String?) {
        navigationController?.popViewController(animated: true)
        if let data {
            NotificationCenter.default.post(
                name: .subGameDidReturn,
                object: nil,
                userInfo: ["data": data]
            )
        }
    }
}
