"""
微信 Skill v2.0 — 服务端完整版（对齐 Agent 端 112 个 RPC 方法）
================================================================

通道优先级：
1. Hook 通道（Frida RPC）— 最优先，通过 WiFi 无线连接
2. WebSocket 通道（Agent WirelessBridge）— 备选
3. UI 自动化通道（uiautomator2）— 最后降级

所有方法通过统一的 _execute() 分发到对应通道。

模块清单（24 个模块 / 112 个方法）：
  H15 消息接收 | H16 联系人 | H17 消息发送 | H18 好友请求监听
  H19 好友管理 | H20 朋友圈发布 | H21 朋友圈浏览 | H22 群管理
  H23 账号管理 | H24 账号安全 | H25 支付 | H26 二维码
  H27 视频号 | H28 标签管理 | H29 收藏管理 | H30 设置
  H31 搜索 | H32 小程序 | H33 文件传输 | H34 消息转发
  H35 注册/登录 | H36 公众号 | H37 表情管理 | H38 浮窗
  H39 设备信息
"""
import time
import logging
import asyncio
from typing import Dict, Any, Optional, List

logger = logging.getLogger(__name__)

# Hook 动作映射（与 agent/hook/hook_executor.py 完全对齐）
WECHAT_ACTIONS = {
    # ── H15 消息接收 ──
    "get_messages": "getMessages",
    "get_recent_messages": "getRecentMessages",
    "search_messages": "searchMessages",
    # ── H16 联系人 ──
    "get_contacts": "getContacts",
    "get_contact_info": "getContactInfo",
    "search_contacts": "searchContacts",
    # ── H17 消息发送 ──
    "send_message": "sendMessage",
    "send_group_message": "sendGroupMessage",
    # ── H18 好友请求 ──
    "get_friend_requests": "getFriendRequests",
    # ── H19 好友管理 ──
    "add_friend": "addFriend",
    "accept_friend": "acceptFriend",
    "delete_friend": "deleteFriend",
    "set_friend_remark": "setFriendRemark",
    "add_friend_by_qr": "addFriendByQr",
    # ── H20 朋友圈发布 ──
    "post_moments": "postMoments",
    "delete_moments": "deleteMoments",
    # ── H21 朋友圈浏览 ──
    "get_moments": "getMoments",
    "like_moments": "likeMoments",
    "comment_moments": "commentMoments",
    # ── H22 群管理 ──
    "get_groups": "getGroups",
    "get_group_info": "getGroupInfo",
    "get_group_members": "getGroupMembers",
    "create_group": "createGroup",
    "invite_to_group": "inviteToGroup",
    "remove_from_group": "removeFromGroup",
    "set_group_announcement": "setGroupAnnouncement",
    "set_group_name": "setGroupName",
    "quit_group": "quitGroup",
    # ── H23 账号管理 ──
    "get_profile": "getProfile",
    "check_account_status": "checkAccountStatus",
    "set_nickname": "setNickname",
    "set_signature": "setSignature",
    "set_avatar": "setAvatar",
    "set_sex": "setSex",
    "set_region": "setRegion",
    "set_what_up": "setWhatUp",
    # ── H24 账号安全 ──
    "unblock_self": "unblockSelf",
    "change_password": "changePassword",
    "bind_phone": "bindPhone",
    "unbind_phone": "unbindPhone",
    "get_login_devices": "getLoginDevices",
    "remove_login_device": "removeLoginDevice",
    "enable_fingerprint": "enableFingerprint",
    "set_account_protection": "setAccountProtection",
    # ── H25 支付 ──
    "send_red_packet": "sendRedPacket",
    "receive_red_packet": "receiveRedPacket",
    "send_transfer": "sendTransfer",
    "receive_transfer": "receiveTransfer",
    "get_wallet_balance": "getWalletBalance",
    "get_transaction_history": "getTransactionHistory",
    # ── H26 二维码 ──
    "scan_qr_code": "scanQrCode",
    "generate_my_qr_code": "generateMyQrCode",
    "generate_group_qr_code": "generateGroupQrCode",
    # ── H27 视频号 ──
    "browse_channels": "browseChannels",
    "like_channel_video": "likeChannelVideo",
    "comment_channel_video": "commentChannelVideo",
    "follow_channel": "followChannel",
    "unfollow_channel": "unfollowChannel",
    "share_channel_video": "shareChannelVideo",
    # ── H28 标签 ──
    "get_labels": "getLabels",
    "create_label": "createLabel",
    "delete_label": "deleteLabel",
    "set_contact_label": "setContactLabel",
    "get_contacts_by_label": "getContactsByLabel",
    # ── H29 收藏 ──
    "get_favorites": "getFavorites",
    "add_favorite": "addFavorite",
    "delete_favorite": "deleteFavorite",
    # ── H30 设置 ──
    "set_privacy": "setPrivacy",
    "set_notification": "setNotification",
    "clear_chat_history": "clearChatHistory",
    "set_chat_background": "setChatBackground",
    "set_do_not_disturb": "setDoNotDisturb",
    "pin_chat": "pinChat",
    # ── H31 搜索 ──
    "global_search": "globalSearch",
    # ── H32 小程序 ──
    "open_mini_program": "openMiniProgram",
    "get_recent_mini_programs": "getRecentMiniPrograms",
    "share_mini_program": "shareMiniProgram",
    # ── H33 文件传输 ──
    "send_image": "sendImage",
    "send_video": "sendVideo",
    "send_file": "sendFile",
    "send_voice": "sendVoice",
    "send_location": "sendLocation",
    "send_card": "sendCard",
    "send_link": "sendLink",
    # ── H34 消息转发 ──
    "forward_message": "forwardMessage",
    "forward_multiple": "forwardMultiple",
    "revoke_message": "revokeMessage",
    # ── H35 注册/登录 ──
    "register_account": "registerAccount",
    "login_by_password": "loginByPassword",
    "login_by_sms": "loginBySms",
    "logout": "logout",
    "switch_account": "switchAccount",
    "auto_register": "autoRegister",
    "check_login_state": "checkLoginState",
    "get_sim_phone": "getSimPhone",
    # ── H36 公众号 ──
    "get_official_accounts": "getOfficialAccounts",
    "follow_official_account": "followOfficialAccount",
    "unfollow_official_account": "unfollowOfficialAccount",
    "get_official_account_articles": "getOfficialAccountArticles",
    # ── H37 表情 ──
    "send_emoji": "sendEmoji",
    "add_custom_emoji": "addCustomEmoji",
    # ── H38 浮窗 ──
    "add_to_float": "addToFloat",
    "remove_from_float": "removeFromFloat",
    # ── H39 设备信息 ──
    "get_device_info": "getDeviceInfo",
    "get_storage_info": "getStorageInfo",
    "get_network_info": "getNetworkInfo",
    # ── 系统 ──
    "ping": "ping",
    "get_hook_status": "getHookStatus",
    "get_process_info": "getProcessInfo",
    "get_wechat_version": "getWechatVersion",
    "batch_execute": "batchExecute",
    "diag_wcdb": "diagWcdb",
    "diag_sns": "diagSns",
    # ── 矩阵 v8.0.56 补全（Frida RPC 直映射，禁止 REST 空占位）──
    "get_safety_center": "getSafetyCenter",
    "check_restrictions": "checkRestrictions",
    "get_top_stories": "getTopStories",
    "get_wechat_steps": "getWechatSteps",
    "get_sticker_list": "getStickerList",
    "show_payment_code": "showPaymentCode",
    "like_wechat_steps": "likeWechatSteps",
    "clear_cache": "clearCache",
    "check_for_update": "checkForUpdate",
    "voice_call": "voiceCall",
    "video_call": "videoCall",
    "share_real_time_location": "shareRealTimeLocation",
    "download_file": "downloadFile",
    "mass_send": "massSend",
    "batch_send": "massSend",
    "reply_comment": "replyComment",
    "receive_payment": "receivePayment",
    # ── 奥创协议补全（1077-1270 缺口 · 读类真 DB / 写类 intent 诚实通道）──
    "get_conversations": "getConversations",
    "get_message_by_id": "getMessageById",
    "get_msg_ids_by_time": "getMsgIdsByTime",
    "get_message_raw_xml": "getMessageRawXml",
    "add_friend_in_room": "addFriendInChatRoom",
    "add_friend_from_phonebook": "addFriendFromPhonebook",
    "add_friend_with_scene": "addFriendWithScene",
    "add_friend_by_card": "addFriendByCard",
    "join_group_by_qr": "joinGroupByQr",
    "approve_group_invite": "approveGroupInvite",
    "agree_join_group": "agreeJoinGroup",
    "mark_conversation_read": "markConversationRead",
    "send_multi_image": "sendMultiImage",
    "send_jielong": "sendJielong",
    "send_friend_verify": "sendFriendVerify",
    "voice_to_text": "voiceToText",
    "get_friend_moments": "getFriendMoments",
    "get_moment_detail": "getMomentDetail",
    "delete_moment_comment": "deleteMomentComment",
    "reply_moment_comment": "replyMomentComment",
    "stop_moments_praise": "stopMomentsPraise",
    "start_nurture": "startNurture",
    "stop_nurture": "stopNurture",
    "detect_zombie_fans": "detectZombieFans",
    "stop_detect_zombie_fans": "stopDetectZombieFans",
    "query_red_packet": "queryRedPacket",
    "get_wechat_location": "getWechatLocation",
    "search_official_account": "searchOfficialAccount",
    "phone_action": "phoneAction",
}

