"""One-shot: backfill paradisehill movie tags after regex fix.

Bug-report `3c999b27` 2026-05-21 "Brak kategorii, brak studia, brak aktorek" —
paradisehill connector miał broken regex (`</div></div><div class="similar"`)
który failował na nowym skinie z `</noindex>` w środku → fallback do html[:8000]
→ 0 tagów. Fix w `paradisehill.py` (re-relaxed boundary + `<a>` wrapper support);
ten skrypt re-scrapuje istniejące filmy żeby uzupełnić tagi które bug pominął.

Idempotent — re-run bez efektów ubocznych.
"""
from __future__ import annotations

import logging
import time

from sqlalchemy import select

from app.connectors.paradisehill import ParadisehillConnector, _parse_detail
from app.db import session_scope
from app.models import Movie, MovieExternalRef, Tag
from app.models.movie import MovieTag
from app.models.source import Source

log = logging.getLogger(__name__)


def main() -> int:
    logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
    c = ParadisehillConnector()
    done = 0
    new_tags_total = 0
    errors = 0

    with session_scope() as session:
        # Filtr: tylko paradisehill movies (sources.name = 'paradisehill') bez tagów.
        # Wcześniej szukałem po external_id NOT LIKE '%:%' co łapało też mangoporn/
        # pandamovies/streamporn (slugi bez `:`) → 404 spam.
        pdh_src_id = session.execute(
            select(Source.id).where(Source.name == "paradisehill")
        ).scalar_one()
        rows = session.execute(
            select(Movie.id, MovieExternalRef.external_id)
            .join(MovieExternalRef, MovieExternalRef.movie_id == Movie.id)
            .where(MovieExternalRef.source_id == pdh_src_id)
            .where(~Movie.id.in_(select(MovieTag.movie_id).distinct()))
        ).all()
    log.info("paradisehill movies without tags: %d", len(rows))

    for movie_id, hex_id in rows:
        try:
            r = c._client.get(f"/{hex_id}/")
            if r.status_code != 200:
                errors += 1
                continue
            raw_movie = _parse_detail(hex_id, r.text)
            if raw_movie is None or not raw_movie.tags:
                done += 1
                continue
            with session_scope() as s:
                for raw_tag in raw_movie.tags:
                    tag = s.execute(
                        select(Tag).where(Tag.slug == raw_tag.slug)
                    ).scalar_one_or_none()
                    if tag is None:
                        tag = Tag(name=raw_tag.name, slug=raw_tag.slug)
                        s.add(tag)
                        s.flush()
                    exists = s.execute(
                        select(MovieTag).where(
                            MovieTag.movie_id == movie_id,
                            MovieTag.tag_id == tag.id,
                        )
                    ).scalar_one_or_none()
                    if exists is None:
                        s.add(MovieTag(movie_id=movie_id, tag_id=tag.id))
                        new_tags_total += 1
            done += 1
            if done % 50 == 0:
                log.info(
                    "progress: done=%d/%d new_tags=%d errors=%d",
                    done, len(rows), new_tags_total, errors,
                )
            time.sleep(0.05)  # gentle rate-limit
        except Exception as e:
            errors += 1
            if errors <= 5:
                log.warning("hex=%s failed: %s", hex_id, e)

    log.info(
        "DONE: processed=%d/%d new_tags=%d errors=%d",
        done, len(rows), new_tags_total, errors,
    )
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
