//
//  LocalVersionReader.swift
//  ylgamehall
//
//  读本地两个版本号：
//  - 原生 IPA 版本（来自 ChannelConfig.plist 的 appversion 字段）
//  - H5 包版本（来自 Library/Caches/{gamedir}/{gamestart}/version.xml 的 /game/version@value）
//
//  详见 docs/Development-Plan.md ADR-008-F / msext NewRootVC.m:664-682。
//

import Foundation

public enum LocalVersionReader {

    /// 原生 IPA 版本。等价 msext `[FuncPublic filename:@"appversion"] integerValue`
    /// 来源：ChannelConfig.plist 的 `appversion` 字段（沿用渠道注入约定，
    /// IPA 后处理改 plist 可动态调整）。
    /// 解析失败返回 0（msext `[nil intValue] = 0` 兜底语义）。
    nonisolated public static var localAppVersion: Int {
        Int(BundleConfig.shared.appVersion) ?? 0
    }

    /// 大厅 H5 包版本。等价 msext `NewRootVC.m:664-682` 的 GDataXML 路径，
    /// 新外壳用 Foundation `XMLParser`（无外部依赖）解析。
    ///
    /// 文件路径：`SandboxPaths.lobbyVersionXML` =
    ///   `Library/Caches/{gamedir}/{gamestart}/version.xml`
    /// 解析 `/game/version` 节点的 `value` 属性，转 Int。
    ///
    /// **缺失 / 损坏返回 0**（必须保留，首装后首次升级的兜底机制：
    /// `[nil intValue] = 0`，任何远端 gameVersion > 0 触发下载）。
    nonisolated public static var localGameVersion: Int {
        readGameVersion(from: SandboxPaths.lobbyVersionXML) ?? 0
    }

    /// 子游戏 H5 包版本。等价 msext `gameController.m:1249-1254`。
    nonisolated public static func subGameVersion(dir: String, start: String) -> Int {
        let url = SandboxPaths.caches
            .appendingPathComponent(dir)
            .appendingPathComponent(start)
            .appendingPathComponent("version.xml")
        return readGameVersion(from: url) ?? 0
    }

    // MARK: - 内部 XML 解析

    nonisolated private static func readGameVersion(from url: URL) -> Int? {
        guard let data = try? Data(contentsOf: url) else { return nil }
        let parser = XMLParser(data: data)
        let handler = VersionXMLHandler()
        parser.delegate = handler
        guard parser.parse(), let v = handler.gameVersion else { return nil }
        return v
    }
}

// MARK: - XMLParser delegate

/// 仅提取 `<version value="N"/>`（在 `/game/version` 路径下）的 value 转 Int。
/// msext 的 xpath 是 `/game/version` 取属性 `value`；新外壳用 SAX 风格 XMLParser
/// 也只需要在 `version` 元素出现时取属性即可（嵌套层级宽容化处理）。
nonisolated private final class VersionXMLHandler: NSObject, XMLParserDelegate {
    var gameVersion: Int?

    func parser(_ parser: XMLParser,
                didStartElement elementName: String,
                namespaceURI: String?,
                qualifiedName qName: String?,
                attributes attributeDict: [String: String] = [:]) {
        if elementName == "version", let raw = attributeDict["value"], let v = Int(raw) {
            gameVersion = v
        }
    }
}
