// 微信工作手机 SDK v9-final - 全量Frida RPC接口
// 修复: Java.choose异步问题 -> 改用全局初始化+同步等待
// 修复: chatroom表列名(owner->roomowner), ContactLabel表, 朋友圈DB路径
// 账号：游条姐 (wxid_5g37snchpv8e22)
'use strict';

var _dbs = {};
var _dbsReady = false;
var _initCount = 0;

// ==================== DB初始化（脚本加载时立即执行）====================
function initAllDBs() {
    _initCount++;
    Java.choose('com.tencent.wcdb.database.SQLiteDatabase', {
        onMatch: function(db) {
            try {
                var p = db.getPath();
                if (!p) return;
                if (p.indexOf('EnMicroMsg') > -1 && p.indexOf('EnMicroMsg.db') > -1) _dbs['main'] = db;
                else if (p.indexOf('SnsMicroMsg') > -1) _dbs['sns'] = db;
                else if (p.indexOf('sns_star_info') > -1) _dbs['sns_star'] = db;
                else if (p.indexOf('WalletCoreDB-2') > -1) _dbs['wallet'] = db;
                else if (p.indexOf('WalletPay') > -1) _dbs['wallet2'] = db;
                else if (p.indexOf('FinderMM029') > -1) _dbs['finder'] = db;
                else if (p.indexOf('FinderMessage006') > -1) _dbs['finder2'] = db;
                else if (p.indexOf('FinderAccounts_01') > -1) _dbs['finder3'] = db;
                else if (p.indexOf('enFavorite') > -1) _dbs['favorite'] = db;
                else if (p.indexOf('FTS5IndexMicroMsg') > -1) _dbs['fts5'] = db;
                else if (p.indexOf('AppBrandComm') > -1) _dbs['appbrand'] = db;
                else if (p.indexOf('WxFileIndex') > -1) _dbs['wxfile'] = db;
                var key = '_path_' + p.split('/').pop().replace('.db','');
                _dbs[key] = db;
            } catch(e) {}
        },
        onComplete: function() {
            _dbsReady = true;
            var dbNames = Object.keys(_dbs).filter(function(k) { return !k.startsWith('_path_'); });
            send('[*] WeChat SDK v9-final loaded. DBs: ' + dbNames.join(', '));
        }
    });
}

// 脚本加载时立即初始化
Java.perform(function() {
    initAllDBs();
});

function getDB(name) {
    if (!_dbs[name]) {
        // 重新尝试初始化（可能DB刚被加载）
        initAllDBs();
        // 等待一小段时间
        var start = Date.now();
        while (!_dbs[name] && Date.now() - start < 2000) {
            // 忙等待最多2秒
        }
    }
    return _dbs[name] || null;
}

function execSQL(db, sql, args) {
    if (!db) return {error: 'DB not available', rows: [], count: 0};
    try {
        var cursor;
        if (args && args.length > 0) {
            var jArgs = Java.array('java.lang.String', args.map(function(a) { return a ? String(a) : null; }));
            cursor = db.rawQuery(sql, jArgs);
        } else {
            cursor = db.rawQuery(sql, null);
        }
        var cols = [];
        var colCount = cursor.getColumnCount();
        for (var i = 0; i < colCount; i++) cols.push(cursor.getColumnName(i));
        var rows = [];
        while (cursor.moveToNext()) {
            var row = {};
            for (var j = 0; j < colCount; j++) {
                try { row[cols[j]] = cursor.getString(j); } catch(e) { row[cols[j]] = null; }
            }
            rows.push(row);
        }
        cursor.close();
        return {columns: cols, rows: rows, count: rows.length};
    } catch(e) {
        return {error: e.toString(), rows: [], count: 0};
    }
}

function writeSQL(db, sql) {
    if (!db) return {error: 'DB not available'};
    try {
        db.execSQL(sql);
        return {success: true};
    } catch(e) {
        return {error: e.toString()};
    }
}

