-- ========================================
-- 钱包和标签系统多租户改造 - 数据迁移脚本
-- 变更 ID: fix-wallet-tag-multi-tenant
-- ========================================

-- ========================================
-- 第 1 步：备份数据
-- ========================================

-- 删除旧备份表（如果存在）
DROP TABLE IF EXISTS tb_wallet_backup;
DROP TABLE IF EXISTS tb_tag_backup;
DROP TABLE IF EXISTS tb_resource_tag_backup;

-- 备份钱包表
CREATE TABLE tb_wallet_backup AS SELECT * FROM tb_wallet;

-- 备份标签表
CREATE TABLE tb_tag_backup AS SELECT * FROM tb_tag;

-- 备份资源标签表
CREATE TABLE tb_resource_tag_backup AS SELECT * FROM tb_resource_tag;

-- ========================================
-- 第 2 步：钱包表结构变更
-- ========================================

-- 添加新字段（先添加，允许 NULL）
ALTER TABLE tb_wallet 
ADD COLUMN resource_type VARCHAR(20),
ADD COLUMN resource_id BIGINT;

-- 迁移代理钱包数据
-- 代理钱包从 user_id 迁移到 shop_id
UPDATE tb_wallet w
SET 
    resource_type = 'shop',
    resource_id = a.shop_id
FROM tb_account a
WHERE 
    w.user_id = a.id 
    AND w.wallet_type = 'agent'
    AND a.shop_id IS NOT NULL;

-- 标记无法迁移的代理钱包（shop_id 为 NULL）
UPDATE tb_wallet
SET resource_type = 'INVALID_AGENT'
WHERE wallet_type = 'agent' AND resource_type IS NULL;

-- 标记用户钱包为待处理（需要业务人员确认）
UPDATE tb_wallet
SET 
    resource_type = 'PENDING_USER',
    resource_id = 0
WHERE wallet_type = 'user' AND resource_type IS NULL;

-- 检查是否有无法迁移的数据
DO $$
DECLARE
    invalid_count INTEGER;
    pending_count INTEGER;
BEGIN
    SELECT COUNT(*) INTO invalid_count FROM tb_wallet WHERE resource_type = 'INVALID_AGENT';
    SELECT COUNT(*) INTO pending_count FROM tb_wallet WHERE resource_type = 'PENDING_USER';
    
    IF invalid_count > 0 THEN
        RAISE EXCEPTION '存在 % 个无法迁移的代理钱包（shop_id 为 NULL），请手动处理', invalid_count;
    END IF;
    
    IF pending_count > 0 THEN
        RAISE NOTICE '存在 % 个待确认的用户钱包，需要业务人员确认归属', pending_count;
    END IF;
END $$;

-- 设置字段为 NOT NULL
ALTER TABLE tb_wallet 
ALTER COLUMN resource_type SET NOT NULL,
ALTER COLUMN resource_id SET NOT NULL;

-- 删除旧字段和约束
DROP INDEX IF EXISTS idx_wallet_user_type_currency;
DROP INDEX IF EXISTS idx_wallet_user;
ALTER TABLE tb_wallet DROP COLUMN user_id;

-- 创建新索引和约束
CREATE UNIQUE INDEX idx_wallet_resource_type_currency 
ON tb_wallet (resource_type, resource_id, wallet_type, currency) 
WHERE deleted_at IS NULL;

CREATE INDEX idx_wallet_resource ON tb_wallet (resource_type, resource_id, deleted_at);

-- 保留状态索引（如果不存在）
CREATE INDEX IF NOT EXISTS idx_wallet_status ON tb_wallet (status, deleted_at);

-- ========================================
-- 第 3 步：标签表结构变更
-- ========================================

-- 添加新字段
ALTER TABLE tb_tag 
ADD COLUMN enterprise_id BIGINT,
ADD COLUMN shop_id BIGINT;

-- 迁移企业标签数据（从 creator 推断）
UPDATE tb_tag t
SET enterprise_id = (
    SELECT a.enterprise_id 
    FROM tb_account a 
    WHERE a.id = t.creator AND a.enterprise_id IS NOT NULL
    LIMIT 1
);

