"""One-shot migration: paradisehill scenes → movies.

Paradisehill content jest faktycznie filmami (`og:type=video.movie`),
ale wczesna implementacja wlądowała je w `scenes` table. Ten skrypt
przenosi 73 entries z `scenes` do `movies` z zachowaniem UUID, performers,
tags, studios, external_refs i playback_sources. Po migracji DELETE z scenes
cascades pozostałe linki.

Bezpieczne:
- 0 favorite_scenes, 0 scene_play_progress, 0 bug_reports, 0 movie_chapters
  (zweryfikowano 2026-05-15)
- 0 stashdb/tpdb refs (poza 1+1 — accepted loss; matche były nietrafione)
- pornapp refs przenosimy do movie_external_refs (reuse source_id)
"""
from __future__ import annotations

import sys
from sqlalchemy import text

sys.path.insert(0, "/srv")
from app.db import SessionLocal

ORIGIN = "tube:paradisehillcc"


def main() -> None:
    with SessionLocal() as session, session.begin():
        # 0. Collect scene IDs
        scene_ids = session.execute(
            text(
                "SELECT DISTINCT scene_id FROM playback_sources "
                "WHERE origin = :origin AND dead_at IS NULL"
            ),
            {"origin": ORIGIN},
        ).scalars().all()
        print(f"scenes to migrate: {len(scene_ids)}")
        if not scene_ids:
            print("nothing to do")
            return

        params = {"ids": [str(sid) for sid in scene_ids]}

        # 1. Movies — preserve UUID. scenes.title may exceed VARCHAR(512) movies.title
        #    constraint; clamp w SELECT.
        ins_movies = session.execute(
            text(
                """
                INSERT INTO movies (
                    id, title, title_normalized, slug,
                    release_date, release_year,
                    studio_id, director, duration_sec, description,
                    created_at, updated_at
                )
                SELECT
                    s.id,
                    LEFT(s.title, 512),
                    LEFT(s.title_normalized, 512),
                    LEFT(s.slug, 512),
                    s.release_date,
                    EXTRACT(YEAR FROM s.release_date)::int,
                    s.studio_id,
                    s.director,
                    s.duration_sec,
                    s.description,
                    s.created_at,
                    s.updated_at
                FROM scenes s
                WHERE s.id = ANY(CAST(:ids AS uuid[]))
                ON CONFLICT (id) DO NOTHING
                """
            ),
            params,
        )
        print(f"movies inserted: {ins_movies.rowcount}")

        # 2. Performers (scene_performers has different shape — check first)
        ins_perf = session.execute(
            text(
                """
                INSERT INTO movie_performers (movie_id, performer_id, as_alias)
                SELECT sp.scene_id, sp.performer_id, sp.as_alias
                FROM scene_performers sp
                WHERE sp.scene_id = ANY(CAST(:ids AS uuid[]))
                ON CONFLICT (movie_id, performer_id) DO NOTHING
                """
            ),
            params,
        )
        print(f"movie_performers inserted: {ins_perf.rowcount}")

        # 3. Tags
        ins_tags = session.execute(
            text(
                """
                INSERT INTO movie_tags (movie_id, tag_id, source_id)
                SELECT st.scene_id, st.tag_id, st.source_id
                FROM scene_tags st
                WHERE st.scene_id = ANY(CAST(:ids AS uuid[]))
                ON CONFLICT (movie_id, tag_id) DO NOTHING
                """
            ),
            params,
        )
        print(f"movie_tags inserted: {ins_tags.rowcount}")

        # 4. External refs (preserve confidence + URL + first/last seen)
        ins_refs = session.execute(
            text(
                """
                INSERT INTO movie_external_refs (
                    source_id, external_id, movie_id, confidence, url, first_seen, last_seen
                )
                SELECT
                    ser.source_id, ser.external_id, ser.scene_id,
                    COALESCE(ser.confidence, 1.0),
                    ser.url, ser.first_seen, ser.last_seen
                FROM scene_external_refs ser
                WHERE ser.scene_id = ANY(CAST(:ids AS uuid[]))
                ON CONFLICT (source_id, external_id) DO NOTHING
                """
            ),
            params,
        )
        print(f"movie_external_refs inserted: {ins_refs.rowcount}")

        # 5. Playback sources (origin keeps `tube:paradisehillcc` — to potem zaktualizujemy
        #    osobnym statementem na `paradisehill` żeby pasowało do nowego ingest origin)
        ins_pb = session.execute(
            text(
                """
                INSERT INTO movie_playback_sources (
                    id, movie_id, origin, page_url, embed_url, stream_url,
                    quality, duration_sec, thumbnail_url, animated_thumbnail_url,
                    last_seen_at, dead_at, dead_reason, created_at, updated_at
                )
                SELECT
                    ps.id, ps.scene_id,
                    'paradisehill',  -- normalizujemy origin na nowy
                    ps.page_url, ps.embed_url, ps.stream_url,
                    ps.quality, ps.duration_sec, ps.thumbnail_url, ps.animated_thumbnail_url,
                    ps.last_seen_at, ps.dead_at, ps.dead_reason, ps.created_at, ps.updated_at
                FROM playback_sources ps
                WHERE ps.scene_id = ANY(CAST(:ids AS uuid[]))
                ON CONFLICT (origin, page_url) DO NOTHING
                """
            ),
            params,
        )
        print(f"movie_playback_sources inserted: {ins_pb.rowcount}")

        # 6. Delete scenes — CASCADE drops scene_performers/tags/external_refs/
        #    fingerprints/playback_sources/play_progress/favorites automatycznie.
        del_scenes = session.execute(
            text("DELETE FROM scenes WHERE id = ANY(CAST(:ids AS uuid[]))"),
            params,
        )
        print(f"scenes deleted: {del_scenes.rowcount}")

        # Verify
        leftover = session.execute(
            text("SELECT COUNT(*) FROM playback_sources WHERE origin = :origin"),
            {"origin": ORIGIN},
        ).scalar_one()
        movies_count = session.execute(
            text("SELECT COUNT(*) FROM movie_playback_sources WHERE origin = 'paradisehill'"),
        ).scalar_one()
        print(f"\nverify:")
        print(f"  remaining playback_sources origin={ORIGIN}: {leftover}")
        print(f"  movie_playback_sources origin=paradisehill: {movies_count}")


if __name__ == "__main__":
    main()
