-- 添加 is_standalone 物化列，消除 ListStandalone 查询中的 NOT EXISTS 子查询
-- 30M 行表上 NOT EXISTS 子查询导致 9s+ 延迟，物化为布尔列后降至 <500ms

-- 1. 添加列（默认 true，因为大多数卡未绑定设备）
ALTER TABLE tb_iot_card ADD COLUMN IF NOT EXISTS is_standalone BOOLEAN NOT NULL DEFAULT true;

COMMENT ON COLUMN tb_iot_card.is_standalone IS '是否为独立卡(未绑定设备) true=独立卡 false=已绑定设备，由触发器自动维护';

-- 2. 回填数据：将已绑定设备的卡标记为 false
UPDATE tb_iot_card SET is_standalone = false
WHERE id IN (
    SELECT DISTINCT iot_card_id FROM tb_device_sim_binding
    WHERE bind_status = 1 AND deleted_at IS NULL
);

-- 3. 创建部分索引（仅包含独立卡 + 未删除的行）
CREATE INDEX IF NOT EXISTS idx_iot_card_standalone_shop_created
ON tb_iot_card (shop_id, created_at DESC)
WHERE deleted_at IS NULL AND is_standalone = true;

CREATE INDEX IF NOT EXISTS idx_iot_card_standalone_shop_status_created
ON tb_iot_card (shop_id, status, created_at DESC)
WHERE deleted_at IS NULL AND is_standalone = true;

-- 4. 创建触发器函数：绑定时设置 is_standalone = false
CREATE OR REPLACE FUNCTION fn_update_card_standalone_on_bind()
RETURNS TRIGGER AS $$
BEGIN
    -- INSERT 或 bind_status 变为 1（绑定）
    IF (TG_OP = 'INSERT' AND NEW.bind_status = 1) OR
       (TG_OP = 'UPDATE' AND NEW.bind_status = 1 AND (OLD.bind_status IS DISTINCT FROM 1)) THEN
        UPDATE tb_iot_card SET is_standalone = false WHERE id = NEW.iot_card_id;
    END IF;

    -- bind_status 从 1 变为其他值（解绑），检查是否还有其他活跃绑定
    IF TG_OP = 'UPDATE' AND OLD.bind_status = 1 AND NEW.bind_status != 1 THEN
        IF NOT EXISTS (
            SELECT 1 FROM tb_device_sim_binding
            WHERE iot_card_id = NEW.iot_card_id AND bind_status = 1
              AND deleted_at IS NULL AND id != NEW.id
        ) THEN
            UPDATE tb_iot_card SET is_standalone = true WHERE id = NEW.iot_card_id;
        END IF;
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 5. 绑定表的触发器
CREATE TRIGGER trg_device_sim_binding_standalone
AFTER INSERT OR UPDATE OF bind_status ON tb_device_sim_binding
FOR EACH ROW
EXECUTE FUNCTION fn_update_card_standalone_on_bind();

-- 6. 软删除触发器：绑定记录被软删除时恢复独立状态
CREATE OR REPLACE FUNCTION fn_update_card_standalone_on_soft_delete()
RETURNS TRIGGER AS $$
BEGIN
    IF OLD.deleted_at IS NULL AND NEW.deleted_at IS NOT NULL AND OLD.bind_status = 1 THEN
        IF NOT EXISTS (
            SELECT 1 FROM tb_device_sim_binding
            WHERE iot_card_id = NEW.iot_card_id AND bind_status = 1
              AND deleted_at IS NULL AND id != NEW.id
        ) THEN
            UPDATE tb_iot_card SET is_standalone = true WHERE id = NEW.iot_card_id;
        END IF;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_device_sim_binding_soft_delete
AFTER UPDATE OF deleted_at ON tb_device_sim_binding
FOR EACH ROW
EXECUTE FUNCTION fn_update_card_standalone_on_soft_delete();

-- 7. 更新统计信息
ANALYZE tb_iot_card;
