-- ============================================
-- 压力测试数据生成脚本
-- 用于生成大量测试数据以进行性能测试
-- ============================================

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- 清理测试数据（可选，谨慎使用）
-- DELETE FROM wallet_ledger WHERE user_id > 1000;
-- DELETE FROM rental_orders WHERE id > 100;
-- DELETE FROM rental_listings WHERE id > 100;
-- DELETE FROM game_accounts WHERE id > 100;
-- DELETE FROM users WHERE id > 1000;

-- ============================================
-- 1. 批量生成用户数据（10000个用户）
-- ============================================
DROP PROCEDURE IF EXISTS generate_users;
DELIMITER $$
CREATE PROCEDURE generate_users(IN batch_size INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    DECLARE phone_num VARCHAR(32);
    DECLARE nick VARCHAR(64);

    WHILE i <= batch_size DO
        SET phone_num = CONCAT('138', LPAD(i, 8, '0'));
        SET nick = CONCAT('测试用户', i);

        INSERT INTO users (
            phone, nickname, realname_status, risk_status,
            credit_score, status, created_at
        ) VALUES (
            phone_num, nick,
            CASE WHEN i % 10 = 0 THEN 'unverified' ELSE 'verified' END,
            CASE WHEN i % 100 = 0 THEN 'frozen' ELSE 'normal' END,
            80 + (i % 20),
            'active',
            DATE_SUB(NOW(), INTERVAL (i % 365) DAY)
        ) ON DUPLICATE KEY UPDATE id=id;

        -- 为已实名用户创建实名记录
        IF i % 10 != 0 THEN
            INSERT INTO user_realname (
                user_id, provider, status, masked_name, masked_id_no, verified_at
            ) VALUES (
                LAST_INSERT_ID(), 'mock', 'success',
                CONCAT('张*', CHAR(65 + (i % 26))),
                CONCAT('3301**********', LPAD(i % 10000, 4, '0')),
                DATE_SUB(NOW(), INTERVAL (i % 300) DAY)
            ) ON DUPLICATE KEY UPDATE user_id=user_id;
        END IF;

        -- 为用户创建钱包
        INSERT INTO wallet_accounts (user_id, available_balance_cent, frozen_balance_cent, status)
        VALUES (
            LAST_INSERT_ID(),
            (i % 10) * 10000,
            (i % 5) * 5000,
            'active'
        ) ON DUPLICATE KEY UPDATE user_id=user_id;

        SET i = i + 1;

        -- 每1000条提交一次
        IF i % 1000 = 0 THEN
            COMMIT;
        END IF;
    END WHILE;

    COMMIT;
END$$
DELIMITER ;

-- ============================================
-- 2. 批量生成游戏账号和商品（50000个商品）
-- ============================================
DROP PROCEDURE IF EXISTS generate_listings;
DELIMITER $$
CREATE PROCEDURE generate_listings(IN batch_size INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    DECLARE user_id_val BIGINT;
    DECLARE account_id_val BIGINT;
    DECLARE price_val BIGINT;
    DECLARE deposit_val BIGINT;
    DECLARE verified_user_min BIGINT;
    DECLARE verified_user_max BIGINT;
    DECLARE user_pick BIGINT;

    SELECT MIN(id), MAX(id)
    INTO verified_user_min, verified_user_max
    FROM users
    WHERE realname_status = 'verified';

    IF verified_user_min IS NULL THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的已实名用户';
    END IF;

    WHILE i <= batch_size DO
        -- 近似随机选择一个用户作为号主，避免 ORDER BY RAND() 全表排序。
        SET user_id_val = NULL;
        SET user_pick = verified_user_min + FLOOR(RAND() * (verified_user_max - verified_user_min + 1));
        SELECT id INTO user_id_val FROM users
        WHERE id >= user_pick AND realname_status = 'verified'
        ORDER BY id LIMIT 1;

        IF user_id_val IS NULL THEN
            SELECT id INTO user_id_val FROM users
            WHERE realname_status = 'verified'
            ORDER BY id LIMIT 1;
        END IF;

        -- 创建游戏账号
        INSERT INTO game_accounts (
            owner_id, game_name, server_region, login_platform,
            title, description, rank_level, haf_coin_amount, status
        ) VALUES (
            user_id_val,
            'delta_force',
            CASE (i % 4)
                WHEN 0 THEN '亚服'
                WHEN 1 THEN '美服'
                WHEN 2 THEN '欧服'
                ELSE '国服'
            END,
            CASE (i % 3)
                WHEN 0 THEN 'Steam'
                WHEN 1 THEN 'Epic'
                ELSE 'WeGame'
            END,
            CONCAT('账号', i, ' 高分段'),
            CONCAT('这是一个测试账号，编号', i),
            CASE (i % 5)
                WHEN 0 THEN '青铜'
                WHEN 1 THEN '白银'
                WHEN 2 THEN '黄金'
                WHEN 3 THEN '铂金'
                ELSE '钻石'
            END,
            (i % 100) * 10000,
            'published'
        );

        SET account_id_val = LAST_INSERT_ID();

        -- 创建租号商品
        SET price_val = 500 + (i % 20) * 50;
        SET deposit_val = 10000 + (i % 10) * 5000;

        INSERT INTO rental_listings (
            listing_no, account_id, owner_id, price_cent, deposit_amount_cent,
            in_transaction, status, review_status, published_at
        ) VALUES (
            CONCAT(
                DATE_FORMAT(DATE_SUB(NOW(), INTERVAL (i % 90) DAY), '%Y%m%d'),
                LPAD(FLOOR((i - 1) / 90) + 1, 4, '0')
            ),
            account_id_val,
            user_id_val,
            price_val,
            deposit_val,
            CASE WHEN i % 10 = 0 THEN 1 ELSE 0 END,
            CASE
                WHEN i % 20 = 0 THEN 'offline'
                WHEN i % 15 = 0 THEN 'draft'
                ELSE 'published'
            END,
            CASE
                WHEN i % 15 = 0 THEN 'pending'
                WHEN i % 30 = 0 THEN 'rejected'
                ELSE 'approved'
            END,
            DATE_SUB(NOW(), INTERVAL (i % 90) DAY)
        );

        SET i = i + 1;

        IF i % 1000 = 0 THEN
            COMMIT;
        END IF;
    END WHILE;

    INSERT INTO listing_no_sequences (biz_date, next_seq)
    SELECT LEFT(listing_no, 8), MAX(CAST(SUBSTRING(listing_no, 9) AS UNSIGNED))
    FROM rental_listings
    GROUP BY LEFT(listing_no, 8)
    ON DUPLICATE KEY UPDATE next_seq = GREATEST(next_seq, VALUES(next_seq));

    COMMIT;
END$$
DELIMITER ;

-- ============================================
-- 3. 批量生成订单数据（30000个订单）
-- ============================================
DROP PROCEDURE IF EXISTS generate_orders;
DELIMITER $$
CREATE PROCEDURE generate_orders(IN batch_size INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    DECLARE listing_id_val BIGINT;
    DECLARE account_id_val BIGINT;
    DECLARE owner_id_val BIGINT;
    DECLARE renter_id_val BIGINT;
    DECLARE order_no_val VARCHAR(64);
    DECLARE rent_amount_val BIGINT;
    DECLARE deposit_val BIGINT;
    DECLARE listing_min BIGINT;
    DECLARE listing_max BIGINT;
    DECLARE listing_pick BIGINT;
    DECLARE verified_user_min BIGINT;
    DECLARE verified_user_max BIGINT;
    DECLARE user_pick BIGINT;

    SELECT MIN(id), MAX(id)
    INTO listing_min, listing_max
    FROM rental_listings
    WHERE status IN ('published', 'active') AND review_status = 'approved';

    SELECT MIN(id), MAX(id)
    INTO verified_user_min, verified_user_max
    FROM users
    WHERE realname_status = 'verified';

    IF listing_min IS NULL THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的已上架商品';
    END IF;
    IF verified_user_min IS NULL THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的已实名用户';
    END IF;

    WHILE i <= batch_size DO
        -- 近似随机选择一个上架商品，避免 ORDER BY RAND() 全表排序。
        SET listing_id_val = NULL;
        SET listing_pick = listing_min + FLOOR(RAND() * (listing_max - listing_min + 1));
        SELECT rl.id, rl.account_id, rl.owner_id, rl.price_cent, rl.deposit_amount_cent
        INTO listing_id_val, account_id_val, owner_id_val, rent_amount_val, deposit_val
        FROM rental_listings rl
        WHERE rl.id >= listing_pick
          AND rl.status IN ('published', 'active')
          AND rl.review_status = 'approved'
        ORDER BY rl.id LIMIT 1;

        IF listing_id_val IS NULL THEN
            SELECT rl.id, rl.account_id, rl.owner_id, rl.price_cent, rl.deposit_amount_cent
            INTO listing_id_val, account_id_val, owner_id_val, rent_amount_val, deposit_val
            FROM rental_listings rl
            WHERE rl.status IN ('published', 'active')
              AND rl.review_status = 'approved'
            ORDER BY rl.id LIMIT 1;
        END IF;

        -- 近似随机选择一个租客（不能是号主本人）。
        SET renter_id_val = NULL;
        SET user_pick = verified_user_min + FLOOR(RAND() * (verified_user_max - verified_user_min + 1));
        SELECT id INTO renter_id_val FROM users
        WHERE id >= user_pick AND id != owner_id_val AND realname_status = 'verified'
        ORDER BY id LIMIT 1;

        IF renter_id_val IS NULL THEN
            SELECT id INTO renter_id_val FROM users
            WHERE id != owner_id_val AND realname_status = 'verified'
            ORDER BY id LIMIT 1;
        END IF;

        IF renter_id_val IS NULL THEN
            SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的租客用户';
        END IF;

        SET order_no_val = CONCAT('ORD', DATE_FORMAT(NOW(), '%Y%m%d'), LPAD(i, 8, '0'));
        SET rent_amount_val = rent_amount_val * 24; -- 24小时租金

        INSERT INTO rental_orders (
            order_no, listing_id, account_id, owner_id, renter_id,
            estimated_duration_hours, rent_amount_cent, owner_rent_amount_cent,
            deposit_amount_cent, deposit_original_amount_cent, platform_fee_cent, status, handoff_status,
            settlement_status, rented_at, created_at
        ) VALUES (
            order_no_val,
            listing_id_val,
            account_id_val,
            owner_id_val,
            renter_id_val,
            24,
            rent_amount_val,
            ROUND(rent_amount_val * 0.95), -- 号主实得95%
            deposit_val,
            deposit_val,
            ROUND(rent_amount_val * 0.05), -- 平台5%手续费
            CASE (i % 10)
                WHEN 0 THEN 'pending_payment'
                WHEN 1 THEN 'cancelled'
                WHEN 2 THEN 'closed'
                ELSE 'completed'
            END,
            CASE (i % 10)
                WHEN 0 THEN 'none'
                WHEN 1 THEN 'none'
                WHEN 2 THEN 'owner_delivered'
                ELSE 'owner_received'
            END,
            CASE (i % 10)
                WHEN 0 THEN 'unsettled'
                WHEN 1 THEN 'unsettled'
                ELSE 'settled'
            END,
            DATE_SUB(NOW(), INTERVAL (i % 60) DAY),
            DATE_SUB(NOW(), INTERVAL (i % 60) DAY)
        );

        SET i = i + 1;

        IF i % 1000 = 0 THEN
            COMMIT;
        END IF;
    END WHILE;

    COMMIT;
END$$
DELIMITER ;

-- ============================================
-- 4. 批量生成钱包流水（100000条流水）
-- ============================================
DROP PROCEDURE IF EXISTS generate_wallet_ledger;
DELIMITER $$
CREATE PROCEDURE generate_wallet_ledger(IN batch_size INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    DECLARE user_id_val BIGINT;
    DECLARE order_id_val BIGINT;
    DECLARE ledger_no_val VARCHAR(64);
    DECLARE amount_val BIGINT;
    DECLARE user_min BIGINT;
    DECLARE user_max BIGINT;
    DECLARE order_min BIGINT;
    DECLARE order_max BIGINT;
    DECLARE user_pick BIGINT;
    DECLARE order_pick BIGINT;

    SELECT MIN(id), MAX(id) INTO user_min, user_max FROM users;
    SELECT MIN(id), MAX(id) INTO order_min, order_max FROM rental_orders;

    IF user_min IS NULL THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的用户';
    END IF;

    WHILE i <= batch_size DO
        -- 近似随机选择用户，避免 ORDER BY RAND() 全表排序。
        SET user_id_val = NULL;
        SET user_pick = user_min + FLOOR(RAND() * (user_max - user_min + 1));
        SELECT id INTO user_id_val FROM users
        WHERE id >= user_pick
        ORDER BY id LIMIT 1;

        IF user_id_val IS NULL THEN
            SELECT id INTO user_id_val FROM users ORDER BY id LIMIT 1;
        END IF;

        -- 随机关联订单（50%概率）
        IF RAND() > 0.5 AND order_min IS NOT NULL THEN
            SET order_id_val = NULL;
            SET order_pick = order_min + FLOOR(RAND() * (order_max - order_min + 1));
            SELECT id INTO order_id_val FROM rental_orders
            WHERE id >= order_pick
            ORDER BY id LIMIT 1;

            IF order_id_val IS NULL THEN
                SELECT id INTO order_id_val FROM rental_orders ORDER BY id LIMIT 1;
            END IF;
        ELSE
            SET order_id_val = NULL;
        END IF;

        SET ledger_no_val = CONCAT('LDG', DATE_FORMAT(NOW(), '%Y%m%d%H%i%s'), LPAD(i, 6, '0'));
        SET amount_val = ((i % 500) * 100) + FLOOR(RAND() * 10000);

        INSERT INTO wallet_ledger (
            ledger_no, user_id, order_id, direction, amount_cent,
            balance_after_cent, balance_type, biz_type, biz_no, remark, created_at
        ) VALUES (
            ledger_no_val,
            user_id_val,
            order_id_val,
            CASE WHEN i % 2 = 0 THEN 'in' ELSE 'out' END,
            amount_val,
            100000 + (i % 1000) * 100,
            CASE WHEN i % 5 = 0 THEN 'frozen' ELSE 'available' END,
            CASE (i % 6)
                WHEN 0 THEN 'rent_payment'
                WHEN 1 THEN 'deposit_freeze'
                WHEN 2 THEN 'settlement'
                WHEN 3 THEN 'refund'
                WHEN 4 THEN 'recharge'
                ELSE 'withdraw'
            END,
            CONCAT('BIZ', LPAD(i, 10, '0')),
            CONCAT('测试流水', i),
            DATE_SUB(NOW(), INTERVAL (i % 180) DAY)
        );

        SET i = i + 1;

        IF i % 1000 = 0 THEN
            COMMIT;
        END IF;
    END WHILE;

    COMMIT;
END$$
DELIMITER ;

-- ============================================
-- 5. 批量生成聊天消息（50000条消息）
-- ============================================
DROP PROCEDURE IF EXISTS generate_chat_messages;
DELIMITER $$
CREATE PROCEDURE generate_chat_messages(IN batch_size INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    DECLARE conv_id BIGINT;
    DECLARE user_id_val BIGINT;
    DECLARE conv_min BIGINT;
    DECLARE conv_max BIGINT;
    DECLARE user_min BIGINT;
    DECLARE user_max BIGINT;
    DECLARE conv_pick BIGINT;
    DECLARE user_pick BIGINT;

    SELECT MIN(id), MAX(id) INTO conv_min, conv_max FROM chat_conversations;
    SELECT MIN(id), MAX(id) INTO user_min, user_max FROM users;

    IF conv_min IS NULL THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的聊天会话';
    END IF;
    IF user_min IS NULL THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '没有可用的用户';
    END IF;

    WHILE i <= batch_size DO
        -- 近似随机选择一个会话和发送者，避免 ORDER BY RAND() 全表排序。
        SET conv_id = NULL;
        SET conv_pick = conv_min + FLOOR(RAND() * (conv_max - conv_min + 1));
        SELECT id INTO conv_id FROM chat_conversations
        WHERE id >= conv_pick
        ORDER BY id LIMIT 1;

        IF conv_id IS NULL THEN
            SELECT id INTO conv_id FROM chat_conversations ORDER BY id LIMIT 1;
        END IF;

        IF conv_id IS NOT NULL THEN
            SET user_id_val = NULL;
            SET user_pick = user_min + FLOOR(RAND() * (user_max - user_min + 1));
            SELECT id INTO user_id_val FROM users
            WHERE id >= user_pick
            ORDER BY id LIMIT 1;

            IF user_id_val IS NULL THEN
                SELECT id INTO user_id_val FROM users ORDER BY id LIMIT 1;
            END IF;

            INSERT INTO chat_messages (
                conversation_id, sender_type, sender_id, sender_role,
                content_type, content, created_at
            ) VALUES (
                conv_id,
                'user',
                user_id_val,
                CASE WHEN i % 2 = 0 THEN 'owner' ELSE 'renter' END,
                'text',
                CONCAT('这是测试消息', i, '，内容随机生成用于压力测试'),
                DATE_SUB(NOW(), INTERVAL (i % 30) DAY)
            );
        END IF;

        SET i = i + 1;

        IF i % 1000 = 0 THEN
            COMMIT;
        END IF;
    END WHILE;

    COMMIT;
END$$
DELIMITER ;

-- ============================================
-- 本文件只创建存储过程，不直接生成数据。
-- 请使用 scripts/stress_test.sh data 按参数生成，避免意外重复造数。
-- ============================================

SET FOREIGN_KEY_CHECKS = 1;
