-- 02155 Promo Schema Fix
--
-- 修复历史环境中 02154 未正确执行（或部分 GORM AutoMigrate 推断）导致的
-- promo 系统列类型 / 索引偏差。完全幂等：可重复执行。
--
-- 覆盖偏差：
--   1) subscribe_promo.quantity        实际 int/NULL  ->  BIGINT NOT NULL DEFAULT 1
--   2) subscribe_promo 唯一索引         实际 (subscribe_id, promo_rule_id)  ->  (subscribe_id, quantity, promo_rule_id)
--   3) order.promo_rule_id             实际 int/NULL  ->  BIGINT UNSIGNED NOT NULL DEFAULT 0
--   4) order.promo_discount            实际 varchar(255)/NULL  ->  BIGINT NOT NULL DEFAULT 0
--
-- 设计原则：
--   - 所有 ALTER 前先做 NULL/空串兜底，避免 NOT NULL 转换失败。
--   - 类型已经正确的环境（02154 正常跑过）不会被改动，所有 IF 判断都基于
--     INFORMATION_SCHEMA 当前真实状态。
--   - 索引差异处理 4 个分支：仅当索引确实是错的旧形态时才替换，已经是新形态则不动。


-- ============================================================================
-- 1) subscribe_promo.quantity
-- ============================================================================

-- 1.1 列不存在则补建（极端历史环境兜底）
SET @col_exists = (
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
  WHERE TABLE_SCHEMA = DATABASE()
    AND TABLE_NAME = 'subscribe_promo'
    AND COLUMN_NAME = 'quantity'
);

