-- ============================================================
-- 美家卡智影 - 后台运维 SQL 脚本
-- 适用场景：暂无管理后台，直接操作数据库
-- 注意：所有操作应在事务中执行，操作前请备份数据
-- ============================================================

-- -----------------------------------------------------------
-- 一、新增用户（支持同时赠送初始积分）
-- -----------------------------------------------------------
-- 用法：修改下方变量后执行

DO $$
DECLARE
    v_mobile       TEXT := '13800138000';     -- ← 修改：手机号
    v_nickname     TEXT := '新用户昵称';        -- ← 修改：昵称（可为空）
    v_source       TEXT := 'manual';           -- ← 修改：注册来源：manual / invite / promotion
    v_invited_by   UUID := NULL;               -- ← 修改：邀请人 user_id（没有则留 NULL）
    v_gift_points  INT  := 2000;                -- ← 修改：赠送初始积分（0 表示不赠送）
    v_gift_days    INT  := 365;                -- ← 修改：赠送积分有效期（天）
    v_user_id      UUID;
    v_batch_id     BIGINT;
    v_now          TIMESTAMPTZ := NOW();
BEGIN
    -- 1. 插入用户
    INSERT INTO mjk_users (
        id, mobile, password_hash, status, nickname,
        avatar_url, source, invited_by,
        last_login_at, last_login_ip, deleted_at, extra,
        created_at, updated_at
    ) VALUES (
        gen_random_uuid(),
        v_mobile,
        NULL,              -- 密码哈希（未设置密码）
        'active',
        v_nickname,
        NULL,
        v_source,
        v_invited_by,
        NULL, NULL, NULL,
        '{}'::JSONB,
        v_now, v_now
    )
    RETURNING id INTO v_user_id;

    -- 2. 初始化积分汇总（余额为 0）
    INSERT INTO mjk_user_points (
        user_id, balance, total_recharged, total_consumed, total_expired,
        created_at, updated_at
    ) VALUES (
        v_user_id, 0, 0, 0, 0,
        v_now, v_now
    );

    -- 3. 如有赠送积分，创建批次 + 流水 + 更新余额
    IF v_gift_points > 0 THEN
        -- 3.1 插入积分批次
        INSERT INTO mjk_point_batches (
            user_id, amount, remaining, expired_at, source,
            created_at, updated_at
        ) VALUES (
            v_user_id,
            v_gift_points,
            v_gift_points,
            v_now + (v_gift_days || ' days')::INTERVAL,
            'gift',
            v_now, v_now
        )
        RETURNING id INTO v_batch_id;

        -- 3.2 插入积分流水
        INSERT INTO mjk_point_transactions (
            user_id, type, amount,
            balance_before, balance_after,
            source_type, source_id, batch_id,
            duration, category, description,
            created_at, updated_at
        ) VALUES (
            v_user_id,
            'recharge',
            v_gift_points,
            0,                           -- 变动前余额
            v_gift_points,               -- 变动后余额
            'manual_gift',
            v_batch_id::TEXT,
            v_batch_id,
            NULL,
            '充值',
            '新用户注册赠送积分',
            v_now, v_now
        );

        -- 3.3 更新用户积分汇总
        UPDATE mjk_user_points
        SET balance        = v_gift_points,
            total_recharged = v_gift_points,
            updated_at     = v_now
        WHERE user_id = v_user_id;
    END IF;

    RAISE NOTICE '用户创建成功，user_id = %', v_user_id;
END $$;


-- -----------------------------------------------------------
-- 二、积分赠送（给已有用户赠送积分）
-- -----------------------------------------------------------
-- 用法：修改下方变量后执行

DO $$
DECLARE
    v_mobile       TEXT := '13860199646';     -- ← 修改：目标用户手机号
    v_gift_points  INT  := 5000;                -- ← 修改：赠送积分数量
    v_gift_days    INT  := 180;                -- ← 修改：有效期（天）
    v_reason       TEXT := '运营活动赠送';       -- ← 修改：赠送原因（写入流水描述）
    v_user_id      UUID;
    v_batch_id     BIGINT;
    v_balance_before INT;
    v_now          TIMESTAMPTZ := NOW();