// ==================== RPC接口 ====================
rpc.exports = {
    // ===== 系统 =====
    ping: function() {
        var dbStatus = {};
        ['main','sns','sns_star','wallet','finder','favorite','fts5','appbrand'].forEach(function(n) {
            dbStatus[n] = !!_dbs[n];
        });
        return {status: 'ok', version: 'v9-final', timestamp: Date.now(), dbs: dbStatus};
    },

    initDbs: function() {
        initAllDBs();
        var status = {};
        ['main','sns','sns_star','wallet','wallet2','finder','finder2','finder3','favorite','fts5','appbrand'].forEach(function(n) {
            status[n] = !!_dbs[n];
        });
        return {status: status, total_dbs: Object.keys(_dbs).length};
    },

    // ===== 账号 =====
    getAccountInfo: function() {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        var wxid = execSQL(db, "SELECT value FROM userinfo WHERE id=2");
        var nick = execSQL(db, "SELECT value FROM userinfo WHERE id=6");
        var avatar = execSQL(db, "SELECT value FROM userinfo WHERE id=4");
        var phone = execSQL(db, "SELECT value FROM userinfo WHERE id=42");
        var region = execSQL(db, "SELECT value FROM userinfo WHERE id=44");
        var sex = execSQL(db, "SELECT value FROM userinfo WHERE id=12");
        return {
            wxid: wxid.rows[0] ? wxid.rows[0].value : null,
            nickname: nick.rows[0] ? nick.rows[0].value : null,
            avatar: avatar.rows[0] ? avatar.rows[0].value : null,
            phone: phone.rows[0] ? phone.rows[0].value : null,
            region: region.rows[0] ? region.rows[0].value : null,
            sex: sex.rows[0] ? sex.rows[0].value : null,
        };
    },

    // ===== 联系人 =====
    getContacts: function(limit, offset) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available', rows: [], count: 0};
        limit = parseInt(limit) || 100;
        offset = parseInt(offset) || 0;
        return execSQL(db,
            "SELECT username, alias, conRemark, nickname, type, contactLabelIds " +
            "FROM rcontact WHERE type=3 ORDER BY rowid LIMIT " + limit + " OFFSET " + offset
        );
    },

    getContactCount: function() {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        var r1 = execSQL(db, "SELECT COUNT(*) as friends FROM rcontact WHERE type=3");
        var r2 = execSQL(db, "SELECT COUNT(*) as total FROM rcontact");
        return {
            friends: r1.rows[0] ? parseInt(r1.rows[0].friends) : 0,
            total: r2.rows[0] ? parseInt(r2.rows[0].total) : 0
        };
    },

    getContactDetail: function(wxid) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        return execSQL(db, "SELECT * FROM rcontact WHERE username='" + wxid + "' LIMIT 1");
    },

    searchContacts: function(keyword) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available', rows: [], count: 0};
        return execSQL(db,
            "SELECT username, alias, conRemark, nickName, type FROM rcontact " +
            "WHERE (nickName LIKE '%" + keyword + "%' OR conRemark LIKE '%" + keyword + "%' OR alias LIKE '%" + keyword + "%') " +
            "AND type NOT IN (0,4) LIMIT 50"
        );
    },

    // ===== 标签 =====
    getLabels: function() {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available', rows: [], count: 0};
        // 先尝试ContactLabel表
        var r = execSQL(db, "SELECT labelId, labelName, createTime FROM ContactLabel ORDER BY labelId");
        if (r.count > 0) return r;
        // 备用：从rcontact的contactLabelIds字段提取唯一ID
        var ids = execSQL(db, "SELECT DISTINCT contactLabelIds FROM rcontact WHERE contactLabelIds != '' AND contactLabelIds IS NOT NULL LIMIT 200");
        var labelSet = {};
        ids.rows.forEach(function(row) {
            var parts = (row.contactLabelIds || '').split(',');
            parts.forEach(function(id) { if (id) labelSet[id.trim()] = true; });
        });
        var rows = Object.keys(labelSet).map(function(id) { return {labelId: id, labelName: 'Label_' + id}; });
        return {columns: ['labelId', 'labelName'], rows: rows, count: rows.length};
    },

    getLabelContacts: function(labelId) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available', rows: [], count: 0};
        return execSQL(db,
            "SELECT username, nickName, conRemark, contactLabelIds FROM rcontact " +
            "WHERE contactLabelIds LIKE '%" + labelId + "%' AND type=3 LIMIT 200"
        );
    },

    // ===== 统计 =====
    getAllStats: function() {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        var friends = execSQL(db, "SELECT COUNT(*) as n FROM rcontact WHERE type=3");
        var groups = execSQL(db, "SELECT COUNT(*) as n FROM chatroom");
        var labels = execSQL(db, "SELECT COUNT(*) as n FROM ContactLabel");
        var msgs = execSQL(db, "SELECT COUNT(*) as n FROM message");
        var imgs = execSQL(db, "SELECT COUNT(*) as n FROM ImgInfo2");
        var videos = execSQL(db, "SELECT COUNT(*) as n FROM videoinfo2");
        var files = execSQL(db, "SELECT COUNT(*) as n FROM FileMsgInfo");
        var labels = execSQL(db, "SELECT COUNT(*) as n FROM ContactLabel");
        return {
            friends: friends.rows[0] ? parseInt(friends.rows[0].n) : 0,
            groups: groups.rows[0] ? parseInt(groups.rows[0].n) : 0,
            messages: msgs.rows[0] ? parseInt(msgs.rows[0].n) : 0,
            images: imgs.rows[0] ? parseInt(imgs.rows[0].n) : 0,
            videos: videos.rows[0] ? parseInt(videos.rows[0].n) : 0,
            files: files.rows[0] ? parseInt(files.rows[0].n) : 0,
            labels: labels.rows[0] ? parseInt(labels.rows[0].n) : 0
        };
    },

    // ===== 消息 =====
    getRecentMessages: function(hours) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available', rows: [], count: 0};
        hours = parseInt(hours) || 24;
        var since = Date.now() - hours * 3600 * 1000;
        return execSQL(db,
            "SELECT msgId, type, content, talker, createTime, isSend FROM message " +
            "WHERE createTime > " + since + " ORDER BY createTime DESC LIMIT 200"
        );
    },

    getMessages: function(talker, limit) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available', rows: [], count: 0};
        limit = parseInt(limit) || 50;
        return execSQL(db,
            "SELECT msgId, type, content, talker, createTime, isSend FROM message " +
            "WHERE talker='" + talker + "' ORDER BY createTime DESC LIMIT " + limit
        );
    },

    sendMessage: function(toUser, content, type) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        type = parseInt(type) || 1;
        var msgId = Date.now();
        var createTime = Date.now();
        var sql = "INSERT INTO message (msgId, type, status, isSend, content, talker, createTime, imgPath, reserved, lvbuffer, transContent, flag, bizClientMsgId, bizChatId, bizChatUserId, msgSeq, historyId) " +
            "VALUES (" + msgId + ", " + type + ", 3, 1, '" + content.replace(/'/g, "''") + "', '" + toUser + "', " + createTime + ", '', 0, NULL, '', 0, '', 0, '', 0, 0)";
        var r = writeSQL(db, sql);
        if (r.success) {
            var verify = execSQL(db, "SELECT msgId, content, talker, createTime FROM message WHERE msgId=" + msgId);
            return {success: true, msgId: msgId, toUser: toUser, content: content, db_verified: verify.count > 0,
                note: "Written to local DB. For real network send, WeChat 8.0.56 network class name needed."};
        }
        return {success: false, error: r.error};
    },

    massMessage: function(targets, content) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        var results = [];
        var successCount = 0;
        (targets || []).forEach(function(toUser) {
            var msgId = Date.now() + Math.floor(Math.random() * 10000);
            var createTime = Date.now();
            var sql = "INSERT INTO message (msgId, type, status, isSend, content, talker, createTime, imgPath, reserved, lvbuffer, transContent, flag, bizClientMsgId, bizChatId, bizChatUserId, msgSeq, historyId) " +
                "VALUES (" + msgId + ", 1, 3, 1, '" + content.replace(/'/g, "''") + "', '" + toUser + "', " + createTime + ", '', 0, NULL, '', 0, '', 0, '', 0, 0)";
            var r = writeSQL(db, sql);
            if (r.success) { successCount++; results.push({toUser: toUser, msgId: msgId, success: true}); }
            else { results.push({toUser: toUser, success: false, error: r.error}); }
        });
        return {total: targets.length, success: successCount, results: results};
    },

    // ===== 群组 =====
    getGroups: function(limit) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available', rows: [], count: 0};
        limit = parseInt(limit) || 50;
        // 先查chatroom表的列名
        var cols = execSQL(db, "PRAGMA table_info(chatroom)");
        var colNames = cols.rows.map(function(r) { return r.name; });
        var selectCols = ['chatroomname'];
        if (colNames.indexOf('memberCount') > -1) selectCols.push('memberCount');
        if (colNames.indexOf('roomowner') > -1) selectCols.push('roomowner');
        if (colNames.indexOf('announcement') > -1) selectCols.push('announcement');
        if (colNames.indexOf('selfDisplayName') > -1) selectCols.push('selfDisplayName');
        if (colNames.indexOf('memberlist') > -1) selectCols.push('memberlist');
        if (colNames.indexOf('NickName') > -1) selectCols.push('NickName');
        return execSQL(db, "SELECT " + selectCols.join(', ') + " FROM chatroom ORDER BY rowid DESC LIMIT " + limit);
    },

    getGroupCount: function() {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        return execSQL(db, "SELECT COUNT(*) as total FROM chatroom");
    },

    getGroupDetail: function(chatroomId) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        return execSQL(db, "SELECT * FROM chatroom WHERE chatroomname='" + chatroomId + "' LIMIT 1");
    },

    getGroupMembers: function(chatroomId) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        var group = execSQL(db, "SELECT memberlist, roomowner, chatroomnotice, selfDisplayName FROM chatroom WHERE chatroomname='" + chatroomId + "'");
        if (!group.rows[0]) return {error: 'Group not found', rows: [], count: 0};
        var g = group.rows[0];
        var members = (g.memberlist || '').split(';').filter(function(m) { return m.trim(); });
        return {
            chatroomId: chatroomId,
            owner: g.roomowner,
            announcement: g.chatroomnotice,
            selfDisplayName: g.selfDisplayName,
            memberCount: members.length,
            members: members.slice(0, 100),
            rows: members.slice(0, 100).map(function(m) { return {wxid: m}; }),
            count: members.length
        };
    },

    setGroupAnnouncement: function(chatroomId, announcement) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        var sql = "UPDATE chatroom SET chatroomnotice='" + announcement.replace(/'/g, "''") + "' WHERE chatroomname='" + chatroomId + "'";
        return writeSQL(db, sql);
    },

    setGroupNickname: function(chatroomId, nickname) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        var sql = "UPDATE chatroom SET selfDisplayName='" + nickname.replace(/'/g, "''") + "' WHERE chatroomname='" + chatroomId + "'";
        return writeSQL(db, sql);
    },

    // ===== 朋友圈 =====
    getSnsDbInfo: function() {
        initAllDBs(); // 重新尝试获取DB
        return {
            sns: {available: !!_dbs['sns'], path: 'SnsMicroMsg.db'},
            sns_star: {available: !!_dbs['sns_star'], path: 'sns_star_info.db'}
        };
    },

    getMoments: function(limit) {
        var db = _dbs['sns'] || _dbs['sns_star'];
        if (!db) {
            initAllDBs();
            db = _dbs['sns'] || _dbs['sns_star'];
        }
        if (!db) return {error: 'SNS DB not loaded. Need to open WeChat moments first.', rows: [], count: 0};
        limit = parseInt(limit) || 20;
        // 尝试不同的表名
        var tables = ['SnsInfo', 'StarSnsInfo', 'sns_info'];
        for (var i = 0; i < tables.length; i++) {
            var r = execSQL(db, "SELECT * FROM " + tables[i] + " ORDER BY createTime DESC LIMIT " + limit);
            if (!r.error) return r;
        }
        return {error: 'No SNS table found', rows: [], count: 0};
    },

    postMoment: function(content, imgPaths) {
        var db = _dbs['sns'] || _dbs['sns_star'];
        if (!db) {
            initAllDBs();
            db = _dbs['sns'] || _dbs['sns_star'];
        }
        if (!db) return {error: 'SNS DB not loaded. Open WeChat moments first.', success: false};
        var snsId = Date.now();
        var createTime = Math.floor(Date.now() / 1000);
        // 尝试写入StarSnsInfo
        var sql = "INSERT INTO StarSnsInfo (snsId, userName, createTime, content, localFlag, type, sourceType) " +
            "VALUES (" + snsId + ", 'wxid_5g37snchpv8e22', " + createTime + ", '" + content.replace(/'/g, "''") + "', 1, 1, 0)";
        var r = writeSQL(db, sql);
        if (r.success) return {success: true, snsId: snsId, content: content, note: 'Written to local SNS DB.'};
        // 尝试SnsInfo
        sql = "INSERT INTO SnsInfo (snsId, userName, createTime, content, localFlag, type) " +
            "VALUES (" + snsId + ", 'wxid_5g37snchpv8e22', " + createTime + ", '" + content.replace(/'/g, "''") + "', 1, 1)";
        r = writeSQL(db, sql);
        if (r.success) return {success: true, snsId: snsId, content: content, note: 'Written to SnsInfo.'};
        return {success: false, error: r.error};
    },

    // ===== 视频号 =====
    getFinderInfo: function() {
        var db = getDB('finder');
        if (!db) return {error: 'Finder DB not available'};
        var tables = execSQL(db, "SELECT name FROM sqlite_master WHERE type='table'");
        var result = {tables: tables.rows.map(function(r) { return r.name; })};
        // 读取FinderFeedItem
        var feeds = execSQL(db, "SELECT * FROM FinderFeedItem LIMIT 5");
        if (!feeds.error) result.feeds = feeds;
        return result;
    },

    getFinderContacts: function(limit) {
        var db = getDB('finder');
        if (!db) return {error: 'Finder DB not available', rows: [], count: 0};
        limit = parseInt(limit) || 20;
        return execSQL(db, "SELECT * FROM FinderMsgContactStorage LIMIT " + limit);
    },

    getFinderAccounts: function() {
        var db = getDB('finder3');
        if (!db) return {error: 'FinderAccounts DB not available'};
        var tables = execSQL(db, "SELECT name FROM sqlite_master WHERE type='table'");
        var result = {tables: tables.rows.map(function(r) { return r.name; })};
        var accounts = execSQL(db, "SELECT username, nickname, signature, avatarUrl FROM FinderAccount LIMIT 10");
        if (!accounts.error) result.accounts = accounts;
        return result;
    },

    // ===== 收藏 =====
    getFavorites: function(limit) {
        var db = getDB('fts5') || getDB('favorite');
        if (!db) return {error: 'Favorite DB not available', rows: [], count: 0};
        limit = parseInt(limit) || 20;
        // 尝试不同表名
        var tables = ['FTS5MetaFavorite', 'favorite_item', 'FavoriteItem'];
        for (var i = 0; i < tables.length; i++) {
            var r = execSQL(db, "SELECT * FROM " + tables[i] + " LIMIT " + limit);
            if (!r.error) return r;
        }
        // 列出所有表
        var allTables = execSQL(db, "SELECT name FROM sqlite_master WHERE type='table'");
        return {error: 'No favorite table found', available_tables: allTables.rows.map(function(r){return r.name;}), rows: [], count: 0};
    },

    // ===== 钱包/支付 =====
    getWalletInfo: function() {
        var db = getDB('wallet');
        if (!db) return {error: 'Wallet DB not available'};
        var tables = execSQL(db, "SELECT name FROM sqlite_master WHERE type='table'");
        return {tables: tables.rows.map(function(r) { return r.name; })};
    },

    getWalletLedger: function(limit) {
        var db = getDB('wallet');
        if (!db) return {error: 'Wallet DB not available', rows: [], count: 0};
        limit = parseInt(limit) || 20;
        var r = execSQL(db, "SELECT * FROM WalletLedgerRecord ORDER BY rowid DESC LIMIT " + limit);
        return r;
    },

    getLuckyMoney: function(limit) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available', rows: [], count: 0};
        limit = parseInt(limit) || 20;
        return execSQL(db, "SELECT * FROM WalletLuckyMoney ORDER BY rowid DESC LIMIT " + limit);
    },

    // ===== 媒体 =====
    getImageCount: function() {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        return execSQL(db, "SELECT COUNT(*) as total FROM ImgInfo2");
    },

    getVideoList: function(limit) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available', rows: [], count: 0};
        limit = parseInt(limit) || 10;
        return execSQL(db, "SELECT * FROM videoinfo2 ORDER BY rowid DESC LIMIT " + limit);
    },

    getFileList: function(limit) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available', rows: [], count: 0};
        limit = parseInt(limit) || 10;
        return execSQL(db, "SELECT * FROM FileMsgInfo ORDER BY rowid DESC LIMIT " + limit);
    },

    // ===== 小程序 =====
    getAppBrandList: function() {
        var db = getDB('appbrand');
        if (!db) return {error: 'AppBrand DB not available'};
        var tables = execSQL(db, "SELECT name FROM sqlite_master WHERE type='table'");
        var result = {tables: tables.rows.map(function(r) { return r.name; })};
        var apps = execSQL(db, "SELECT * FROM AppBrandCommonUseApp ORDER BY useCount DESC LIMIT 10");
        if (!apps.error) result.common_apps = apps;
        return result;
    },

    // ===== 搜索 =====
    globalSearch: function(keyword) {
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        var contacts = execSQL(db,
            "SELECT username, nickName, conRemark FROM rcontact " +
            "WHERE (nickName LIKE '%" + keyword + "%' OR conRemark LIKE '%" + keyword + "%') AND type IN (3,4) LIMIT 10"
        );
        var groups = execSQL(db,
            "SELECT chatroomname FROM chatroom WHERE chatroomname LIKE '%" + keyword + "%' LIMIT 5"
        );
        var messages = execSQL(db,
            "SELECT msgId, content, talker, createTime FROM message WHERE content LIKE '%" + keyword + "%' ORDER BY createTime DESC LIMIT 10"
        );
        return {contacts: contacts, groups: groups, messages: messages};
    },

    // ===== 原始SQL（调试用）=====
    rawQuery: function(dbName, sql) {
        var db = getDB(dbName);
        if (!db) return {error: 'DB ' + dbName + ' not available', rows: [], count: 0};
        return execSQL(db, sql);
    },

    rawWrite: function(dbName, sql) {
        var db = getDB(dbName);
        if (!db) return {error: 'DB ' + dbName + ' not available'};
        return writeSQL(db, sql);
    },

    getTableInfo: function(dbName, tableName) {
        var db = getDB(dbName);
        if (!db) return {error: 'DB ' + dbName + ' not available'};
        return execSQL(db, "PRAGMA table_info(" + tableName + ")");
    },

    listTables: function(dbName) {
        var db = getDB(dbName);
        if (!db) return {error: 'DB ' + dbName + ' not available'};
        return execSQL(db, "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name");
    },

    // ===== 添加好友 =====
    addFriend: function(wxid, message) {
        // 写入AddContactScene表（如果存在）
        var db = getDB('main');
        if (!db) return {error: 'main DB not available'};
        message = message || '你好，我是游条姐';
        // 检查是否已是好友
        var existing = execSQL(db, "SELECT username, type FROM rcontact WHERE username='" + wxid + "'");
        if (existing.rows[0] && existing.rows[0].type === '3') {
            return {success: false, note: 'Already a friend', wxid: wxid};
        }
        // 记录添加请求（实际网络发送需要真实类名）
        return {
            success: true,
            wxid: wxid,
            message: message,
            note: 'Add friend request prepared. Network send requires WeChat 8.0.56 real class name.',
            existing: existing.rows[0] || null
        };
    },

    // ===== 截图 =====
    takeScreenshot: function(savePath) {
        try {
            var Runtime = Java.use('java.lang.Runtime');
            var rt = Runtime.getRuntime();
            savePath = savePath || '/sdcard/workphone_screenshot.png';
            rt.exec(['sh', '-c', 'screencap -p ' + savePath]);
            return {success: true, path: savePath};
        } catch(e) {
            return {error: e.toString()};
        }
    },

    // ===== 导航 =====
    navigate: function(activity) {
        try {
            var Intent = Java.use('android.content.Intent');
            var ctx = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
            var cls;
            var activityMap = {
                'main': 'com.tencent.mm.ui.LauncherUI',
                'moments': 'com.tencent.mm.plugin.sns.ui.SnsTimeLineUI',
                'contacts': 'com.tencent.mm.ui.contact.AddressBookUI',
                'chat': 'com.tencent.mm.ui.chatting.ChattingUI',
                'finder': 'com.tencent.mm.plugin.finder.ui.FinderUI',
                'wallet': 'com.tencent.mm.plugin.wallet.ui.WalletUI'
            };
            var activityName = activityMap[activity] || activity;
            cls = Java.use(activityName).class;
            var intent = Intent.$new(ctx, cls);
            intent.addFlags(0x10000000); // FLAG_ACTIVITY_NEW_TASK
            ctx.startActivity(intent);
            return {success: true, activity: activityName};
        } catch(e) {
            return {error: e.toString()};
        }
    }
};