# 模块定义
MODULES = {
    "H15": {"name": "消息接收", "actions": ["get_messages", "get_recent_messages", "search_messages"]},
    "H16": {"name": "联系人", "actions": ["get_contacts", "get_contact_info", "search_contacts"]},
    "H17": {"name": "消息发送", "actions": ["send_message", "send_group_message"]},
    "H18": {"name": "好友请求", "actions": ["get_friend_requests"]},
    "H19": {"name": "好友管理", "actions": ["add_friend", "accept_friend", "delete_friend", "set_friend_remark", "add_friend_by_qr"]},
    "H20": {"name": "朋友圈发布", "actions": ["post_moments", "delete_moments"]},
    "H21": {"name": "朋友圈浏览", "actions": ["get_moments", "like_moments", "comment_moments"]},
    "H22": {"name": "群管理", "actions": ["get_groups", "get_group_info", "get_group_members", "create_group", "invite_to_group", "remove_from_group", "set_group_announcement", "set_group_name", "quit_group"]},
    "H23": {"name": "账号管理", "actions": ["get_profile", "check_account_status", "set_nickname", "set_signature", "set_avatar", "set_sex", "set_region", "set_what_up"]},
    "H24": {"name": "账号安全", "actions": ["unblock_self", "change_password", "bind_phone", "unbind_phone", "get_login_devices", "remove_login_device", "enable_fingerprint", "set_account_protection"]},
    "H25": {"name": "支付", "actions": ["send_red_packet", "receive_red_packet", "send_transfer", "receive_transfer", "get_wallet_balance", "get_transaction_history"]},
    "H26": {"name": "二维码", "actions": ["scan_qr_code", "generate_my_qr_code", "generate_group_qr_code"]},
    "H27": {"name": "视频号", "actions": ["browse_channels", "like_channel_video", "comment_channel_video", "follow_channel", "unfollow_channel", "share_channel_video"]},
    "H28": {"name": "标签", "actions": ["get_labels", "create_label", "delete_label", "set_contact_label", "get_contacts_by_label"]},
    "H29": {"name": "收藏", "actions": ["get_favorites", "add_favorite", "delete_favorite"]},
    "H30": {"name": "设置", "actions": ["set_privacy", "set_notification", "clear_chat_history", "set_chat_background", "set_do_not_disturb", "pin_chat"]},
    "H31": {"name": "搜索", "actions": ["global_search"]},
    "H32": {"name": "小程序", "actions": ["open_mini_program", "get_recent_mini_programs", "share_mini_program"]},
    "H33": {"name": "文件传输", "actions": ["send_image", "send_video", "send_file", "send_voice", "send_location", "send_card", "send_link"]},
    "H34": {"name": "消息转发", "actions": ["forward_message", "forward_multiple", "revoke_message"]},
    "H35": {"name": "注册/登录", "actions": ["register_account", "login_by_password", "login_by_sms", "logout", "switch_account", "auto_register", "check_login_state", "get_sim_phone"]},
    "H36": {"name": "公众号", "actions": ["get_official_accounts", "follow_official_account", "unfollow_official_account", "get_official_account_articles"]},
    "H37": {"name": "表情", "actions": ["send_emoji", "add_custom_emoji"]},
    "H38": {"name": "浮窗", "actions": ["add_to_float", "remove_from_float"]},
    "H39": {"name": "设备信息", "actions": ["get_device_info", "get_storage_info", "get_network_info"]},
    "H40": {
        "name": "矩阵补全",
        "actions": [
            "ping", "get_safety_center", "check_restrictions", "get_top_stories",
            "get_wechat_steps", "get_sticker_list", "show_payment_code", "like_wechat_steps",
            "clear_cache", "check_for_update", "voice_call", "video_call",
            "share_real_time_location", "download_file", "mass_send", "batch_send",
            "reply_comment", "receive_payment",
        ],
    },
}