BEGIN
    -- 1. 查找用户
    SELECT id INTO v_user_id
    FROM mjk_users
    WHERE mobile = v_mobile
      AND status = 'active'
      AND deleted_at IS NULL;

    IF v_user_id IS NULL THEN
        RAISE EXCEPTION '用户不存在或已注销：mobile = %', v_mobile;
    END IF;

    -- 2. 获取当前余额
    SELECT balance INTO v_balance_before
    FROM mjk_user_points
    WHERE user_id = v_user_id;

    IF v_balance_before IS NULL THEN
        -- 如果没有积分记录，先初始化
        INSERT INTO mjk_user_points (
            user_id, balance, total_recharged, total_consumed, total_expired,
            created_at, updated_at
        ) VALUES (
            v_user_id, 0, 0, 0, 0,
            v_now, v_now
        );
        v_balance_before := 0;
    END IF;

    -- 3. 插入积分批次
    INSERT INTO mjk_point_batches (
        user_id, amount, remaining, expired_at, source,
        created_at, updated_at
    ) VALUES (
        v_user_id,
        v_gift_points,
        v_gift_points,
        v_now + (v_gift_days || ' days')::INTERVAL,
        'gift',
        v_now, v_now
    )
    RETURNING id INTO v_batch_id;

    -- 4. 插入积分流水
    INSERT INTO mjk_point_transactions (
        user_id, type, amount,
        balance_before, balance_after,
        source_type, source_id, batch_id,
        duration, category, description,
        created_at, updated_at
    ) VALUES (
        v_user_id,
        'recharge',
        v_gift_points,
        v_balance_before,
        v_balance_before + v_gift_points,
        'manual_gift',
        v_batch_id::TEXT,
        v_batch_id,
        NULL,
        '充值',
        v_reason,
        v_now, v_now
    );

    -- 5. 更新用户积分汇总
    UPDATE mjk_user_points
    SET balance         = balance + v_gift_points,
        total_recharged = total_recharged + v_gift_points,
        updated_at      = v_now
    WHERE user_id = v_user_id;

    RAISE NOTICE '已向用户 % 赠送 % 积分，当前余额 = %',
        v_mobile, v_gift_points, v_balance_before + v_gift_points;
END $$;


-- -----------------------------------------------------------
-- 三、积分补偿（给用户补偿积分，source = compensation）
-- -----------------------------------------------------------
-- 用法：修改下方变量后执行

DO $$
DECLARE
    v_mobile       TEXT := '13800138000';     -- ← 修改：目标用户手机号
    v_comp_points  INT  := 200;                -- ← 修改：补偿积分数量
    v_comp_days    INT  := 365;                -- ← 修改：有效期（天，建议给长一点）
    v_reason       TEXT := '系统故障补偿';       -- ← 修改：补偿原因
    v_user_id      UUID;
    v_batch_id     BIGINT;
    v_balance_before INT;
    v_now          TIMESTAMPTZ := NOW();
BEGIN
    -- 1. 查找用户
    SELECT id INTO v_user_id
    FROM mjk_users
    WHERE mobile = v_mobile
      AND status = 'active'
      AND deleted_at IS NULL;

    IF v_user_id IS NULL THEN
        RAISE EXCEPTION '用户不存在或已注销：mobile = %', v_mobile;
    END IF;

    -- 2. 获取当前余额
    SELECT balance INTO v_balance_before
    FROM mjk_user_points
    WHERE user_id = v_user_id;

    IF v_balance_before IS NULL THEN
        INSERT INTO mjk_user_points (
            user_id, balance, total_recharged, total_consumed, total_expired,
            created_at, updated_at
        ) VALUES (
            v_user_id, 0, 0, 0, 0,
            v_now, v_now
        );
        v_balance_before := 0;
    END IF;

    -- 3. 插入积分批次（source = compensation）
    INSERT INTO mjk_point_batches (
        user_id, amount, remaining, expired_at, source,
        created_at, updated_at
    ) VALUES (
        v_user_id,
        v_comp_points,
        v_comp_points,
        v_now + (v_comp_days || ' days')::INTERVAL,
        'compensation',
        v_now, v_now
    )
    RETURNING id INTO v_batch_id;

    -- 4. 插入积分流水
    INSERT INTO mjk_point_transactions (
        user_id, type, amount,
        balance_before, balance_after,
        source_type, source_id, batch_id,
        duration, category, description,
        created_at, updated_at
    ) VALUES (
        v_user_id,
        'recharge',
        v_comp_points,
        v_balance_before,
        v_balance_before + v_comp_points,
        'manual_compensation',
        v_batch_id::TEXT,
        v_batch_id,
        NULL,
            '补偿',
        v_reason,
        v_now, v_now
    );

    -- 5. 更新用户积分汇总
    UPDATE mjk_user_points
    SET balance         = balance + v_comp_points,
        total_recharged = total_recharged + v_comp_points,
        updated_at      = v_now
    WHERE user_id = v_user_id;

    RAISE NOTICE '已向用户 % 补偿 % 积分，当前余额 = %',
        v_mobile, v_comp_points, v_balance_before + v_comp_points;