-- 迁移店铺标签数据（从 creator 推断）
UPDATE tb_tag t
SET shop_id = (
    SELECT a.shop_id 
    FROM tb_account a 
    WHERE a.id = t.creator AND a.shop_id IS NOT NULL
    LIMIT 1
)
WHERE enterprise_id IS NULL;

-- 其他标签默认为全局标签（enterprise_id 和 shop_id 都为 NULL）

-- 删除旧约束
DROP INDEX IF EXISTS idx_tag_name;

-- 创建新索引
CREATE INDEX idx_tag_enterprise ON tb_tag (enterprise_id, deleted_at);
CREATE INDEX idx_tag_shop ON tb_tag (shop_id, deleted_at);

-- 创建新唯一约束
CREATE UNIQUE INDEX idx_tag_enterprise_name 
ON tb_tag (enterprise_id, name) 
WHERE deleted_at IS NULL AND enterprise_id IS NOT NULL;

CREATE UNIQUE INDEX idx_tag_shop_name 
ON tb_tag (shop_id, name) 
WHERE deleted_at IS NULL AND shop_id IS NOT NULL;

CREATE UNIQUE INDEX idx_tag_global_name 
ON tb_tag (name) 
WHERE deleted_at IS NULL AND enterprise_id IS NULL AND shop_id IS NULL;

-- ========================================
-- 第 4 步：资源标签表结构变更
-- ========================================

-- 添加新字段
ALTER TABLE tb_resource_tag 
ADD COLUMN enterprise_id BIGINT,
ADD COLUMN shop_id BIGINT;

-- 从 creator 推断归属（企业）
UPDATE tb_resource_tag rt
SET enterprise_id = (
    SELECT a.enterprise_id 
    FROM tb_account a 
    WHERE a.id = rt.creator AND a.enterprise_id IS NOT NULL
    LIMIT 1
);

-- 从 creator 推断归属（店铺）
UPDATE tb_resource_tag rt
SET shop_id = (
    SELECT a.shop_id 
    FROM tb_account a 
    WHERE a.id = rt.creator AND a.shop_id IS NOT NULL
    LIMIT 1
)
WHERE enterprise_id IS NULL;

-- 创建索引
CREATE INDEX idx_resource_tag_enterprise ON tb_resource_tag (enterprise_id, deleted_at);
CREATE INDEX idx_resource_tag_shop ON tb_resource_tag (shop_id, deleted_at);

-- ========================================
-- 第 5 步：验证数据一致性
-- ========================================

-- 输出迁移统计信息
DO $$
DECLARE
    wallet_total INTEGER;
    wallet_shop INTEGER;
    wallet_pending INTEGER;
    tag_total INTEGER;
    tag_enterprise INTEGER;
    tag_shop INTEGER;
    tag_global INTEGER;
BEGIN
    -- 钱包统计
    SELECT COUNT(*) INTO wallet_total FROM tb_wallet;
    SELECT COUNT(*) INTO wallet_shop FROM tb_wallet WHERE resource_type = 'shop';
    SELECT COUNT(*) INTO wallet_pending FROM tb_wallet WHERE resource_type = 'PENDING_USER';
    
    RAISE NOTICE '========================================';
    RAISE NOTICE '钱包迁移统计:';
    RAISE NOTICE '  总数: %', wallet_total;
    RAISE NOTICE '  店铺钱包: %', wallet_shop;
    RAISE NOTICE '  待确认用户钱包: %', wallet_pending;
    
    -- 标签统计
    SELECT COUNT(*) INTO tag_total FROM tb_tag;
    SELECT COUNT(*) INTO tag_enterprise FROM tb_tag WHERE enterprise_id IS NOT NULL;
    SELECT COUNT(*) INTO tag_shop FROM tb_tag WHERE shop_id IS NOT NULL;
    SELECT COUNT(*) INTO tag_global FROM tb_tag WHERE enterprise_id IS NULL AND shop_id IS NULL;
    
    RAISE NOTICE '========================================';
    RAISE NOTICE '标签迁移统计:';
    RAISE NOTICE '  总数: %', tag_total;
    RAISE NOTICE '  企业标签: %', tag_enterprise;
    RAISE NOTICE '  店铺标签: %', tag_shop;
    RAISE NOTICE '  全局标签: %', tag_global;
    RAISE NOTICE '========================================';
END $$;

-- ========================================
-- 迁移完成
-- ========================================
