"""Autonomous "look online": find a real product photo for a request and pull it
local, so the Pi agent's web step is one reliable call.

  .cad-venv/bin/python scripts/find_reference.py \
    --name r1-0-oval-halo --query "2 carat oval halo engagement ring white gold"

Searches the web, walks the top results for an og:image, downloads the first that
is a real raster image, and records it on the design's eval entry (delegating the
download/record to fetch_reference.py). Exits nonzero if nothing usable is found —
the agent can then search itself and call fetch_reference.py with an explicit URL.
"""

from __future__ import annotations

import argparse
import re
import subprocess
import sys
import urllib.parse
import urllib.request
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
PY = str(ROOT / ".cad-venv" / "bin" / "python")
UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36"
# Prefer retailer pages — their og:image is the clean packshot we want to match.
PREFER = ("vrai.com", "brilliantearth.com", "blissdiamond.com", "ravendiamonds.com",
          "jamesallen.com", "withclarity.com", "gabrielny.com", "shaneco.com",
          "bluenile.com", "diamondmansion.com", "pompeii3.com", "ritani.com")
SKIP = ("bing.com", "microsoft.com", "duckduckgo.com", "google.com", "youtube.com",
        "pinterest.", "amazon.com", "etsy.com", "facebook.com", "instagram.com")


def _get(url: str, timeout: int = 20) -> str:
    req = urllib.request.Request(url, headers={"User-Agent": UA, "Accept": "text/html"})
    with urllib.request.urlopen(req, timeout=timeout) as r:
        return r.read(2_000_000).decode("utf-8", "replace")


def _result_links(query: str) -> list[str]:
    """Scrape organic result URLs from DuckDuckGo-lite (uddg-wrapped links)."""
    out: list[str] = []
    for engine in (
        "https://lite.duckduckgo.com/lite/?q=" + urllib.parse.quote(query),
        "https://html.duckduckgo.com/html/?q=" + urllib.parse.quote(query),
    ):
        try:
            html = _get(engine)
        except Exception:
            continue
        for m in re.finditer(r'[?&]uddg=([^&"]+)', html):
            u = urllib.parse.unquote(m.group(1))
            host = urllib.parse.urlparse(u).netloc.lower()
            if "y.js" in u or any(s in host for s in SKIP) or u in out:
                continue
            out.append(u)
        if out:
            break
    # Retailers first, then the rest — stable, no randomness.
    out.sort(key=lambda u: 0 if any(p in u for p in PREFER) else 1)
    return out[:8]


def _norm(img: str) -> str | None:
    if img.startswith("//"):
        img = "https:" + img
    return img if img.startswith("http") else None


def _og_image(page_url: str) -> str | None:
    try:
        html = _get(page_url)
    except Exception:
        return None
    # 1) og:image / twitter:image meta (either attribute order)
    for pat in (r'<meta[^>]+property=["\']og:image(?::secure_url)?["\'][^>]+content=["\']([^"\']+)',
                r'<meta[^>]+content=["\']([^"\']+)["\'][^>]+property=["\']og:image',
                r'<meta[^>]+name=["\']twitter:image["\'][^>]+content=["\']([^"\']+)'):
        m = re.search(pat, html, re.I)
        if m and (u := _norm(m.group(1))):
            return u
    # 2) JSON-LD product image ("image":"..." or "image":["..."])
    m = re.search(r'"image"\s*:\s*"([^"]+\.(?:jpg|jpeg|png|webp)[^"]*)"', html, re.I)
    if m and (u := _norm(m.group(1))):
        return u
    # 3) largest-looking product <img> (shopify/cdn packshots)
    for m in re.finditer(r'<img[^>]+src=["\']([^"\']+\.(?:jpg|jpeg|png|webp)[^"\']*)', html, re.I):
        u = _norm(m.group(1))
        if u and any(k in u.lower() for k in ("product", "cdn", "/files/", "/i/", "ring")):
            return u
    return None


def main() -> int:
    p = argparse.ArgumentParser()
    p.add_argument("--name", required=True)
    p.add_argument("--query", required=True)
    args = p.parse_args()

    links = _result_links(args.query)
    if not links:
        print(f"no search results for: {args.query}", file=sys.stderr)
        return 3

    for page in links:
        img = _og_image(page)
        if not img:
            continue
        host = urllib.parse.urlparse(page).netloc.replace("www.", "")
        r = subprocess.run(
            [PY, "harness/fetch.py", "--name", args.name,
             "--image-url", img, "--page-url", page, "--source", host],
            cwd=ROOT, capture_output=True, text=True)
        if r.returncode == 0:
            print(r.stdout.strip() or f"reference: {img}")
            return 0
        # else: not a real image / download failed — try the next result.

    print(f"found {len(links)} pages but no usable og:image for: {args.query}",
          file=sys.stderr)
    return 4


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