-- 目的：支持上游 IoT 平台传入 19/20 位 ICCID 均能精确命中卡记录
-- 背景：部分运营商 19 位为唯一标识，部分运营商需要完整 20 位才能唯一标识一张卡
-- 策略：双列存储 + 按上游传入长度路由查询，Miss 时记录 Warn 日志不降级

-- 注意：golang-migrate 默认在事务中运行，CREATE INDEX CONCURRENTLY 不能在事务中执行
-- 因此使用 CREATE INDEX IF NOT EXISTS（非 CONCURRENTLY）
-- 生产环境若需零停机建索引，可手动执行 CONCURRENTLY 版本

-- ==========================================================================
-- 1. tb_iot_card 新增双列
-- ==========================================================================

ALTER TABLE tb_iot_card
    ADD COLUMN IF NOT EXISTS iccid_19 varchar(19),
    ADD COLUMN IF NOT EXISTS iccid_20 varchar(20);

COMMENT ON COLUMN tb_iot_card.iccid_19 IS 'ICCID前19位（所有卡必填，用于19位运营商精确查询）';
COMMENT ON COLUMN tb_iot_card.iccid_20 IS '完整20位ICCID（仅20位运营商卡有值，19位卡为NULL）';

-- ==========================================================================
-- 1.1a 冲突检测（执行后人工确认均为 0 行，否则停止迁移人工处理）
-- 检测 19 位前缀重复：若 19 位前缀不唯一，回填后 iccid_19 无法作为唯一索引列
-- ==========================================================================

DO $$
DECLARE
    conflict_count INTEGER;
    abnormal_count INTEGER;
BEGIN
    -- 检测 19 位前缀重复
    SELECT COUNT(*) INTO conflict_count
    FROM (
        SELECT LEFT(iccid, 19)
        FROM tb_iot_card
        WHERE deleted_at IS NULL
        GROUP BY LEFT(iccid, 19)
        HAVING COUNT(*) > 1
    ) t;

    IF conflict_count > 0 THEN
        RAISE EXCEPTION '冲突检测失败：发现 % 组 19 位前缀重复的 ICCID，请人工处理后再执行迁移', conflict_count;
    END IF;

    -- 检测异常长度 ICCID（长度既非 19 也非 20 的记录）
    SELECT COUNT(*) INTO abnormal_count
    FROM tb_iot_card
    WHERE deleted_at IS NULL
      AND LENGTH(iccid) NOT IN (19, 20);

    IF abnormal_count > 0 THEN
        RAISE WARNING '警告：发现 % 条异常长度 ICCID 记录（长度非19也非20），回填后这些卡将无法通过新查询路径命中', abnormal_count;
    END IF;
END $$;

-- ==========================================================================
-- 1.2 回填存量数据
-- iccid_19 = LEFT(iccid, 19)（所有卡）
-- iccid_20 = iccid（仅当 LENGTH(iccid)=20，否则 NULL）
-- ==========================================================================

UPDATE tb_iot_card
SET iccid_19 = LEFT(iccid, 19),
    iccid_20 = CASE WHEN LENGTH(iccid) = 20 THEN iccid ELSE NULL END;

-- ==========================================================================
-- 1.3 为 iccid_19 创建 Partial Index（过滤软删除记录）
-- ==========================================================================

CREATE INDEX IF NOT EXISTS idx_iot_card_iccid_19
    ON tb_iot_card (iccid_19)
    WHERE deleted_at IS NULL;

-- ==========================================================================
-- 1.4 为 iccid_20 创建 Partial Index（过滤软删除和 NULL 记录）
-- ==========================================================================

CREATE INDEX IF NOT EXISTS idx_iot_card_iccid_20
    ON tb_iot_card (iccid_20)
    WHERE deleted_at IS NULL AND iccid_20 IS NOT NULL;

-- ==========================================================================
-- 1.5 tb_personal_customer_iccid 新增 iccid_19 列
-- ==========================================================================

ALTER TABLE tb_personal_customer_iccid
    ADD COLUMN IF NOT EXISTS iccid_19 varchar(19);

COMMENT ON COLUMN tb_personal_customer_iccid.iccid_19 IS 'ICCID前19位（用于19位运营商精确查询）';

-- 回填存量数据
UPDATE tb_personal_customer_iccid
SET iccid_19 = LEFT(iccid, 19);

-- 创建对应 Partial Index
CREATE INDEX IF NOT EXISTS idx_personal_customer_iccid_19
    ON tb_personal_customer_iccid (iccid_19)
    WHERE deleted_at IS NULL;
