// 微信工作手机 SDK v7 - 全量Frida RPC接口
// 基于微信8.0.56真实DB结构开发
// 账号：游条姐-游戏教学辅助看我朋友圈 (wxid_5g37snchpv8e22)

'use strict';

var _db = null;
var _snsDb = null;
var _walletDb = null;
var _finderDb = null;
var _favoriteDb = null;
var _dbPath = null;

// ==================== DB初始化 ====================
function initDB() {
    if (_db) return _db;
    try {
        Java.choose('com.tencent.wcdb.database.SQLiteDatabase', {
            onMatch: function(db) {
                try {
                    var path = db.getPath();
                    if (path && path.indexOf('EnMicroMsg.db') > -1 && path.indexOf('wal') === -1) {
                        _db = db;
                        _dbPath = path;
                    }
                    if (path && path.indexOf('sns_star_info') > -1) _snsDb = db;
                    if (path && path.indexOf('WalletCoreDB') > -1) _walletDb = db;
                    if (path && path.indexOf('Finder') > -1 && path.indexOf('MM') > -1) _finderDb = db;
                    if (path && path.indexOf('FTS5Index') > -1) _favoriteDb = db;
                } catch(e) {}
            },
            onComplete: function() {}
        });
    } catch(e) {}
    return _db;
}

function execSQL(db, sql, args) {
    try {
        if (!db) return {error: 'DB not initialized'};
        var cursor;
        if (args && args.length > 0) {
            var strArgs = args.map(function(a) { return a ? a.toString() : null; });
            var jArgs = Java.array('java.lang.String', strArgs);
            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()};
    }
}

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

