-- 房间新版 VIP 媒体、上传授权与装扮失效读模型。
-- 性能边界：
-- 1. nullable/default 列使用 MySQL 8 INSTANT，仅短暂持有 metadata lock，不重写历史行；仍建议业务低峰执行。
-- 2. image_url 扩容与唯一索引需要在线扫描低频 room_background_images，使用 INPLACE/LOCK=NONE。
-- 3. 唯一索引创建前会主动检查非 NULL command_id 重复组；发现脏数据直接 SIGNAL，拒绝创建冲突索引。
-- 4. 所有分支先查 information_schema，因此脚本可在发布重试时重复执行。

SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;

USE hyapp_room;

DELIMITER $$

DROP PROCEDURE IF EXISTS hyapp_migrate_003_room_vip_media_decorations$$
CREATE PROCEDURE hyapp_migrate_003_room_vip_media_decorations()
BEGIN
  DECLARE duplicate_groups BIGINT DEFAULT 0;
  DECLARE oversized_urls BIGINT DEFAULT 0;

  IF EXISTS (
    SELECT 1 FROM information_schema.tables
    WHERE table_schema = DATABASE() AND table_name = 'room_background_images'
  ) THEN
    -- 先移除旧 URL 唯一键，否则将 image_url 扩到 1024 字符时，utf8mb4 最大键长会超过 InnoDB 3072 字节限制。
    IF EXISTS (
      SELECT 1 FROM information_schema.statistics
      WHERE table_schema = DATABASE() AND table_name = 'room_background_images'
        AND index_name = 'uk_room_background_url'
    ) THEN
      ALTER TABLE room_background_images DROP INDEX uk_room_background_url, ALGORITHM=INPLACE, LOCK=NONE;
    END IF;

    IF EXISTS (
      SELECT 1 FROM information_schema.columns
      WHERE table_schema = DATABASE() AND table_name = 'room_background_images'
        AND column_name = 'image_url'
        AND (data_type <> 'varchar' OR character_maximum_length <> 1024)
    ) THEN
      SELECT COUNT(*) INTO oversized_urls
      FROM room_background_images
      WHERE CHAR_LENGTH(image_url) > 1024;
      IF oversized_urls > 0 THEN
        SIGNAL SQLSTATE '45000'
          SET MESSAGE_TEXT = 'room_background_images.image_url contains values longer than 1024';
      END IF;
      ALTER TABLE room_background_images
        MODIFY COLUMN image_url VARCHAR(1024) NOT NULL,
        ALGORITHM=INPLACE,
        LOCK=NONE;
    END IF;

    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'command_id') THEN
      ALTER TABLE room_background_images ADD COLUMN command_id VARCHAR(128) NULL COMMENT '新版素材保存幂等键；历史行保持 NULL', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'image_url_sha256') THEN
      -- 不使用 URL 前缀唯一键；前 700 余字符相同的不同 URL 仍必须能同时保存。
      ALTER TABLE room_background_images
        ADD COLUMN image_url_sha256 BINARY(32) GENERATED ALWAYS AS (UNHEX(SHA2(image_url, 256))) STORED COMMENT '背景图 URL 唯一性哈希',
        -- MySQL 8.4 新增 STORED 生成列只支持 COPY；该表为低频素材表，复制期间的写锁是可控的一次性迁移成本。
        ALGORITHM=COPY;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'object_key') THEN
      ALTER TABLE room_background_images ADD COLUMN object_key VARCHAR(512) NOT NULL DEFAULT '' COMMENT 'COS 对象 key', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'content_type') THEN
      ALTER TABLE room_background_images ADD COLUMN content_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '服务端嗅探 MIME', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'media_format') THEN
      ALTER TABLE room_background_images ADD COLUMN media_format VARCHAR(16) NOT NULL DEFAULT '' COMMENT 'jpeg/png/gif/webp', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'size_bytes') THEN
      ALTER TABLE room_background_images ADD COLUMN size_bytes BIGINT NOT NULL DEFAULT 0 COMMENT '文件字节数', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'width') THEN
      ALTER TABLE room_background_images ADD COLUMN width INT NOT NULL DEFAULT 0 COMMENT '像素宽度', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'height') THEN
      ALTER TABLE room_background_images ADD COLUMN height INT NOT NULL DEFAULT 0 COMMENT '像素高度', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'animated') THEN
      ALTER TABLE room_background_images ADD COLUMN animated BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否动图', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'frame_count') THEN
      ALTER TABLE room_background_images ADD COLUMN frame_count INT NOT NULL DEFAULT 0 COMMENT '帧数', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'duration_ms') THEN
      ALTER TABLE room_background_images ADD COLUMN duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT '动图总时长', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'poster_url') THEN
      ALTER TABLE room_background_images ADD COLUMN poster_url VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '可选首帧 URL', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'thumbnail_url') THEN
      ALTER TABLE room_background_images ADD COLUMN thumbnail_url VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '可选缩略图 URL', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'sha256') THEN
      ALTER TABLE room_background_images ADD COLUMN sha256 CHAR(64) NOT NULL DEFAULT '' COMMENT '原文件 SHA-256', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_background_images' AND column_name = 'media_status') THEN
      ALTER TABLE room_background_images ADD COLUMN media_status VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'active 表示已通过专用上传入口', ALGORITHM=INSTANT;
    END IF;

    IF NOT EXISTS (
      SELECT 1 FROM information_schema.statistics
      WHERE table_schema = DATABASE() AND table_name = 'room_background_images'
        AND index_name = 'uk_room_background_url'
    ) THEN
      ALTER TABLE room_background_images
        ADD UNIQUE KEY uk_room_background_url (app_code, room_id, image_url_sha256),
        ALGORITHM=INPLACE,
        LOCK=NONE;
    END IF;

    IF NOT EXISTS (
      SELECT 1 FROM information_schema.statistics
      WHERE table_schema = DATABASE() AND table_name = 'room_background_images'
        AND index_name = 'uk_room_background_command'
    ) THEN
      SELECT COUNT(*) INTO duplicate_groups
      FROM (
        SELECT 1
        FROM room_background_images
        WHERE command_id IS NOT NULL
        GROUP BY app_code, room_id, command_id
        HAVING COUNT(*) > 1
        LIMIT 1
      ) AS duplicate_command_groups;
      IF duplicate_groups > 0 THEN
        SIGNAL SQLSTATE '45000'
          SET MESSAGE_TEXT = 'duplicate room background command_id blocks unique index';
      END IF;
      ALTER TABLE room_background_images
        ADD UNIQUE KEY uk_room_background_command (app_code, room_id, command_id),
        ALGORITHM=INPLACE,
        LOCK=NONE;
    END IF;
  END IF;

  IF EXISTS (
    SELECT 1 FROM information_schema.tables
    WHERE table_schema = DATABASE() AND table_name = 'room_list_entries'
  ) THEN
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_list_entries' AND column_name = 'room_border_json') THEN
      ALTER TABLE room_list_entries ADD COLUMN room_border_json JSON NULL COMMENT '当前未过期房间边框资源快照', ALGORITHM=INSTANT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'room_list_entries' AND column_name = 'room_name_style_json') THEN
      ALTER TABLE room_list_entries ADD COLUMN room_name_style_json JSON NULL COMMENT '当前未过期彩色房名资源快照', ALGORITHM=INSTANT;
    END IF;
  END IF;
