"""comparison_record: 唯一键 (user_id,trace_id) → trace_id 单列 + user_id 可空

Revision ID: comparison_record_trace_unique
Revises: feedback_type_reply
Create Date: 2026-07-03 12:00:00.000000

比价记录改「后端 harvest」：app-server 在帧0(pricebot 出 trace_id)即建行，随 done/finalize
逐步补全，客户端不再 POST 记录。故本表要两处调整：
  1. user_id 改**可空**——harvest 建行那刻(软鉴权 / 老客户端匿名)可能还没有 user_id。
  2. 唯一键 (user_id, trace_id) → **trace_id 单列**——trace_id 由 app-server 签发、全局唯一，
     一次比价一行；harvest 建行时 user_id 还没有，不能再用复合键去重。

⚠️ 上线前(QA)务必确认 comparison_record 无重复 trace_id：旧复合唯一键**允许**同 trace_id
   跨不同 user_id（实际上客户端 UUID 从不重复，但约束没拦），若真有重复,建 trace 单列唯一会失败。
   查:  SELECT trace_id, COUNT(*) c FROM comparison_record GROUP BY trace_id HAVING c > 1;

SQLite 不支持直接 drop/alter 约束/列，用 batch_alter_table（建临时表+拷数据+换名），
与 coupon_engage_per_package / store_mapping_* 同款；Postgres 直接执行原生 ALTER。
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = 'comparison_record_trace_unique'
down_revision: Union[str, Sequence[str], None] = 'feedback_type_reply'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    with op.batch_alter_table('comparison_record', schema=None) as batch_op:
        # harvest 帧0 建行时 user_id 可能暂缺 → 放开非空。
        batch_op.alter_column('user_id', existing_type=sa.Integer(), nullable=True)
        # 复合唯一 → trace_id 单列唯一。
        batch_op.drop_constraint('uq_comparison_user_trace', type_='unique')
        batch_op.create_unique_constraint('uq_comparison_trace', ['trace_id'])


def downgrade() -> None:
    with op.batch_alter_table('comparison_record', schema=None) as batch_op:
        batch_op.drop_constraint('uq_comparison_trace', type_='unique')
        batch_op.create_unique_constraint(
            'uq_comparison_user_trace', ['user_id', 'trace_id']
        )
        # 回退非空前提是当时无 null user_id 行(harvest 期可能有孤儿行,回滚需先清理)。
        batch_op.alter_column('user_id', existing_type=sa.Integer(), nullable=False)