// ==================== RPC接口定义 ====================
rpc.exports = {

    // ===== 系统 =====
    ping: function() {
        return {status: 'ok', version: 'v7', timestamp: Date.now()};
    },

    getSystemInfo: function() {
        initDB();
        return {
            db_path: _dbPath,
            has_main_db: !!_db,
            has_sns_db: !!_snsDb,
            has_wallet_db: !!_walletDb,
            has_finder_db: !!_finderDb,
            has_favorite_db: !!_favoriteDb,
            frida_version: Frida.version,
            timestamp: Date.now()
        };
    },

    // ===== 账号 =====
    getAccountInfo: function() {
        initDB();
        var r = execSQL(_db, "SELECT value FROM userinfo WHERE id IN (2,4,6,42,43,44,62,66,67) ORDER BY id");
        var info = 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");
        return {
            wxid: info.rows && info.rows[0] ? info.rows[0].value : null,
            nickname: nick.rows && nick.rows[0] ? nick.rows[0].value : null,
            avatar: avatar.rows && avatar.rows[0] ? avatar.rows[0].value : null,
            phone: phone.rows && phone.rows[0] ? phone.rows[0].value : null,
            raw: r
        };
    },

    // ===== 联系人 =====
    getContacts: function(limit, offset) {
        initDB();
        limit = limit || 100;
        offset = offset || 0;
        return execSQL(_db,
            "SELECT username, alias, conRemark, nickName, type, contactLabelIds, imgFlag, verifyFlag " +
            "FROM rcontact WHERE type=3 AND verifyFlag=0 " +
            "ORDER BY rowid LIMIT " + limit + " OFFSET " + offset
        );
    },

    getContactCount: function() {
        initDB();
        return execSQL(_db, "SELECT COUNT(*) as total FROM rcontact WHERE type=3 AND verifyFlag=0");
    },

    searchContact: function(keyword) {
        initDB();
        return execSQL(_db,
            "SELECT username, alias, conRemark, nickName, type, contactLabelIds " +
            "FROM rcontact WHERE (nickName LIKE '%" + keyword + "%' OR conRemark LIKE '%" + keyword + "%' OR alias LIKE '%" + keyword + "%') " +
            "AND type NOT IN (0,4) LIMIT 50"
        );
    },

    getContactDetail: function(wxid) {
        initDB();
        return execSQL(_db,
            "SELECT * FROM rcontact WHERE username='" + wxid + "' LIMIT 1"
        );
    },

    // ===== 消息 =====
    getMessages: function(talker, limit) {
        initDB();
        limit = limit || 50;
        return execSQL(_db,
            "SELECT msgId, type, isSend, createTime, talker, content, imgPath " +
            "FROM message WHERE talker='" + talker + "' " +
            "ORDER BY createTime DESC LIMIT " + limit
        );
    },

    getRecentMessages: function(hours) {
        initDB();
        hours = hours || 24;
        var since = Date.now() - hours * 3600 * 1000;
        return execSQL(_db,
            "SELECT msgId, type, isSend, createTime, talker, content " +
            "FROM message WHERE createTime > " + since +
            " ORDER BY createTime DESC LIMIT 200"
        );
    },

    sendMessage: function(toUser, content) {
        initDB();
        if (!_db) return {error: 'DB not available'};
        var msgId = Date.now();
        var createTime = Date.now();
        var sql = "INSERT INTO message (msgId, msgSvrId, type, status, isSend, isShowTimer, createTime, talker, content, imgPath, reserved, lvbuffer, transContent, transBrandWording, talkerId, bizClientMsgId, bizChatId, bizChatUserId, msgSeq, flag) VALUES (" +
            msgId + ", 0, 1, 2, 1, 0, " + createTime + ", '" + toUser + "', '" + content.replace(/'/g, "''") + "', '', '', '', '', '', 0, '', '', '', 0, 0)";
        var result = writeDB(_db, sql);
        if (result.success) {
            // 验证写入
            var verify = execSQL(_db, "SELECT msgId, content, talker, createTime FROM message WHERE msgId=" + msgId);
            return {success: true, msgId: msgId, toUser: toUser, content: content, verify: verify};
        }
        return result;
    },

    // ===== 会话 =====
    getConversations: function(limit) {
        initDB();
        limit = limit || 30;
        return execSQL(_db,
            "SELECT username, unReadCount, lastMsg, lastMsgCreateTime, isSend, msgStatus " +
            "FROM conversation ORDER BY lastMsgCreateTime DESC LIMIT " + limit
        );
    },

    // ===== 群组 =====
    getGroups: function(limit) {
        initDB();
        limit = limit || 50;
        return execSQL(_db,
            "SELECT chatroomname, memberlist, roomowner, announcement, selfDisplayName, memberCount " +
            "FROM chatroom ORDER BY rowid DESC LIMIT " + limit
        );
    },

    getGroupCount: function() {
        initDB();
        return execSQL(_db, "SELECT COUNT(*) as total FROM chatroom");
    },

    getGroupDetail: function(chatroomId) {
        initDB();
        return execSQL(_db, "SELECT * FROM chatroom WHERE chatroomname='" + chatroomId + "' LIMIT 1");
    },

    getGroupMembers: function(chatroomId) {
        initDB();
        var group = execSQL(_db, "SELECT memberlist FROM chatroom WHERE chatroomname='" + chatroomId + "'");
        if (group.rows && group.rows[0]) {
            var memberList = group.rows[0].memberlist || '';
            var members = memberList.split(';').filter(function(m) { return m.trim(); });
            return {chatroomId: chatroomId, members: members, count: members.length};
        }
        return {error: 'Group not found'};
    },

    getGroupAnnouncement: function(chatroomId) {
        initDB();
        return execSQL(_db, "SELECT chatroomname, announcement, selfDisplayName FROM chatroom WHERE chatroomname='" + chatroomId + "'");
    },

    setGroupRemark: function(chatroomId, remark) {
        initDB();
        var sql = "UPDATE chatroom SET selfDisplayName='" + remark.replace(/'/g, "''") + "' WHERE chatroomname='" + chatroomId + "'";
        return writeDB(_db, sql);
    },

    // ===== 标签 =====
    getLabels: function() {
        initDB();
        // 从rcontact的contactLabelIds字段提取所有标签ID
        var r = execSQL(_db, "SELECT DISTINCT contactLabelIds FROM rcontact WHERE contactLabelIds IS NOT NULL AND contactLabelIds != '' LIMIT 500");
        var labelSet = {};
        if (r.rows) {
            r.rows.forEach(function(row) {
                var ids = (row.contactLabelIds || '').split(',');
                ids.forEach(function(id) { if (id.trim()) labelSet[id.trim()] = true; });
            });
        }
        return {label_ids: Object.keys(labelSet), count: Object.keys(labelSet).length};
    },

    getContactsByLabel: function(labelId) {
        initDB();
        return execSQL(_db,
            "SELECT username, nickName, conRemark, contactLabelIds FROM rcontact " +
            "WHERE contactLabelIds LIKE '%" + labelId + "%' AND type=3 LIMIT 100"
        );
    },

    // ===== 朋友圈 =====
    getMoments: function(limit) {
        if (!_snsDb) initDB();
        limit = limit || 20;
        if (!_snsDb) return {error: 'SNS DB not available'};
        return execSQL(_snsDb,
            "SELECT snsId, userName, createTime, content, type, localFlag, likeFlag " +
            "FROM StarSnsInfo ORDER BY createTime DESC LIMIT " + limit
        );
    },

    getMomentCount: function() {
        if (!_snsDb) initDB();
        if (!_snsDb) return {error: 'SNS DB not available'};
        return execSQL(_snsDb, "SELECT COUNT(*) as total FROM StarSnsInfo");
    },

    postMoment: function(content) {
        if (!_snsDb) initDB();
        if (!_snsDb) return {error: 'SNS DB not available'};
        var snsId = Date.now();
        var createTime = Math.floor(Date.now() / 1000);
        var sql = "INSERT INTO StarSnsInfo (snsId, userName, localFlag, createTime, content, type, localPrivate, likeFlag, pravited, stringSeq, withTa, withTaHasOther, sourceType, subType, serverExtFlag) VALUES (" +
            snsId + ", 'wxid_5g37snchpv8e22', 1, " + createTime + ", '" + content.replace(/'/g, "''") + "', 1, 0, 0, 0, '', 0, 0, 0, 0, 0)";
        var result = writeDB(_snsDb, sql);
        if (result.success) {
            var verify = execSQL(_snsDb, "SELECT snsId, content, createTime FROM StarSnsInfo WHERE snsId=" + snsId);
            return {success: true, snsId: snsId, content: content, verify: verify};
        }
        return result;
    },

    // ===== 视频号 =====
    getFinderInfo: function() {
        if (!_finderDb) initDB();
        if (!_finderDb) return {error: 'Finder DB not available'};
        var tables = execSQL(_finderDb, "SELECT name FROM sqlite_master WHERE type='table'");
        return {tables: tables, has_finder_db: !!_finderDb};
    },

    getFinderContacts: function() {
        if (!_finderDb) initDB();
        if (!_finderDb) return {error: 'Finder DB not available'};
        return execSQL(_finderDb, "SELECT * FROM FinderMsgContactStorage LIMIT 20");
    },

    getFinderMedia: function() {
        if (!_finderDb) initDB();
        if (!_finderDb) return {error: 'Finder DB not available'};
        return execSQL(_finderDb, "SELECT * FROM FinderMediaCacheInfoV4 LIMIT 20");
    },

    // ===== 收藏 =====
    getFavorites: function(limit) {
        if (!_favoriteDb) initDB();
        limit = limit || 20;
        if (!_favoriteDb) {
            // 尝试从主DB查
            return execSQL(_db, "SELECT * FROM FavItems LIMIT " + limit);
        }
        return execSQL(_favoriteDb, "SELECT * FROM FTS5MetaFavorite LIMIT " + limit);
    },

    // ===== 钱包/红包 =====
    getWalletInfo: function() {
        if (!_walletDb) initDB();
        if (!_walletDb) return {error: 'Wallet DB not available'};
        var tables = execSQL(_walletDb, "SELECT name FROM sqlite_master WHERE type='table'");
        return {tables: tables, has_wallet_db: !!_walletDb};
    },

    getWalletLedger: function(limit) {
        if (!_walletDb) initDB();
        limit = limit || 20;
        if (!_walletDb) return {error: 'Wallet DB not available'};
        return execSQL(_walletDb,
            "SELECT transferId, talker, msgTime, msgDate, tradeUser, tradeType, tradeAmount " +
            "FROM WalletLedgerRecord ORDER BY msgTime DESC LIMIT " + limit
        );
    },

    getLuckyMoney: function(limit) {
        initDB();
        limit = limit || 20;
        return execSQL(_db,
            "SELECT * FROM WalletLuckyMoney ORDER BY rowid DESC LIMIT " + limit
        );
    },

    getWalletBalance: function() {
        if (!_walletDb) initDB();
        if (!_walletDb) return {error: 'Wallet DB not available'};
        // 查询钱包余额相关表
        var tables = execSQL(_walletDb, "SELECT name FROM sqlite_master WHERE type='table'");
        var results = {};
        if (tables.rows) {
            tables.rows.forEach(function(t) {
                try {
                    var r = execSQL(_walletDb, "SELECT * FROM " + t.name + " LIMIT 5");
                    results[t.name] = r;
                } catch(e) {}
            });
        }
        return results;
    },

    // ===== 图片/文件 =====
    getImageList: function(limit) {
        initDB();
        limit = limit || 20;
        return execSQL(_db, "SELECT * FROM ImgInfo2 ORDER BY rowid DESC LIMIT " + limit);
    },

    getImageCount: function() {
        initDB();
        return execSQL(_db, "SELECT COUNT(*) as total FROM ImgInfo2");
    },

    getVideoList: function(limit) {
        initDB();
        limit = limit || 20;
        return execSQL(_db, "SELECT * FROM videoinfo2 ORDER BY rowid DESC LIMIT " + limit);
    },

    getVideoCount: function() {
        initDB();
        return execSQL(_db, "SELECT COUNT(*) as total FROM videoinfo2");
    },

    getFileList: function(limit) {
        initDB();
        limit = limit || 20;
        return execSQL(_db, "SELECT * FROM FileMsgInfo ORDER BY rowid DESC LIMIT " + limit);
    },

    // ===== 小程序 =====
    getAppBrandList: function() {
        initDB();
        return execSQL(_db, "SELECT * FROM AppBrandInfo LIMIT 20");
    },

    // ===== 搜索 =====
    globalSearch: function(keyword) {
        initDB();
        var contacts = execSQL(_db,
            "SELECT username, nickName, conRemark FROM rcontact WHERE nickName LIKE '%" + keyword + "%' OR conRemark LIKE '%" + keyword + "%' LIMIT 10"
        );
        var messages = execSQL(_db,
            "SELECT talker, content, createTime FROM message WHERE content LIKE '%" + keyword + "%' ORDER BY createTime DESC LIMIT 10"
        );
        var groups = execSQL(_db,
            "SELECT chatroomname FROM chatroom WHERE chatroomname LIKE '%" + keyword + "%' LIMIT 10"
        );
        return {contacts: contacts, messages: messages, groups: groups};
    },

    // ===== 群发消息 =====
    massMessage: function(targets, content) {
        initDB();
        if (!_db) return {error: 'DB not available'};
        if (!targets || !targets.length) return {error: 'No targets'};
        var results = [];
        targets.forEach(function(toUser) {
            var msgId = Date.now() + Math.floor(Math.random() * 1000);
            var createTime = Date.now();
            var sql = "INSERT INTO message (msgId, msgSvrId, type, status, isSend, isShowTimer, createTime, talker, content, imgPath, reserved, lvbuffer, transContent, transBrandWording, talkerId, bizClientMsgId, bizChatId, bizChatUserId, msgSeq, flag) VALUES (" +
                msgId + ", 0, 1, 2, 1, 0, " + createTime + ", '" + toUser + "', '" + content.replace(/'/g, "''") + "', '', '', '', '', '', 0, '', '', '', 0, 0)";
            var r = writeDB(_db, sql);
            results.push({toUser: toUser, msgId: msgId, success: r.success || false, error: r.error});
        });
        return {results: results, total: targets.length, success: results.filter(function(r) { return r.success; }).length};
    },

    // ===== 原始SQL（调试用）=====
    rawQuery: function(dbName, sql) {
        initDB();
        var db;
        if (dbName === 'main') db = _db;
        else if (dbName === 'sns') db = _snsDb;
        else if (dbName === 'wallet') db = _walletDb;
        else if (dbName === 'finder') db = _finderDb;
        else if (dbName === 'favorite') db = _favoriteDb;
        else db = _db;
        return execSQL(db, sql);
    },

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

    // ===== DB信息 =====
    getDbInfo: function() {
        initDB();
        return {
            main: _dbPath,
            sns: _snsDb ? _snsDb.getPath() : null,
            wallet: _walletDb ? _walletDb.getPath() : null,
            finder: _finderDb ? _finderDb.getPath() : null,
            favorite: _favoriteDb ? _favoriteDb.getPath() : null
        };
    },

    // ===== 联系人完整统计 =====
    getContactStats: function() {
        initDB();
        var total = execSQL(_db, "SELECT COUNT(*) as total FROM rcontact");
        var friends = execSQL(_db, "SELECT COUNT(*) as total FROM rcontact WHERE type=3 AND verifyFlag=0");
        var groups = execSQL(_db, "SELECT COUNT(*) as total FROM chatroom");
        var msgs = execSQL(_db, "SELECT COUNT(*) as total FROM message");
        var imgs = execSQL(_db, "SELECT COUNT(*) as total FROM ImgInfo2");
        var videos = execSQL(_db, "SELECT COUNT(*) as total FROM videoinfo2");
        return {
            total_contacts: total.rows[0] ? total.rows[0].total : 0,
            friends: friends.rows[0] ? friends.rows[0].total : 0,
            groups: groups.rows[0] ? groups.rows[0].total : 0,
            messages: msgs.rows[0] ? msgs.rows[0].total : 0,
            images: imgs.rows[0] ? imgs.rows[0].total : 0,
            videos: videos.rows[0] ? videos.rows[0].total : 0
        };
    }
};

console.log('[*] WeChat SDK v7 loaded. All interfaces ready.');
