"""Douyin formal acquisition adapter."""
from __future__ import annotations

from typing import Any, Iterable

from acquisition.content_mode import infer_content_mode
from acquisition.crawler import fetch_post_detail
from acquisition.platforms.base import PlatformCandidate, PlatformItem, PlatformSearchPage
from acquisition.search import SearchHit, search_douyin_hits, search_douyin_page
from core.config import Settings


class DouyinAdapter:
    platform = "douyin"

    def search(
        self,
        query: str,
        *,
        settings: Settings,
        limit: int,
        rate_limiter: Any,
    ) -> list[PlatformCandidate]:
        hits = search_douyin_hits(
            query,
            content_type="视频",
            limit=limit,
            settings=settings,
            rate_limiter=rate_limiter,
        )
        return [
            PlatformCandidate(
                rank=i,
                platform=self.platform,
                provider=hit.provider,
                source_id=hit.content_id,
                raw={
                    "id": hit.content_id,
                    "search_provider": hit.provider,
                    "original": hit.raw,
                    "request_payload": hit.request_payload,
                },
            )
            for i, hit in enumerate(hits, start=1)
        ]

    def search_pages(
        self,
        query: str,
        *,
        settings: Settings,
        limit: int,
        rate_limiter: Any,
        max_pages: int = 2,
    ) -> Iterable[PlatformSearchPage]:
        provider = "piaoquantv"
        cursors: dict[str, str] = {}
        rank = 1
        seen: set[str] = set()
        for page_index in range(1, max_pages + 1):
            page = search_douyin_page(
                query,
                provider=provider,
                cursors=cursors,
                content_type="视频",
                limit=limit,
                settings=settings,
                rate_limiter=rate_limiter,
            )
            candidates: list[PlatformCandidate] = []
            for page_rank, hit in enumerate(page.rows, start=1):
                if not isinstance(hit, SearchHit):
                    continue
                if not hit.content_id or hit.content_id in seen:
                    continue
                seen.add(hit.content_id)
                candidates.append(
                    PlatformCandidate(
                        rank=rank,
                        platform=self.platform,
                        provider=hit.provider,
                        source_id=hit.content_id,
                        raw={
                            "id": hit.content_id,
                            "search_provider": hit.provider,
                            "original": hit.raw,
                            "request_payload": hit.request_payload,
                            "page_index": page_index,
                            "page_rank": page_rank,
                            "source_cursor": page.cursor,
                        },
                    )
                )
                rank += 1
            yield PlatformSearchPage(
                page_index=page_index,
                candidates=candidates,
                raw_count=page.raw_count,
                cursor=page.cursor,
                next_cursor=page.next_cursor,
                has_more=page.has_more,
                provider=page.provider,
                request_payload=page.request_payload,
                raw_metadata=page.raw_metadata,
            )
            provider = page.provider
            cursors = dict(page.raw_metadata.get("cursors") or cursors)
            current_cursor = page.cursor
            if not page.has_more or not page.next_cursor or page.next_cursor == current_cursor:
                break

    def fetch_detail(
        self,
        candidate: PlatformCandidate,
        *,
        settings: Settings,
        rate_limiter: Any,
    ) -> PlatformItem:
        if not candidate.provider:
            raise RuntimeError("douyin candidate missing search provider")
        post = fetch_post_detail(
            candidate.source_id,
            platform=self.platform,
            provider=candidate.provider,
            settings=settings,
            rate_limiter=rate_limiter,
        )
        content_mode = infer_content_mode(
            platform=self.platform,
            content_type=post.content_type,
            body_text=post.body_text,
            image_urls=post.image_urls,
            video_urls=post.video_urls,
            raw=post.raw if isinstance(post.raw, dict) else {},
        )
        return PlatformItem(
            platform=self.platform,
            provider=post.provider or candidate.provider,
            source_id=post.content_id or candidate.source_id,
            url=post.url or candidate.url,
            content_type=post.content_type or "",
            content_mode=content_mode,
            title=post.title or candidate.title,
            author=post.author_name or candidate.author,
            body_text=post.body_text or "",
            image_urls=post.image_urls,
            video_urls=post.video_urls,
            raw=post.raw if isinstance(post.raw, dict) else {},
        )
