//
//  FriendsShareHandler.swift
//  ylgamehall
//
//  H5 → Native handler：friendsSharetypeUrlToptitleDescript — 分享
//  契约：docs/H5-Native-Contract.md §3.1 ［2］ + §3.2 ［11］sharesuccess
//
//  **页面 mode 区分**（与原 msext 两个 ViewController 各注册一份且行为不同对齐）：
//  - `.lobby`   对应 NewRootVC.m：直发微信，3 type 分支（链接 / 截图 / 远端图）
//  - `.subGame` 对应 gameController.m 活路径：SharePanel 三选一 + 朋友圈兜底
//
//  公共流程（无论 mode）：
//    1. responseCallback("sharefriend")
//    2. 立即 bridge.call("sharesuccess", { success:"2", type:<sharefriend 原值> })
//       （**有意为之**：调用分享接口即视为成功；URL Scheme / 剪贴板路径本就无返回）
//    3. 按 mode 异步 fire-and-forget 拉起 UI
//
//  各平台 SDK 依赖：
//    - 微信：通过 WeChatManager（已接入 1.8.2 SDK）
//    - QQ + 抖音：不依赖 SDK，走 URL Scheme + 剪贴板（CLAUDE.md ADR-006）
//

import Foundation
import os.log

@MainActor
public enum FriendsShareHandler {

    private static let log = Logger(subsystem: "ylgamehall", category: "FriendsShare")

    /// 注册时机的页面 mode。
    public enum Mode: Sendable {
        /// 大厅页：H5 在 WebContainer 调 friendsShare 时直发微信
        case lobby
        /// 子游戏页：H5 在 SubGame 调 friendsShare 时弹 SharePanel 或朋友圈兜底
        case subGame
    }

    public static func register(on bridge: any BridgeProtocol, mode: Mode) {
        // 【2】friendsSharetypeUrlToptitleDescript
        //   入参：sharefriend / sharetype / type / webpageUrl / title / description
        //   cb: "sharefriend"（msext 字面，沿用）
        //   反向 callback：sharesuccess({ success: "2", type: sharefriend 原值 })
        bridge.register("friendsSharetypeUrlToptitleDescript") { [weak bridge] data, callback in
            // 1. responseCallback —— msext 字面 "sharefriend"
            callback?(.string("sharefriend"))

            await MainActor.run {
                // 0. 调试日志：H5 传入的原始 JSON（含未声明字段，便于排查 H5 端字段漂移）
                Self.log.debug("← H5 friendsShare mode=\(String(describing: mode), privacy: .public) raw=\(Self.describe(data), privacy: .public)")

                guard let obj = data?.asObject else {
                    Self.log.error("friendsShare: data 不是 object，跳过分发")
                    return
                }
                let content = ShareContent(
                    // sharefriend / sharetype / type 实际 H5 传 number（如 1/2 而非 "1"/"2"），
                    // 必须用 asLooseString 兼容（与 mediaTypeAudio.user 同款问题，commit b058990）。
                    // 对齐原 msext ObjC 行为：[NSNumber intValue] 与 [NSString intValue] 都得到整数。
                    // 用 asString 会拿不到值 → 整路由跑偏到 default 分支。
                    sharefriend: obj["sharefriend"]?.asLooseString ?? "",
                    sharetype:   obj["sharetype"]?.asLooseString ?? "",
                    type:        obj["type"]?.asLooseString ?? "",
                    // 下面 3 项 H5 始终传 string，保持 asString
                    webpageUrl:  obj["webpageUrl"]?.asString ?? "",
                    title:       obj["title"]?.asString ?? "",
                    desc:        obj["description"]?.asString ?? ""
                )

                // 调试日志：解析后的 ShareContent 各字段（带语义注释方便定位行为分支）
                Self.log.debug("""
                friendsShare parsed:
                  sharefriend = "\(content.sharefriend, privacy: .public)"  (1=好友/SharePanel, 2/其他=朋友圈)
                  sharetype   = "\(content.sharetype,   privacy: .public)"  (1/2=微信, 3=闲聊；新外壳忽略)
                  type        = "\(content.type,        privacy: .public)"  (1=链接, 2=截图, 其他=远端图)
                  webpageUrl  = "\(content.webpageUrl,  privacy: .public)"
                  title       = "\(content.title,       privacy: .public)"
                  description = "\(content.desc,        privacy: .public)"
                """)

                // 2. 立即触发 sharesuccess —— 有意为之：调用即视为成功
                bridge?.call(
                    "sharesuccess",
                    data: .object([
                        "success": .string("2"),
                        "type":    .string(content.sharefriend)
                    ]),
                    callback: nil
                )
                Self.log.debug("→ H5 sharesuccess fired: success=\"2\", type=\"\(content.sharefriend, privacy: .public)\"")

                // 3. fire-and-forget 拉起真实分享 UI（按页面 mode 选路径）
                switch mode {
                case .lobby:
                    Self.log.debug("dispatch → lobby (直发微信 3 type 分支)")
                    ShareCenter.dispatchLobby(content)
                case .subGame:
                    Self.log.debug("dispatch → subGame (SharePanel 或朋友圈兜底)")
                    ShareCenter.dispatchSubGame(content)
                }
            }
        }
    }

    /// 把 BridgeData 整体序列化为 JSON 字符串方便日志输出（含 H5 传入的所有字段，
    /// 不限于上面解析的 6 项 —— 万一 H5 偷偷加了字段也能看到）。
    private static func describe(_ data: BridgeData?) -> String {
        guard let data else { return "<nil>" }
        let raw = data.jsonObject
        if let bytes = try? JSONSerialization.data(
            withJSONObject: raw,
            options: [.fragmentsAllowed, .sortedKeys]
        ), let s = String(data: bytes, encoding: .utf8) {
            return s
        }
        return String(describing: raw)
    }
}