END $$;


-- -----------------------------------------------------------
-- 四、批量积分补偿（给多个用户同时补偿）
-- -----------------------------------------------------------
-- 用法：将要补偿的手机号填入临时表，然后执行

-- 步骤 1：创建临时补偿名单（手机号 + 补偿数量 + 原因）
-- DROP TABLE IF EXISTS _temp_compensation_list;
CREATE TEMP TABLE IF NOT EXISTS _temp_compensation_list (
    mobile       TEXT PRIMARY KEY,
    comp_points  INT NOT NULL,
    reason       TEXT NOT NULL DEFAULT '批量补偿'
);

-- 步骤 2：插入要补偿的用户（每次执行前清空并重新插入）
TRUNCATE _temp_compensation_list;
INSERT INTO _temp_compensation_list (mobile, comp_points, reason) VALUES
    ('13800138000', 100, '活动补偿'),
    ('13800138001', 200, '活动补偿'),
    ('13800138002', 100, '活动补偿');

-- 步骤 3：执行批量补偿
DO $$
DECLARE
    v_rec          RECORD;
    v_user_id      UUID;
    v_batch_id     BIGINT;
    v_balance_before INT;
    v_now          TIMESTAMPTZ := NOW();
    v_comp_days    INT := 365;
    v_success_cnt  INT := 0;
    v_fail_cnt     INT := 0;
BEGIN
    FOR v_rec IN SELECT * FROM _temp_compensation_list LOOP
        BEGIN
            -- 查找用户
            SELECT id INTO v_user_id
            FROM mjk_users
            WHERE mobile = v_rec.mobile
              AND status = 'active'
              AND deleted_at IS NULL;

            IF v_user_id IS NULL THEN
                RAISE WARNING '用户不存在：%', v_rec.mobile;
                v_fail_cnt := v_fail_cnt + 1;
                CONTINUE;
            END IF;

            -- 获取当前余额
            SELECT balance INTO v_balance_before
            FROM mjk_user_points
            WHERE user_id = v_user_id;

            IF v_balance_before IS NULL THEN
                INSERT INTO mjk_user_points (
                    user_id, balance, total_recharged, total_consumed, total_expired,
                    created_at, updated_at
                ) VALUES (
                    v_user_id, 0, 0, 0, 0,
                    v_now, v_now
                );
                v_balance_before := 0;
            END IF;

            -- 插入批次
            INSERT INTO mjk_point_batches (
                user_id, amount, remaining, expired_at, source,
                created_at, updated_at
            ) VALUES (
                v_user_id,
                v_rec.comp_points,
                v_rec.comp_points,
                v_now + (v_comp_days || ' days')::INTERVAL,
                'compensation',
                v_now, v_now
            )
            RETURNING id INTO v_batch_id;

            -- 插入流水
            INSERT INTO mjk_point_transactions (
                user_id, type, amount,
                balance_before, balance_after,
                source_type, source_id, batch_id,
                duration, category, description,
                created_at, updated_at
            ) VALUES (
                v_user_id,
                'recharge',
                v_rec.comp_points,
                v_balance_before,
                v_balance_before + v_rec.comp_points,
                'batch_compensation',
                v_batch_id::TEXT,
                v_batch_id,
                NULL,
                '补偿',
                v_rec.reason,
                v_now, v_now
            );

            -- 更新汇总
            UPDATE mjk_user_points
            SET balance         = balance + v_rec.comp_points,
                total_recharged = total_recharged + v_rec.comp_points,
                updated_at      = v_now
            WHERE user_id = v_user_id;

            v_success_cnt := v_success_cnt + 1;

        EXCEPTION WHEN OTHERS THEN
            RAISE WARNING '补偿失败 %: %', v_rec.mobile, SQLERRM;
            v_fail_cnt := v_fail_cnt + 1;
        END;
    END LOOP;

    RAISE NOTICE '批量补偿完成：成功 % 人，失败 % 人', v_success_cnt, v_fail_cnt;
END $$;

-- 清理临时表
-- DROP TABLE IF EXISTS _temp_compensation_list;
