#!/usr/bin/env python3
"""Search/download Pixabay images or videos with mandatory 24-hour cache and provenance.

NOTE: `scripts/stock_media.py` supersedes this script. It searches every
configured provider at once, deduplicates the results, builds a contact sheet
so the choice is visual, and verifies each download with ffprobe:

    python scripts/stock_media.py "запрос" --kind video --providers pixabay \n      --orientation portrait --sheet candidates.jpg

This one is kept because existing project scripts call it."""
from __future__ import annotations

import argparse
import hashlib
import json
import sys
import time
from datetime import datetime, timezone
from pathlib import Path

import requests

from skill_config import SKILL_ROOT, require_secret


def cached_json(endpoint: str, params: dict, cache: Path, ttl: int = 86400) -> dict:
    cache.parent.mkdir(parents=True, exist_ok=True)
    if cache.exists() and time.time() - cache.stat().st_mtime < ttl:
        return json.loads(cache.read_text(encoding="utf-8"))
    response = requests.get(endpoint, params=params, headers={"User-Agent": "AI-Pro-Video-Skill/3"}, timeout=30)
    if response.status_code >= 400:
        raise SystemExit(f"Pixabay API request failed with HTTP {response.status_code}")
    data = response.json()
    cache.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
    return data


def download(url: str, out: Path) -> None:
    out.parent.mkdir(parents=True, exist_ok=True)
    with requests.get(url, stream=True, timeout=180) as response:
        response.raise_for_status()
        with out.open("wb") as handle:
            for chunk in response.iter_content(1024 * 1024):
                if chunk:
                    handle.write(chunk)

def merge_manifest(path: Path, new_items: list[dict]) -> list[dict]:
    existing = []
    if path.exists():
        existing = json.loads(path.read_text(encoding="utf-8"))
    merged = {(item.get("provider"), item.get("id")): item for item in existing}
    for item in new_items:
        merged[(item.get("provider"), item.get("id"))] = item
    return sorted(merged.values(), key=lambda item: (str(item.get("provider")), int(item.get("id") or 0)))


def main() -> None:
    if hasattr(sys.stdout, "reconfigure"):
        sys.stdout.reconfigure(encoding="utf-8", errors="replace")
    parser = argparse.ArgumentParser()
    parser.add_argument("query")
    parser.add_argument("--type", choices=["video", "image"], default="video")
    parser.add_argument("--orientation", choices=["vertical", "horizontal", "all"], default="vertical")
    parser.add_argument("--count", type=int, default=5)
    parser.add_argument("--out", default="project/assets/stock/pixabay")
    parser.add_argument("--cache", default=str(SKILL_ROOT / "cache" / "pixabay"))
    parser.add_argument("--search-only", action="store_true")
    parser.add_argument("--ids", help="Comma-separated Pixabay IDs to download after review")
    args = parser.parse_args()
    key = require_secret("PIXABAY_API_KEY")
    params = {"key": key, "q": args.query, "per_page": min(max(args.count * 3, 3), 200), "safesearch": "true"}
    if args.orientation != "all":
        params["orientation"] = args.orientation
    endpoint = "https://pixabay.com/api/videos/" if args.type == "video" else "https://pixabay.com/api/"
    signature = json.dumps({k: v for k, v in params.items() if k != "key"}, sort_keys=True)
    cache_name = hashlib.sha256((endpoint + signature).encode()).hexdigest() + ".json"
    data = cached_json(endpoint, params, Path(args.cache) / cache_name)
    allowed = {int(value) for value in args.ids.split(",")} if args.ids else None
    candidates = []
    manifest = []
    outdir = Path(args.out)
    for hit in data.get("hits", []):
        if args.type == "video":
            variants = hit.get("videos", {})
            selected = variants.get("large") or variants.get("medium") or variants.get("small")
            media_url = selected.get("url") if selected else None
            width = selected.get("width") if selected else None
            height = selected.get("height") if selected else None
            extension = ".mp4"
        else:
            media_url = hit.get("largeImageURL") or hit.get("webformatURL")
            width = hit.get("imageWidth")
            height = hit.get("imageHeight")
            extension = ".jpg"
        if not media_url:
            continue
        candidate = {
            "provider": "pixabay",
            "id": hit.get("id"),
            "width": width,
            "height": height,
            "duration": hit.get("duration"),
            "source_page": hit.get("pageURL"),
            "creator": hit.get("user"),
            "tags": hit.get("tags"),
        }
        candidates.append(candidate)
        if not args.search_only and (allowed is None or hit.get("id") in allowed):
            out = outdir / f"pixabay_{hit.get('id')}{extension}"
            download(media_url, out)
            manifest.append({
                **candidate,
                "local_path": str(out),
                "license": "Pixabay Content License",
                "query": args.query,
                "downloaded_at": datetime.now(timezone.utc).isoformat(),
                "attribution": f"{args.type.title()} by {hit.get('user')} on Pixabay",
            })
        if len(candidates) >= args.count:
            break
    if not args.search_only:
        outdir.mkdir(parents=True, exist_ok=True)
        manifest_path = outdir / "manifest.json"
        merged = merge_manifest(manifest_path, manifest)
        manifest_path.write_text(json.dumps(merged, ensure_ascii=False, indent=2), encoding="utf-8")
    print(json.dumps({"query": args.query, "candidates": candidates, "downloaded": manifest}, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()
