"""Openverse provider.

Zero-config (no API key required). Indexes openly licensed images across
Wikimedia, Flickr, museums, and other sources.

API docs: https://api.openverse.org/v1/
"""

from __future__ import annotations

import sys
from pathlib import Path

_SCRIPTS_DIR = Path(__file__).resolve().parents[1]
if str(_SCRIPTS_DIR) not in sys.path:
    sys.path.insert(0, str(_SCRIPTS_DIR))

from console_encoding import configure_utf8_stdio  # noqa: E402

configure_utf8_stdio()

if __name__ == "__main__":
    print(__doc__)
    print("Use via: python3 skills/ppt-master/scripts/image_search.py ...")
    raise SystemExit(0 if any(arg in {"-h", "--help", "help"} for arg in sys.argv[1:]) else 1)

import requests

from image_sources.provider_common import (
    AssetCandidate,
    ImageSearchRequest,
    USER_AGENT,
    build_query_progression,
    classify_license,
    normalize_license_name,
)


API_URL = "https://api.openverse.org/v1/images/"
DEFAULT_PAGE_SIZE = 20
DEFAULT_TIMEOUT = 30

# Map our orientation vocabulary to Openverse's ``aspect_ratio`` parameter.
_ASPECT_MAP = {"landscape": "wide", "portrait": "tall", "square": "square"}

# Openverse license param values. ``cc0,pdm`` covers our "no-attribution" tier;
# adding ``by,by-sa`` opens the "attribution-required" tier.
_LICENSE_PARAM = {
    "no-attribution-only": "cc0,pdm",
    "all": "by,by-sa,cc0,pdm",
}


def parse_results(payload: dict) -> list[AssetCandidate]:
    """Translate an Openverse search payload into a list of candidates."""
    candidates: list[AssetCandidate] = []
    for item in payload.get("results", []) or []:
        license_name = (item.get("license") or "").strip()
        license_url = (item.get("license_url") or "").strip()
        tier = classify_license(license_name, license_url, provider="openverse")
        if not tier:
            continue

        download_url = (item.get("url") or item.get("thumbnail") or "").strip()
        if not download_url:
            continue

        candidates.append(
            AssetCandidate(
                provider="openverse",
                title=(item.get("title") or "").strip() or "Untitled",
                asset_id=str(item.get("id") or ""),
                source_page_url=(
                    item.get("foreign_landing_url") or item.get("detail_url") or ""
                ).strip(),
                license_name=normalize_license_name(license_name),
                license_url=license_url,
                license_tier=tier,
                width=int(item.get("width") or 0),
                height=int(item.get("height") or 0),
                download_url=download_url,
                author=(item.get("creator") or "").strip(),
                raw=item,
            )
        )
    return candidates


def search(
    request: ImageSearchRequest,
    *,
    license_tier_filter: str = "no-attribution-only",
    page_size: int = DEFAULT_PAGE_SIZE,
    timeout: int = DEFAULT_TIMEOUT,
) -> list[AssetCandidate]:
    """Search Openverse for candidates matching ``request``.

    ``license_tier_filter`` is one of ``"no-attribution-only"`` or ``"all"``.
    Returns the candidates from the first non-empty query in the
    progression — caller is responsible for picking the best one via
    ``score_candidate``.
    """
    if license_tier_filter not in _LICENSE_PARAM:
        raise ValueError(f"unsupported license_tier_filter: {license_tier_filter!r}")

    orientation = (request.orientation or "").strip().lower()

    for query in build_query_progression(request.query):
        params: dict[str, str | int] = {
            "q": query,
            "page_size": page_size,
            "license": _LICENSE_PARAM[license_tier_filter],
            "size": "large",
        }
        if orientation in _ASPECT_MAP:
            params["aspect_ratio"] = _ASPECT_MAP[orientation]

        response = requests.get(
            API_URL,
            params=params,
            headers={"User-Agent": USER_AGENT, "Accept": "application/json"},
            timeout=timeout,
        )
        response.raise_for_status()
        candidates = parse_results(response.json())
        if candidates:
            return candidates

    return []
