//
//  WeChatManager.swift
//  ylgamehall
//
//  微信 SDK 持久 delegate + authorize 异步包装。
//  把 WXApiDelegate 的 onResp 回调 → async/await，state UUID 配对多发起方。
//
//  注：分享路径已改走剪贴板 + 引导框（详见 WechatShare.swift），不再依赖
//  微信 SDK 的 SendMessageToWXReq；本类只剩登录 OAuth 链路。
//

import Foundation
import UIKit

// 微信 SDK 1.8.2（与 daoqi msext 同款）通过 Bridging Header 导入，无需 import 语句

@MainActor
public final class WeChatManager: NSObject {

    public static let shared = WeChatManager()

    /// 授权 scope（沿用 msext SGDefineInfo.h:104）
    public static let authScope = "snsapi_message,snsapi_userinfo,snsapi_friend,snsapi_contact"

    /// 待 resolve 的 authorize continuation（state UUID 配对）
    private var authPending: [String: CheckedContinuation<WXAuthCodePayload, Error>] = [:]

    public override init() {
        super.init()
    }

    // MARK: - Authorize

    /// 拉起微信授权（msext NewRootVC.m → WXApiRequestHandler.m 同款路径）。
    /// 必须用新版 SDK 2.x 的 `sendAuthReq:viewController:delegate:completion:`：
    /// - viewController = SDK 拉起微信回来时的 present 上下文（缺失则 SDK 无法弹起）
    /// - delegate = SDK 弱引用，授权完成由 WXApiDelegate.onResp 回调（与 SceneDelegate
    ///   openURL 路径解耦，授权回包独立由 SDK 直接派给 delegate）
    /// 旧版 1.x 的 `WXApi.send(req)` 已 deprecated，不传 vc/delegate 会导致 H5 调了无反应。
    public func authorize() async throws -> WXAuthCodePayload {
        let state = UUID().uuidString
        return try await withCheckedThrowingContinuation { cont in
            authPending[state] = cont
            let req = SendAuthReq()
            req.scope = Self.authScope
            req.state = state

            guard let vc = Self.topmostViewController() else {
                authPending.removeValue(forKey: state)
                cont.resume(throwing: WeChatError.authFailed(-3))
                return
            }
            // 1.x 的 sendAuthReq 返回 BOOL（同步知道是否成功拉起），无 completion
            let success = WXApi.sendAuthReq(req, viewController: vc, delegate: self)
            if !success {
                if let pending = authPending.removeValue(forKey: state) {
                    pending.resume(throwing: WeChatError.authFailed(-3))
                }
            }
            // success=true 时等 WXApiDelegate.onResp 触发（SceneDelegate openURL 链路）
        }
    }

    /// 取当前最顶层 ViewController（含 presented / nav.visible），供微信 SDK 作为
    /// modal present 的上下文。msext 直接 self（gameController/NewRootVC），新外壳
    /// AccreditLoginHandler 是 stateless enum，由本方法 resolve。
    private static func topmostViewController() -> UIViewController? {
        let windowScene = UIApplication.shared.connectedScenes
            .compactMap { $0 as? UIWindowScene }
            .first(where: { $0.activationState == .foregroundActive })
            ?? UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.first
        guard let root = windowScene?.windows.first(where: \.isKeyWindow)?.rootViewController
                      ?? windowScene?.windows.first?.rootViewController else {
            return nil
        }
        var top: UIViewController = root
        while let presented = top.presentedViewController {
            top = presented
        }
        if let nav = top as? UINavigationController, let visible = nav.visibleViewController {
            return visible
        }
        return top
    }

    // MARK: - Internal: resolve callbacks

    fileprivate func resolveAuth(state: String, code: String?, errCode: Int) {
        guard let cont = authPending.removeValue(forKey: state) else { return }
        if errCode == 0, let code {
            cont.resume(returning: WXAuthCodePayload(code: code, state: state))
        } else {
            cont.resume(throwing: WeChatError.authFailed(errCode))
        }
    }
}

// MARK: - WXApiDelegate

extension WeChatManager: WXApiDelegate {

    public nonisolated func onReq(_ req: BaseReq) {
        // 我们当前只发起请求，不接受外部 req（微信 → 本 App 的 req 用于公众号回复等场景）
    }

    public nonisolated func onResp(_ resp: BaseResp) {
        // 主线程化：BaseResp 由 SDK 在主线程派发，但保留 MainActor.run 兜底
        let errCode = Int(resp.errCode)
        if let auth = resp as? SendAuthResp {
            let code = auth.code
            let state = auth.state ?? ""
            Task { @MainActor in
                Self.shared.resolveAuth(state: state, code: code, errCode: errCode)
            }
        }
        // 分享走剪贴板路径（WechatShare），不再有 SendMessageToWXResp 回包
    }
}

// MARK: - Public payload / error types

public struct WXAuthCodePayload: Sendable {
    public let code:  String
    public let state: String
}

public enum WeChatError: Error, Sendable {
    case sdkNotLinked
    case authFailed(Int)
}