SET @sql = IF(
  @col_exists = 0,
  'ALTER TABLE `subscribe_promo` ADD COLUMN `quantity` BIGINT NOT NULL DEFAULT 1 COMMENT ''购买数量'' AFTER `subscribe_id`',
  'SELECT ''subscribe_promo.quantity exists, skip ADD'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

-- 1.2 NULL 兜底为 1（旧 AutoMigrate 推断列允许 NULL，必须先回填再 NOT NULL）
UPDATE `subscribe_promo` SET `quantity` = 1 WHERE `quantity` IS NULL;

-- 1.3 类型 / 可空 / 默认值修正：只在与目标定义不一致时改
SET @col_def_wrong = (
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
  WHERE TABLE_SCHEMA = DATABASE()
    AND TABLE_NAME = 'subscribe_promo'
    AND COLUMN_NAME = 'quantity'
    AND (
         LOWER(DATA_TYPE) <> 'bigint'
      OR IS_NULLABLE = 'YES'
      OR COLUMN_DEFAULT IS NULL
      OR COLUMN_DEFAULT <> '1'
    )
);

SET @sql = IF(
  @col_def_wrong = 1,
  'ALTER TABLE `subscribe_promo` MODIFY COLUMN `quantity` BIGINT NOT NULL DEFAULT 1 COMMENT ''购买数量''',
  'SELECT ''subscribe_promo.quantity already matches target definition'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;


-- ============================================================================
-- 2) subscribe_promo 唯一索引：旧形态 -> (subscribe_id, quantity, promo_rule_id)
-- ============================================================================

-- 2.1 删除已知的所有旧形态唯一索引（如果存在）
SET @idx_exists = (
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
  WHERE TABLE_SCHEMA = DATABASE()
    AND TABLE_NAME = 'subscribe_promo'
    AND INDEX_NAME = 'idx_subscribe_rule'
);
SET @sql = IF(
  @idx_exists = 1,
  'ALTER TABLE `subscribe_promo` DROP INDEX `idx_subscribe_rule`',
  'SELECT ''subscribe_promo.idx_subscribe_rule absent'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @idx_exists = (
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
  WHERE TABLE_SCHEMA = DATABASE()
    AND TABLE_NAME = 'subscribe_promo'
    AND INDEX_NAME = 'uk_subscribe_rule'
);
SET @sql = IF(
  @idx_exists = 1,
  'ALTER TABLE `subscribe_promo` DROP INDEX `uk_subscribe_rule`',
  'SELECT ''subscribe_promo.uk_subscribe_rule absent'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @idx_exists = (
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
  WHERE TABLE_SCHEMA = DATABASE()
    AND TABLE_NAME = 'subscribe_promo'
    AND INDEX_NAME = 'uk_subscribe_qty_rule'
);
SET @sql = IF(
  @idx_exists = 1,
  'ALTER TABLE `subscribe_promo` DROP INDEX `uk_subscribe_qty_rule`',
  'SELECT ''subscribe_promo.uk_subscribe_qty_rule absent'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

-- 2.2 新建目标唯一索引（缺失时才建）
SET @idx_exists = (
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
  WHERE TABLE_SCHEMA = DATABASE()
    AND TABLE_NAME = 'subscribe_promo'
    AND INDEX_NAME = 'uk_subscribe_quantity_rule'
);
SET @sql = IF(
  @idx_exists = 0,
  'ALTER TABLE `subscribe_promo` ADD UNIQUE KEY `uk_subscribe_quantity_rule` (`subscribe_id`, `quantity`, `promo_rule_id`)',
  'SELECT ''subscribe_promo.uk_subscribe_quantity_rule exists'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;


-- ============================================================================
-- 3) order.promo_rule_id  ->  BIGINT UNSIGNED NOT NULL DEFAULT 0
-- ============================================================================

SET @col_exists = (
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
  WHERE TABLE_SCHEMA = DATABASE()
    AND TABLE_NAME = 'order'
    AND COLUMN_NAME = 'promo_rule_id'
);

SET @sql = IF(
  @col_exists = 0,
  'ALTER TABLE `order` ADD COLUMN `promo_rule_id` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT ''促销规则ID, 0=未使用促销'' AFTER `discount`',
  'SELECT ''order.promo_rule_id exists, skip ADD'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

UPDATE `order` SET `promo_rule_id` = 0 WHERE `promo_rule_id` IS NULL;

SET @col_def_wrong = (
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
  WHERE TABLE_SCHEMA = DATABASE()
    AND TABLE_NAME = 'order'
    AND COLUMN_NAME = 'promo_rule_id'
    AND (
         LOWER(DATA_TYPE) <> 'bigint'
      OR INSTR(LOWER(COLUMN_TYPE), 'unsigned') = 0
      OR IS_NULLABLE = 'YES'
      OR COLUMN_DEFAULT IS NULL
      OR COLUMN_DEFAULT <> '0'
    )
);

SET @sql = IF(
  @col_def_wrong = 1,
  'ALTER TABLE `order` MODIFY COLUMN `promo_rule_id` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT ''促销规则ID, 0=未使用促销''',
  'SELECT ''order.promo_rule_id already matches target definition'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;


-- ============================================================================
-- 4) order.promo_discount  ->  BIGINT NOT NULL DEFAULT 0
--    历史 AutoMigrate 推断为 varchar(255)/NULL，金额字段错存为字符串。
--    必须先把空串/NULL 兜底为 '0'，再 MODIFY，否则 MySQL 转 BIGINT 会写 0
--    （这里我们仍兜底显式化，避免触发 strict mode 报错）。
-- ============================================================================

SET @col_exists = (
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
  WHERE TABLE_SCHEMA = DATABASE()
    AND TABLE_NAME = 'order'
    AND COLUMN_NAME = 'promo_discount'
);

SET @sql = IF(
  @col_exists = 0,
  'ALTER TABLE `order` ADD COLUMN `promo_discount` BIGINT NOT NULL DEFAULT 0 COMMENT ''促销优惠金额(分)'' AFTER `promo_rule_id`',
  'SELECT ''order.promo_discount exists, skip ADD'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

-- 当且仅当当前是字符串型时做兜底（避免对已经是 BIGINT 的环境跑无谓 UPDATE）
SET @col_is_string = (
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
  WHERE TABLE_SCHEMA = DATABASE()
    AND TABLE_NAME = 'order'
    AND COLUMN_NAME = 'promo_discount'
    AND LOWER(DATA_TYPE) IN ('varchar', 'char', 'text')
);

SET @sql = IF(
  @col_is_string = 1,
  'UPDATE `order` SET `promo_discount` = ''0'' WHERE `promo_discount` IS NULL OR `promo_discount` = ''''',
  'SELECT ''order.promo_discount not string type, skip backfill'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @col_def_wrong = (
  SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
  WHERE TABLE_SCHEMA = DATABASE()
    AND TABLE_NAME = 'order'
    AND COLUMN_NAME = 'promo_discount'
    AND (
         LOWER(DATA_TYPE) <> 'bigint'
      OR IS_NULLABLE = 'YES'
      OR COLUMN_DEFAULT IS NULL
      OR COLUMN_DEFAULT <> '0'
    )
);

SET @sql = IF(
  @col_def_wrong = 1,
  'ALTER TABLE `order` MODIFY COLUMN `promo_discount` BIGINT NOT NULL DEFAULT 0 COMMENT ''促销优惠金额(分)''',
  'SELECT ''order.promo_discount already matches target definition'''
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
