#!/usr/bin/env python3
"""
Prismex — search the web via this product's HTTP API (same request body as REST / MCP).

Usage:
  export INSIGHTSEARCH_BASE_URL="https://your-host"
  export INSIGHTSEARCH_API_KEY="psk_..."
  python3 search.py '{"query":"example","count":10}'

INSIGHTSEARCH_BASE_URL and INSIGHTSEARCH_API_KEY are retained as Prismex
compatibility names. WEB_SEARCH_API_KEY is accepted as a key alias.
Stdlib only (urllib); no pip install required.
"""
from __future__ import annotations

import json
import os
import re
import sys
import urllib.error
import urllib.request
from typing import Any


def _env_base() -> str:
    return os.environ.get("INSIGHTSEARCH_BASE_URL", "").strip().rstrip("/")


def _env_key() -> str:
    return (
        os.environ.get("INSIGHTSEARCH_API_KEY", "").strip()
        or os.environ.get("WEB_SEARCH_API_KEY", "").strip()
    )


def _validate_freshness(raw: str) -> str | None:
    """Return error message if invalid; else None."""
    pattern = r"\d{4}-\d{2}-\d{2}to\d{4}-\d{2}-\d{2}"
    if raw in ("pd", "pw", "pm", "py"):
        return None
    if re.fullmatch(pattern, raw):
        return None
    return (
        f"freshness ({raw!r}) must be pd, pw, pm, py, or match {pattern}"
    )


def search_insight(base: str, api_key: str, body: dict[str, Any]) -> dict[str, Any]:
    url = f"{base}/api/v1/search"
    payload = json.dumps(body).encode("utf-8")
    req = urllib.request.Request(
        url,
        data=payload,
        method="POST",
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
    )
    try:
        with urllib.request.urlopen(req, timeout=120) as resp:
            text = resp.read().decode("utf-8")
    except urllib.error.HTTPError as e:
        err_body = e.read().decode("utf-8", errors="replace")
        raise RuntimeError(f"HTTP {e.code}: {err_body}") from e
    return json.loads(text)


def main() -> None:
    if len(sys.argv) < 2:
        print(
            'Usage: python3 search.py \'{"query":"keywords","count":10}\'',
            file=sys.stderr,
        )
        sys.exit(1)

    try:
        data = json.loads(sys.argv[1])
    except json.JSONDecodeError as e:
        print(f"JSON parse error: {e}", file=sys.stderr)
        sys.exit(1)

    q = data.get("query") if data.get("query") is not None else data.get("q")
    if not q or not str(q).strip():
        print("Error: query (or q) must be present and non-empty.", file=sys.stderr)
        sys.exit(1)

    count = 10
    if "count" in data:
        count = int(data["count"])
    elif "limit" in data:
        count = int(data["limit"])
    count = max(1, min(50, count))

    freshness: str | None = None
    if "freshness" in data and data["freshness"] is not None:
        freshness = str(data["freshness"]).strip()
        err = _validate_freshness(freshness)
        if err:
            print(f"Error: {err}", file=sys.stderr)
            sys.exit(1)

    base = _env_base()
    key = _env_key()
    if not base or not key:
        print(
            "Error: set INSIGHTSEARCH_BASE_URL and INSIGHTSEARCH_API_KEY "
            "(or WEB_SEARCH_API_KEY).",
            file=sys.stderr,
        )
        sys.exit(1)

    body: dict[str, Any] = {"query": str(q).strip(), "count": count}
    if freshness:
        body["freshness"] = freshness

    try:
        results = search_insight(base, key, body)
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)

    print(json.dumps(results, indent=2, ensure_ascii=False))


if __name__ == "__main__":
    main()
