#!/usr/bin/env python3
"""将 multi_demand_video_detail 三个 JSON 点位列迁移到 multi_demand_video_point 表。

用法:
    python jobs/backfill_multi_demand_video_points_table.py
    python jobs/backfill_multi_demand_video_points_table.py 500   # 每批 500 条视频
"""

from __future__ import annotations

import logging
import sys

from sqlalchemy import select

from supply_infra.db.models.multi_demand_video_detail import MultiDemandVideoDetail
from supply_infra.db.repositories.multi_demand_video_point_repo import (
    MultiDemandVideoPointRepository,
)
from supply_infra.db.session import get_session
from supply_infra.video_points import points_from_json_fields

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
)
logger = logging.getLogger(__name__)

_DEFAULT_BATCH_SIZE = 200


def backfill_video_points_table(batch_size: int = _DEFAULT_BATCH_SIZE) -> dict:
    """从 detail 表 JSON 列回填点位表，跳过已迁移的 video_id。"""
    chunk = max(1, int(batch_size))
    total_rows = 0
    total_points = 0
    batches = 0
    offset = 0

    while True:
        with get_session() as session:
            stmt = (
                select(MultiDemandVideoDetail)
                .where(
                    MultiDemandVideoDetail.inspiration_points_json.is_not(None)
                    | MultiDemandVideoDetail.purpose_points_json.is_not(None)
                    | MultiDemandVideoDetail.key_points_json.is_not(None)
                )
                .order_by(MultiDemandVideoDetail.id)
                .offset(offset)
                .limit(chunk)
            )
            rows = list(session.scalars(stmt).all())
            if not rows:
                break

            vids = [str(row.vid) for row in rows if row.vid]
            existing = MultiDemandVideoPointRepository(session).list_video_ids_with_points(
                vids
            )

            points_by_vid: dict[str, list] = {}
            for row in rows:
                vid = str(row.vid).strip() if row.vid else ""
                if not vid or vid in existing:
                    continue
                point_rows = points_from_json_fields(
                    vid,
                    inspiration_points_json=row.inspiration_points_json,
                    purpose_points_json=row.purpose_points_json,
                    key_points_json=row.key_points_json,
                )
                if point_rows:
                    points_by_vid[vid] = point_rows

            inserted = 0
            if points_by_vid:
                inserted = MultiDemandVideoPointRepository(session).replace_for_video_ids(
                    points_by_vid
                )

        batch_count = len(rows)
        migrated = len(points_by_vid)
        total_rows += batch_count
        total_points += inserted
        batches += 1
        offset += batch_count
        logger.info(
            "Batch %d: scanned=%d migrated_videos=%d inserted_points=%d offset=%d",
            batches,
            batch_count,
            migrated,
            inserted,
            offset,
        )

        if batch_count < chunk:
            break

    result = {
        "batches": batches,
        "scanned_rows": total_rows,
        "inserted_points": total_points,
    }
    logger.info("Backfill multi_demand_video_point completed: %s", result)
    return result


def main(batch_arg: str | None = None) -> dict:
    batch_size = int(batch_arg) if batch_arg else _DEFAULT_BATCH_SIZE
    result = backfill_video_points_table(batch_size=batch_size)
    print(result)
    return result


if __name__ == "__main__":
    main(sys.argv[1] if len(sys.argv) > 1 else None)