END$$

CALL hyapp_migrate_003_room_vip_media_decorations()$$
DROP PROCEDURE IF EXISTS hyapp_migrate_003_room_vip_media_decorations$$

DELIMITER ;

CREATE TABLE IF NOT EXISTS room_media_upload_registrations (
  app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
  room_id VARCHAR(64) NOT NULL COMMENT '目标房间 ID',
  command_id VARCHAR(128) NOT NULL COMMENT '专用上传强幂等键',
  actor_user_id BIGINT NOT NULL COMMENT '首次授权用户 ID',
  purpose VARCHAR(32) NOT NULL COMMENT 'room_background/room_image',
  media_payload_sha256 CHAR(64) NOT NULL COMMENT '首次服务端解析媒体事实哈希',
  expected_object_key VARCHAR(512) NOT NULL COMMENT 'room owner 确定的 COS key',
  object_url VARCHAR(1024) NOT NULL DEFAULT '' COMMENT 'PutObject 成功后的访问 URL',
  status VARCHAR(32) NOT NULL DEFAULT 'authorized' COMMENT 'authorized/active',
  content_type VARCHAR(64) NOT NULL COMMENT '服务端嗅探 MIME',
  media_format VARCHAR(16) NOT NULL COMMENT 'jpeg/png/gif/webp',
  size_bytes BIGINT NOT NULL COMMENT '原文件字节数',
  width INT NOT NULL COMMENT '像素宽度',
  height INT NOT NULL COMMENT '像素高度',
  animated BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否动图',
  frame_count INT NOT NULL COMMENT '帧数',
  duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT '动图总时长',
  sha256 CHAR(64) NOT NULL COMMENT '原文件 SHA-256',
  authorized_room_version BIGINT NOT NULL COMMENT '首次授权看到的房间版本',
  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
  PRIMARY KEY (app_code, room_id, command_id),
  UNIQUE KEY uk_room_media_upload_object (app_code, expected_object_key),
  KEY idx_room_media_upload_status_created (app_code, status, created_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间专用媒体上传授权与完成事实';

CREATE TABLE IF NOT EXISTS room_decoration_assignments (
  app_code VARCHAR(32) NOT NULL,
  room_id VARCHAR(64) NOT NULL,
  decoration_type VARCHAR(32) NOT NULL,
  owner_user_id BIGINT NOT NULL,
  benefit_code VARCHAR(64) NOT NULL,
  resource_id BIGINT NOT NULL,
  entitlement_id VARCHAR(128) NOT NULL DEFAULT '',
  expires_at_ms BIGINT NOT NULL DEFAULT 0,
  updated_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, room_id, decoration_type),
  KEY idx_room_decoration_resource (app_code, resource_id, room_id, decoration_type),
  KEY idx_room_decoration_owner (app_code, owner_user_id, room_id, decoration_type),
  KEY idx_room_decoration_expiry (app_code, expires_at_ms, room_id, decoration_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间当前 VIP 装扮反向索引';

CREATE TABLE IF NOT EXISTS room_wallet_event_consumption (
  app_code VARCHAR(32) NOT NULL,
  event_id VARCHAR(128) NOT NULL,
  event_type VARCHAR(64) NOT NULL,
  consumed_at_ms BIGINT NOT NULL,
  PRIMARY KEY (app_code, event_id),
  KEY idx_room_wallet_event_consumed (app_code, consumed_at_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='room-service 消费 wallet 装扮事实的本地幂等表';