class WechatSkillV2:
    """
    微信 Skill 完整版 — 128 个 action / 25 个模块（含矩阵 H40）
    
    通道优先级：Hook > WebSocket Agent > UI 自动化
    
    使用方式：
        skill = WechatSkillV2(device_id="xxx")
        result = await skill.execute("send_message", {"to_id": "filehelper", "content": "hello"})
    """

    PLATFORM = "wechat"

    def __init__(self, device_id: str, ws_hub=None):
        self.device_id = device_id
        self.ws_hub = ws_hub
        self._stats = {
            "total_calls": 0,
            "success": 0,
            "failed": 0,
            "by_channel": {"hook": 0, "ws_agent": 0, "ui": 0},
        }

    # ============================================================
    # § 1  统一执行入口
    # ============================================================

    async def execute(self, action: str, params: dict = None) -> Dict[str, Any]:
        """
        统一执行入口 — WebSocket + Frida Hook（经 device_transport，禁止空转占位）
        """
        params = params or {}
        original_action = action
        canonical = action

        try:
            import sys
            from pathlib import Path
            agent_root = Path(__file__).resolve().parents[2] / "agent"
            if str(agent_root) not in sys.path:
                sys.path.insert(0, str(agent_root))
            from hook.hook_executor import resolve_action, normalize_params
            canonical = resolve_action(action)
            params = normalize_params(action, params)
        except Exception:
            pass

        dispatch_action = canonical if canonical in WECHAT_ACTIONS else action
        if dispatch_action not in WECHAT_ACTIONS:
            return {
                "success": False,
                "error": f"不支持的操作: {original_action}",
                "resolved": canonical,
                "supported": list(WECHAT_ACTIONS.keys()),
            }

        action = dispatch_action
        self._stats["total_calls"] += 1
        start_time = time.time()

        from services.device_transport import device_transport

        hook_only = device_transport.should_force_hook_only("wechat", action, False)

        if device_transport.ws_hook_only("wechat"):
            if not device_transport.is_ws_online(self.device_id):
                out = device_transport.offline_payload(self.device_id)
                out["action"] = action
                self._stats["failed"] += 1
                return out
            result = await device_transport.execute_via_ws(
                self.device_id,
                "wechat",
                action,
                params,
                timeout=120,
                hook_only=hook_only,
            )
        else:
            result = await self._execute_legacy(action, params, hook_only)

        elapsed = int((time.time() - start_time) * 1000)
        result["latency_ms"] = elapsed
        result.setdefault("action", action)
        result.setdefault("device_id", self.device_id)

        inner = result.get("data") if isinstance(result.get("data"), dict) else {}
        ok = bool(
            result.get("success")
            or inner.get("success")
            or (result.get("code") in (200, 0) and inner.get("success") is not False)
        )
        if ok and "offline" in str(result.get("_channel_used", "")):
            ok = False
            result["success"] = False
            result.setdefault("error", "设备 WebSocket 未在线")

        if ok:
            self._stats["success"] += 1
            ch = str(result.get("_channel_used", "websocket/hook"))
            if "hook" in ch:
                self._stats["by_channel"]["hook"] += 1
            elif "ws" in ch or "websocket" in ch:
                self._stats["by_channel"]["ws_agent"] += 1
            else:
                self._stats["by_channel"]["ui"] += 1
            result["channel"] = ch.split("/")[-1] if "/" in ch else ch
        else:
            self._stats["failed"] += 1

        return result

    async def _execute_legacy(self, action: str, params: dict, hook_only: bool) -> Dict[str, Any]:
        """非 WS 优先模式下的旧通道（运维/调试）。"""
        from services.device_transport import device_transport
        if device_transport.is_ws_online(self.device_id):
            return await device_transport.execute_via_ws(
                self.device_id, "wechat", action, params, timeout=120, hook_only=hook_only,
            )
        result = await self._execute_via_ui(action, params)
        if result:
            result["_channel_used"] = "adb/ui"
            return result
        return {"success": False, "error": f"所有通道均失败: {action}", "_channel_used": "offline"}

    # ============================================================
    # § 2  Hook / WS 通道（已合并至 execute → device_transport）
    # ============================================================

    async def _execute_via_hook(self, action: str, params: dict) -> Optional[Dict[str, Any]]:
        """Deprecated: 使用 execute() → device_transport.execute_via_ws"""
        from services.device_transport import device_transport
        if not device_transport.is_ws_online(self.device_id):
            return None
        return await device_transport.execute_via_ws(
            self.device_id, "wechat", action, params, hook_only=True,
        )

    async def _execute_via_ws_agent(self, action: str, params: dict) -> Optional[Dict[str, Any]]:
        return await self._execute_via_hook(action, params)

    # ============================================================
    # § 4  UI 自动化通道（降级）
    # ============================================================

    async def _execute_via_ui(self, action: str, params: dict) -> Optional[Dict[str, Any]]:
        """通过 UI 自动化执行（最后降级方案）"""
        # UI 自动化只支持部分操作
        ui_supported = {
            "send_message", "get_contacts", "add_friend", "accept_friend",
            "get_messages", "post_moments",
        }
        if action not in ui_supported:
            return None

        try:
            # 尝试通过 ADB 设备执行
            from services.adb_device import adb_manager
            device = adb_manager.get_device(self.device_id)
            if not device or not device.is_online():
                return None

            # 委托给旧版 UI Skill
            from skills.wechat.skill import WechatSkill
            ui_skill = WechatSkill(device.d)
            
            if action == "send_message":
                return await ui_skill.send_message(
                    params.get("to_id", ""),
                    params.get("content", ""),
                )
            elif action == "get_contacts":
                return await ui_skill.get_contacts(params.get("limit", 100))
            elif action == "get_messages":
                return await ui_skill.get_messages(params.get("limit", 20))
            elif action == "add_friend":
                return await ui_skill.add_friend(
                    params.get("user_id", ""),
                    params.get("message", ""),
                )
            elif action == "accept_friend":
                return await ui_skill.accept_friend(params.get("user_id", ""))

            return None

        except Exception as e:
            logger.debug(f"UI 通道失败: {action} - {e}")
            return None

    # ============================================================
    # § 5  便捷方法（每个方法对应一个 RPC 操作）
    # ============================================================

    # ---- H15 消息接收 ----
    async def get_messages(self, conversation_id: str = "", limit: int = 50) -> Dict[str, Any]:
        return await self.execute("get_messages", {"conversation_id": conversation_id, "limit": limit})

    async def get_recent_messages(self, limit: int = 20) -> Dict[str, Any]:
        return await self.execute("get_recent_messages", {"limit": limit})

    async def search_messages(self, keyword: str, limit: int = 50) -> Dict[str, Any]:
        return await self.execute("search_messages", {"keyword": keyword, "limit": limit})

    # ---- H16 联系人 ----
    async def get_contacts(self, limit: int = 200) -> Dict[str, Any]:
        return await self.execute("get_contacts", {"limit": limit})

    async def get_contact_info(self, wxid: str) -> Dict[str, Any]:
        return await self.execute("get_contact_info", {"wxid": wxid})

    async def search_contacts(self, keyword: str, limit: int = 50) -> Dict[str, Any]:
        return await self.execute("search_contacts", {"keyword": keyword, "limit": limit})

    # ---- H17 消息发送 ----
    async def send_message(self, to_id: str, content: str, msg_type: str = "text") -> Dict[str, Any]:
        return await self.execute("send_message", {"to_id": to_id, "content": content, "msg_type": msg_type})

    async def send_group_message(self, group_id: str, content: str) -> Dict[str, Any]:
        return await self.execute("send_group_message", {"group_id": group_id, "content": content})

    # ---- H18 好友请求 ----
    async def get_friend_requests(self, limit: int = 50) -> Dict[str, Any]:
        return await self.execute("get_friend_requests", {"limit": limit})

    # ---- H19 好友管理 ----
    async def add_friend(self, user_id: str, message: str = "", source_type: int = 3) -> Dict[str, Any]:
        return await self.execute("add_friend", {"user_id": user_id, "message": message, "source_type": source_type})

    async def accept_friend(self, encrypt_username: str = "", ticket: str = "") -> Dict[str, Any]:
        return await self.execute("accept_friend", {"encrypt_username": encrypt_username, "ticket": ticket})

    async def delete_friend(self, wxid: str) -> Dict[str, Any]:
        return await self.execute("delete_friend", {"wxid": wxid})

    async def set_friend_remark(self, wxid: str, remark: str) -> Dict[str, Any]:
        return await self.execute("set_friend_remark", {"wxid": wxid, "remark": remark})

    async def add_friend_by_qr(self, qr_content: str) -> Dict[str, Any]:
        return await self.execute("add_friend_by_qr", {"qr_content": qr_content})

    # ---- H20/H21 朋友圈 ----
    async def post_moments(self, content: str, image_urls: list = None) -> Dict[str, Any]:
        return await self.execute("post_moments", {"content": content, "image_urls": image_urls or []})

    async def get_moments(self, wxid: str = "", limit: int = 20) -> Dict[str, Any]:
        return await self.execute("get_moments", {"wxid": wxid, "limit": limit})

    async def like_moments(self, sns_id: str) -> Dict[str, Any]:
        return await self.execute("like_moments", {"sns_id": sns_id})

    async def comment_moments(self, sns_id: str, comment: str) -> Dict[str, Any]:
        return await self.execute("comment_moments", {"sns_id": sns_id, "comment": comment})

    async def delete_moments(self, sns_id: str) -> Dict[str, Any]:
        return await self.execute("delete_moments", {"sns_id": sns_id})

    # ---- H22 群管理 ----
    async def get_groups(self, limit: int = 100) -> Dict[str, Any]:
        return await self.execute("get_groups", {"limit": limit})

    async def get_group_info(self, group_id: str) -> Dict[str, Any]:
        return await self.execute("get_group_info", {"group_id": group_id})

    async def get_group_members(self, group_id: str) -> Dict[str, Any]:
        return await self.execute("get_group_members", {"group_id": group_id})

    async def create_group(self, member_ids: list, topic: str = "") -> Dict[str, Any]:
        return await self.execute("create_group", {"member_ids": member_ids, "topic": topic})

    async def invite_to_group(self, group_id: str, member_ids: list) -> Dict[str, Any]:
        return await self.execute("invite_to_group", {"group_id": group_id, "member_ids": member_ids})

    async def remove_from_group(self, group_id: str, member_ids: list) -> Dict[str, Any]:
        return await self.execute("remove_from_group", {"group_id": group_id, "member_ids": member_ids})

    async def set_group_announcement(self, group_id: str, announcement: str) -> Dict[str, Any]:
        return await self.execute("set_group_announcement", {"group_id": group_id, "announcement": announcement})

    async def set_group_name(self, group_id: str, name: str) -> Dict[str, Any]:
        return await self.execute("set_group_name", {"group_id": group_id, "name": name})

    async def quit_group(self, group_id: str) -> Dict[str, Any]:
        return await self.execute("quit_group", {"group_id": group_id})

    # ---- H23 账号管理 ----
    async def get_profile(self) -> Dict[str, Any]:
        return await self.execute("get_profile")

    async def check_account_status(self) -> Dict[str, Any]:
        return await self.execute("check_account_status")

    async def set_nickname(self, nickname: str) -> Dict[str, Any]:
        return await self.execute("set_nickname", {"nickname": nickname})

    async def set_signature(self, signature: str) -> Dict[str, Any]:
        return await self.execute("set_signature", {"signature": signature})

    async def set_avatar(self, image_path: str) -> Dict[str, Any]:
        return await self.execute("set_avatar", {"image_path": image_path})

    async def set_sex(self, sex: str) -> Dict[str, Any]:
        return await self.execute("set_sex", {"sex": sex})

    async def set_region(self, region: str) -> Dict[str, Any]:
        return await self.execute("set_region", {"region": region})

    async def set_what_up(self, status: str) -> Dict[str, Any]:
        return await self.execute("set_what_up", {"status": status})

    # ---- H24 账号安全 ----
    async def unblock_self(self) -> Dict[str, Any]:
        return await self.execute("unblock_self")

    async def change_password(self, old_password: str, new_password: str) -> Dict[str, Any]:
        return await self.execute("change_password", {"old_password": old_password, "new_password": new_password})

    async def bind_phone(self, phone: str) -> Dict[str, Any]:
        return await self.execute("bind_phone", {"phone": phone})

    async def unbind_phone(self) -> Dict[str, Any]:
        return await self.execute("unbind_phone")

    async def get_login_devices(self) -> Dict[str, Any]:
        return await self.execute("get_login_devices")

    async def remove_login_device(self, device_id: str) -> Dict[str, Any]:
        return await self.execute("remove_login_device", {"device_id": device_id})

    async def enable_fingerprint(self, enable: bool = True) -> Dict[str, Any]:
        return await self.execute("enable_fingerprint", {"enable": enable})

    async def set_account_protection(self, enable: bool = True) -> Dict[str, Any]:
        return await self.execute("set_account_protection", {"enable": enable})

    # ---- H25 支付 ----
    async def send_red_packet(self, to_id: str, amount: str, message: str = "恭喜发财") -> Dict[str, Any]:
        return await self.execute("send_red_packet", {"to_id": to_id, "amount": amount, "message": message})

    async def receive_red_packet(self, msg_svr_id: str) -> Dict[str, Any]:
        return await self.execute("receive_red_packet", {"msg_svr_id": msg_svr_id})

    async def send_transfer(self, to_id: str, amount: str, description: str = "") -> Dict[str, Any]:
        return await self.execute("send_transfer", {"to_id": to_id, "amount": amount, "description": description})

    async def receive_transfer(self, msg_svr_id: str) -> Dict[str, Any]:
        return await self.execute("receive_transfer", {"msg_svr_id": msg_svr_id})

    async def get_wallet_balance(self) -> Dict[str, Any]:
        return await self.execute("get_wallet_balance")

    async def get_transaction_history(self, limit: int = 20) -> Dict[str, Any]:
        return await self.execute("get_transaction_history", {"limit": limit})

    # ---- H26 二维码 ----
    async def scan_qr_code(self, image_path: str = "") -> Dict[str, Any]:
        return await self.execute("scan_qr_code", {"image_path": image_path})

    async def generate_my_qr_code(self) -> Dict[str, Any]:
        return await self.execute("generate_my_qr_code")

    async def generate_group_qr_code(self, group_id: str) -> Dict[str, Any]:
        return await self.execute("generate_group_qr_code", {"group_id": group_id})

    # ---- H27 视频号 ----
    async def browse_channels(self, limit: int = 10) -> Dict[str, Any]:
        return await self.execute("browse_channels", {"limit": limit})

    async def like_channel_video(self, video_id: str) -> Dict[str, Any]:
        return await self.execute("like_channel_video", {"video_id": video_id})

    async def comment_channel_video(self, video_id: str, comment: str) -> Dict[str, Any]:
        return await self.execute("comment_channel_video", {"video_id": video_id, "comment": comment})

    async def follow_channel(self, channel_id: str) -> Dict[str, Any]:
        return await self.execute("follow_channel", {"channel_id": channel_id})

    async def unfollow_channel(self, channel_id: str) -> Dict[str, Any]:
        return await self.execute("unfollow_channel", {"channel_id": channel_id})

    async def share_channel_video(self, video_id: str, to_id: str) -> Dict[str, Any]:
        return await self.execute("share_channel_video", {"video_id": video_id, "to_id": to_id})

    # ---- H28 标签 ----
    async def get_labels(self) -> Dict[str, Any]:
        return await self.execute("get_labels")

    async def create_label(self, name: str) -> Dict[str, Any]:
        return await self.execute("create_label", {"name": name})

    async def delete_label(self, label_id: str) -> Dict[str, Any]:
        return await self.execute("delete_label", {"label_id": label_id})

    async def set_contact_label(self, wxid: str, label_ids: list) -> Dict[str, Any]:
        return await self.execute("set_contact_label", {"wxid": wxid, "label_ids": label_ids})

    async def get_contacts_by_label(self, label_id: str) -> Dict[str, Any]:
        return await self.execute("get_contacts_by_label", {"label_id": label_id})

    # ---- H29 收藏 ----
    async def get_favorites(self, limit: int = 50) -> Dict[str, Any]:
        return await self.execute("get_favorites", {"limit": limit})

    async def add_favorite(self, msg_svr_id: str, type: str = "message") -> Dict[str, Any]:
        return await self.execute("add_favorite", {"msg_svr_id": msg_svr_id, "type": type})

    async def delete_favorite(self, local_id: str) -> Dict[str, Any]:
        return await self.execute("delete_favorite", {"local_id": local_id})

    # ---- H30 设置 ----
    async def set_privacy(self, setting: str, value: bool = True) -> Dict[str, Any]:
        return await self.execute("set_privacy", {"setting": setting, "value": value})

    async def set_notification(self, type: str = "all", enable: bool = True) -> Dict[str, Any]:
        return await self.execute("set_notification", {"type": type, "enable": enable})

    async def clear_chat_history(self, wxid: str) -> Dict[str, Any]:
        return await self.execute("clear_chat_history", {"wxid": wxid})

    async def set_chat_background(self, wxid: str, image_path: str = "") -> Dict[str, Any]:
        return await self.execute("set_chat_background", {"wxid": wxid, "image_path": image_path})

    async def set_do_not_disturb(self, wxid: str, enable: bool = True) -> Dict[str, Any]:
        return await self.execute("set_do_not_disturb", {"wxid": wxid, "enable": enable})

    async def pin_chat(self, wxid: str, pin: bool = True) -> Dict[str, Any]:
        return await self.execute("pin_chat", {"wxid": wxid, "pin": pin})

    # ---- H31 搜索 ----
    async def global_search(self, keyword: str, limit: int = 30) -> Dict[str, Any]:
        return await self.execute("global_search", {"keyword": keyword, "limit": limit})

    # ---- H32 小程序 ----
    async def open_mini_program(self, app_id: str, path: str = "") -> Dict[str, Any]:
        return await self.execute("open_mini_program", {"app_id": app_id, "path": path})

    async def get_recent_mini_programs(self) -> Dict[str, Any]:
        return await self.execute("get_recent_mini_programs")

    async def share_mini_program(self, app_id: str, to_id: str, title: str = "") -> Dict[str, Any]:
        return await self.execute("share_mini_program", {"app_id": app_id, "to_id": to_id, "title": title})

    # ---- H33 文件传输 ----
    async def send_image(self, to_id: str, image_path: str) -> Dict[str, Any]:
        return await self.execute("send_image", {"to_id": to_id, "image_path": image_path})

    async def send_video(self, to_id: str, video_path: str) -> Dict[str, Any]:
        return await self.execute("send_video", {"to_id": to_id, "video_path": video_path})

    async def send_file(self, to_id: str, file_path: str) -> Dict[str, Any]:
        return await self.execute("send_file", {"to_id": to_id, "file_path": file_path})

    async def send_voice(self, to_id: str, voice_path: str, duration: int = 0) -> Dict[str, Any]:
        return await self.execute("send_voice", {"to_id": to_id, "voice_path": voice_path, "duration": duration})

    async def send_location(self, to_id: str, latitude: str = "", longitude: str = "", label: str = "") -> Dict[str, Any]:
        return await self.execute("send_location", {"to_id": to_id, "latitude": latitude, "longitude": longitude, "label": label})

    async def send_card(self, to_id: str, card_wxid: str) -> Dict[str, Any]:
        return await self.execute("send_card", {"to_id": to_id, "card_wxid": card_wxid})

    async def send_link(self, to_id: str, url: str, title: str = "", description: str = "") -> Dict[str, Any]:
        return await self.execute("send_link", {"to_id": to_id, "url": url, "title": title, "description": description})

    # ---- H34 消息转发 ----
    async def forward_message(self, msg_svr_id: str, to_id: str) -> Dict[str, Any]:
        return await self.execute("forward_message", {"msg_svr_id": msg_svr_id, "to_id": to_id})

    async def forward_multiple(self, msg_svr_ids: list, to_id: str) -> Dict[str, Any]:
        return await self.execute("forward_multiple", {"msg_svr_ids": msg_svr_ids, "to_id": to_id})

    async def revoke_message(self, msg_svr_id: str) -> Dict[str, Any]:
        return await self.execute("revoke_message", {"msg_svr_id": msg_svr_id})

    # ---- H35 注册/登录 ----
    async def register_account(self, phone: str, nickname: str = "", password: str = "") -> Dict[str, Any]:
        return await self.execute("register_account", {"phone": phone, "nickname": nickname, "password": password})

    async def login_by_password(self, phone: str, password: str) -> Dict[str, Any]:
        return await self.execute("login_by_password", {"phone": phone, "password": password})

    async def login_by_sms(self, phone: str) -> Dict[str, Any]:
        return await self.execute("login_by_sms", {"phone": phone})

    async def logout(self) -> Dict[str, Any]:
        return await self.execute("logout")

    async def switch_account(self, wxid: str) -> Dict[str, Any]:
        return await self.execute("switch_account", {"wxid": wxid})

    async def auto_register(self, phone: str = "", nickname: str = "卡若AI", password: str = "") -> Dict[str, Any]:
        return await self.execute("auto_register", {"phone": phone, "nickname": nickname, "password": password})

    async def check_login_state(self) -> Dict[str, Any]:
        return await self.execute("check_login_state")

    async def get_sim_phone(self) -> Dict[str, Any]:
        return await self.execute("get_sim_phone")

    # ---- H36 公众号 ----
    async def get_official_accounts(self, limit: int = 100) -> Dict[str, Any]:
        return await self.execute("get_official_accounts", {"limit": limit})

    async def follow_official_account(self, account_id: str) -> Dict[str, Any]:
        return await self.execute("follow_official_account", {"account_id": account_id})

    async def unfollow_official_account(self, account_id: str) -> Dict[str, Any]:
        return await self.execute("unfollow_official_account", {"account_id": account_id})

    async def get_official_account_articles(self, account_id: str, limit: int = 10) -> Dict[str, Any]:
        return await self.execute("get_official_account_articles", {"account_id": account_id, "limit": limit})

    # ---- H37 表情 ----
    async def send_emoji(self, to_id: str, emoji_md5: str) -> Dict[str, Any]:
        return await self.execute("send_emoji", {"to_id": to_id, "emoji_md5": emoji_md5})

    async def add_custom_emoji(self, image_path: str) -> Dict[str, Any]:
        return await self.execute("add_custom_emoji", {"image_path": image_path})

    # ---- H38 浮窗 ----
    async def add_to_float(self, wxid: str) -> Dict[str, Any]:
        return await self.execute("add_to_float", {"wxid": wxid})

    async def remove_from_float(self, wxid: str) -> Dict[str, Any]:
        return await self.execute("remove_from_float", {"wxid": wxid})

    # ---- H39 设备信息 ----
    async def get_device_info(self) -> Dict[str, Any]:
        return await self.execute("get_device_info")

    async def get_storage_info(self) -> Dict[str, Any]:
        return await self.execute("get_storage_info")

    async def get_network_info(self) -> Dict[str, Any]:
        return await self.execute("get_network_info")

    # ---- 系统 ----
    async def get_hook_status(self) -> Dict[str, Any]:
        return await self.execute("get_hook_status")

    async def get_process_info(self) -> Dict[str, Any]:
        return await self.execute("get_process_info")

    async def get_wechat_version(self) -> Dict[str, Any]:
        return await self.execute("get_wechat_version")

    async def batch_execute(self, actions: list) -> Dict[str, Any]:
        return await self.execute("batch_execute", {"actions": actions})

    async def diag_wcdb(self) -> Dict[str, Any]:
        return await self.execute("diag_wcdb")

    # ---- H40 矩阵补全 ----
    async def ping(self) -> Dict[str, Any]:
        return await self.execute("ping")

    async def get_safety_center(self) -> Dict[str, Any]:
        return await self.execute("get_safety_center")

    async def check_restrictions(self) -> Dict[str, Any]:
        return await self.execute("check_restrictions")

    async def get_top_stories(self) -> Dict[str, Any]:
        return await self.execute("get_top_stories")

    async def get_wechat_steps(self) -> Dict[str, Any]:
        return await self.execute("get_wechat_steps")

    async def get_sticker_list(self) -> Dict[str, Any]:
        return await self.execute("get_sticker_list")

    async def show_payment_code(self) -> Dict[str, Any]:
        return await self.execute("show_payment_code")

    async def like_wechat_steps(self, user_id: str = "filehelper") -> Dict[str, Any]:
        return await self.execute("like_wechat_steps", {"user_id": user_id})

    async def clear_cache(self) -> Dict[str, Any]:
        return await self.execute("clear_cache")

    async def check_for_update(self) -> Dict[str, Any]:
        return await self.execute("check_for_update")

    async def voice_call(self, to_id: str) -> Dict[str, Any]:
        return await self.execute("voice_call", {"to_id": to_id})

    async def video_call(self, to_id: str) -> Dict[str, Any]:
        return await self.execute("video_call", {"to_id": to_id})

    async def share_real_time_location(self, to_id: str) -> Dict[str, Any]:
        return await self.execute("share_real_time_location", {"to_id": to_id})

    async def download_file(self, url: str, save_path: str) -> Dict[str, Any]:
        return await self.execute("download_file", {"url": url, "save_path": save_path})

    async def mass_send(self, user_ids: list, content: str) -> Dict[str, Any]:
        return await self.execute("mass_send", {"user_ids": user_ids, "content": content})

    async def batch_send(self, user_ids: list, content: str) -> Dict[str, Any]:
        return await self.execute("batch_send", {"user_ids": user_ids, "content": content})

    async def reply_comment(self, sns_id: str, comment: str) -> Dict[str, Any]:
        return await self.execute("reply_comment", {"sns_id": sns_id, "comment": comment})

    async def receive_payment(self, msg_svr_id: str) -> Dict[str, Any]:
        return await self.execute("receive_payment", {"msg_svr_id": msg_svr_id})

    # ============================================================
    # § 6  状态查询
    # ============================================================

    def get_stats(self) -> Dict[str, Any]:
        return {
            "device_id": self.device_id,
            "platform": self.PLATFORM,
            "total_actions": len(WECHAT_ACTIONS),
            "total_modules": len(MODULES),
            "stats": self._stats,
            "modules": {k: v["name"] for k, v in MODULES.items()},
        }

    @staticmethod
    def get_action_list() -> List[str]:
        return sorted(WECHAT_ACTIONS.keys())

    @staticmethod
    def get_catalog_action_list() -> List[str]:
        """128 canonical + 46 matrix aliases = 173 hook catalog entries."""
        try:
            import sys
            from pathlib import Path
            agent_root = Path(__file__).resolve().parents[2] / "agent"
            if str(agent_root) not in sys.path:
                sys.path.insert(0, str(agent_root))
            from hook.hook_executor import ACTION_TO_RPC, ACTION_ALIASES
            return sorted(set(ACTION_TO_RPC.keys()) | set(ACTION_ALIASES.keys()))
        except Exception:
            return WechatSkillV2.get_action_list()

    @staticmethod
    def get_module_list() -> Dict[str, Any]:
        return MODULES
