"""porndish.com — latest browse scraper via WordPress REST API.

Historia: dawniej search scraper (`?s=`), zamarzł 2026-05-07 (search przestał dawać
nowe sceny — 1151h cisza, watchdog GOON-16). To WordPress (g1/bimber theme), VPS
dociera, więc czysty kanał to REST API: `/wp-json/wp/v2/posts?_embed=1` daje
ustrukturyzowany JSON jednym requestem na stronę. Przerobione na browse 2026-06-24
(ten sam wzorzec co perverzija).

Z REST `_embed`: tytuł, data, miniatura (featured_media), STUDIO (taksonomia
`category` — np. "Freeuse Fantasy", content studyjny) i tagi (`post_tag` — porndish
miesza w nich performerów z gatunkami, bierzemy jak jest; canonical-merge i tak
dorabia performerów z TPDB/StashDB, a tytuł ma nazwiska). Performerów osobno nie
wyciągamy (post_tag ich nie rozdziela od gatunków bez listy known-performers).

Playback: post page embeduje hoster iframe → extractor `porndishcom` → `_embed_iframe`
→ resolwowany phone-side.
"""
from __future__ import annotations

import html
import json
import logging
from datetime import date, datetime

from app.connectors.base import (
    RawFingerprint,
    RawPlaybackSource,
    RawScene,
    RawStudio,
    RawTag,
)
from app.connectors.direct_scrapers._browse_base import (
    BaseBrowseScraper,
    compute_thumbnail_phash,
)
from app.extractors import browser_get
from app.normalize.text import slugify

log = logging.getLogger(__name__)

_BASE = "https://www.porndish.com"
_PER_PAGE = 20


def _parse_date(value: str | None) -> date | None:
    if not value:
        return None
    try:
        return datetime.fromisoformat(value.replace("Z", "+00:00")).date()
    except ValueError:
        return None


class PornDishScraper(BaseBrowseScraper):
    sitetag = "porndishcom"

    def _listing_url(self, page: int) -> str:
        return f"{_BASE}/wp-json/wp/v2/posts?per_page={_PER_PAGE}&page={page}&_embed=1"

    # crawl_page nadpisany (REST JSON, nie HTML) → abstrakcje nieużywane.
    def _extract_scene_urls(self, listing_html: str) -> list[str]:
        return []

    def _parse_detail(self, scene_url: str, detail_html: str) -> RawScene | None:
        return None

    def crawl_page(self, page: int) -> list[RawScene] | None:
        url = self._listing_url(page)
        try:
            res = browser_get(url, timeout=self._timeout)
        except Exception as e:
            log.warning("porndish REST fetch failed (page %d): %s", page, e)
            return None
        # WP zwraca 400 (rest_post_invalid_page_number) za ostatnią stroną → exhausted.
        if res.status_code != 200:
            return []
        try:
            posts = json.loads(res.text)
        except (json.JSONDecodeError, ValueError):
            log.warning("porndish REST: bad JSON page %d", page)
            return None
        if not isinstance(posts, list) or not posts:
            return []

        out: list[RawScene] = []
        for p in posts:
            link = (p.get("link") or "").strip()
            title = html.unescape((p.get("title") or {}).get("rendered", "")).strip()
            if not link or not title:
                continue
            release_date = _parse_date(p.get("date"))

            emb = p.get("_embedded") or {}
            fm = emb.get("wp:featuredmedia") or []
            thumb = (fm[0].get("source_url") if fm and isinstance(fm[0], dict) else None) or None

            studio: RawStudio | None = None
            tags: list[RawTag] = []
            seen_tag: set[str] = set()
            for group in emb.get("wp:term") or []:
                if not group:
                    continue
                tax = group[0].get("taxonomy")
                if tax == "category" and studio is None:
                    sname = (group[0].get("name") or "").strip()
                    if sname:
                        studio = RawStudio(
                            external_id=f"{self.sitetag}:studio:{slugify(sname)}",
                            name=sname, slug=slugify(sname),
                        )
                elif tax == "post_tag":
                    for g in group:
                        name = (g.get("name") or "").strip()
                        sl = (g.get("slug") or slugify(name)).strip()
                        if not name or sl in seen_tag:
                            continue
                        seen_tag.add(sl)
                        tags.append(RawTag(external_id=f"{self.sitetag}:tag:{sl}", name=name, slug=sl))

            fingerprints: list[RawFingerprint] = []
            if thumb:
                ph = compute_thumbnail_phash(thumb, referer=_BASE + "/")
                if ph:
                    fingerprints.append(RawFingerprint(kind="phash", value=ph))

            out.append(
                RawScene(
                    external_id=f"{self.sitetag}:{link}",
                    title=title,
                    release_date=release_date,
                    url=link,
                    studio=studio,
                    performers=[],
                    tags=tags,
                    fingerprints=fingerprints,
                    playback_sources=[
                        RawPlaybackSource(
                            origin=f"tube:{self.sitetag}",
                            page_url=link,
                            thumbnail_url=thumb,
                        )
                    ],
                )
            )

        log.info("porndish REST page %d: %d scenes", page, len(out))
        return out
