#!/usr/bin/env python3
"""
Recherche Perplexity Sonar pour la veille Fidulia (Agent 50).

Lit la clé depuis l'environnement (PERPLEXITY_API_KEY) si exportée, sinon
depuis ~/.config/fidulia/perplexity.env (chmod 600, hors repo). La clé n'est
JAMAIS imprimée. Réplique l'appel du workflow n8n `veille-cgp-perplexity.json`
mais en générique (Périmètres 1 à 4), pour la curation newsletter/posts.

Usage:
    perplexity_search.py "requête en langage naturel" \
        [--model sonar-pro] [--recency day|week|month] \
        [--domains site1.com,site2.com] [--max 8] [--system "prompt système"]

Sortie : le JSON strict renvoyé par le modèle ({"items":[{title,url,source,date,summary}]})
suivi de la liste des citations. Rien d'autre (pas la clé, pas les en-têtes).
"""
import argparse
import json
import os
import sys
import urllib.request
import urllib.error

ENV_FILE = os.path.expanduser("~/.config/fidulia/perplexity.env")
API_URL = "https://api.perplexity.ai/chat/completions"

DEFAULT_SYSTEM = (
    "Tu es un assistant de veille documentaire pour Fidulia, agence LinkedIn "
    "spécialisée dans l'accompagnement des professions de confiance (CGP, avocats, "
    "experts-comptables, notaires). Réponds UNIQUEMENT par un JSON valide, sans aucun "
    "texte autour, au format exact : {\"items\":[{\"title\":\"...\",\"url\":\"...\","
    "\"source\":\"...\",\"date\":\"YYYY-MM-DD\",\"summary\":\"...\"}]}. Chaque item doit "
    "être un fait vérifiable et sourcé (institution, presse sérieuse, rapport, doc "
    "officiel), jamais une opinion ni un post d'influenceur. Si aucune actualité "
    "pertinente n'est trouvée, renvoie {\"items\":[]} plutôt que d'inventer un item."
)


def load_env_file(path):
    values = {}
    try:
        with open(path, "r", encoding="utf-8") as f:
            for line in f:
                line = line.strip()
                if not line or line.startswith("#"):
                    continue
                if line.startswith("export "):
                    line = line[len("export "):]
                if "=" not in line:
                    continue
                key, _, val = line.partition("=")
                values[key.strip()] = val.strip().strip('"').strip("'")
    except OSError:
        pass
    return values


def get_key():
    key = os.environ.get("PERPLEXITY_API_KEY")
    if not key:
        key = load_env_file(ENV_FILE).get("PERPLEXITY_API_KEY")
    if not key:
        print(f"PERPLEXITY_API_KEY introuvable (ni env, ni {ENV_FILE}).", file=sys.stderr)
        sys.exit(1)
    return key


def main():
    p = argparse.ArgumentParser(description=__doc__)
    p.add_argument("query", help="Requête de veille en langage naturel")
    p.add_argument("--model", default="sonar-pro")
    p.add_argument("--recency", default="week", choices=["day", "week", "month", "year"])
    p.add_argument("--domains", default="", help="Liste de domaines séparés par des virgules (search_domain_filter)")
    p.add_argument("--max", type=int, default=8, help="Nombre max d'items demandés")
    p.add_argument("--system", default=DEFAULT_SYSTEM)
    args = p.parse_args()

    key = get_key()

    user_content = (
        f"{args.query}\n\nRenvoie au maximum {args.max} items, les plus importants et "
        f"les plus récents, chacun avec une source d'autorité vérifiable et son URL directe."
    )

    payload = {
        "model": args.model,
        "messages": [
            {"role": "system", "content": args.system},
            {"role": "user", "content": user_content},
        ],
        "search_recency_filter": args.recency,
        "return_citations": True,
    }
    domains = [d.strip() for d in args.domains.split(",") if d.strip()]
    if domains:
        payload["search_domain_filter"] = domains

    req = urllib.request.Request(
        API_URL,
        data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),
        headers={
            "Authorization": f"Bearer {key}",
            "Content-Type": "application/json",
        },
        method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=300) as resp:
            body = json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        # Ne jamais imprimer la clé : on n'affiche que le statut et le corps d'erreur.
        detail = e.read().decode("utf-8", "replace")[:500]
        print(f"Erreur HTTP {e.code} Perplexity: {detail}", file=sys.stderr)
        sys.exit(1)
    except urllib.error.URLError as e:
        print(f"Erreur réseau Perplexity: {e}", file=sys.stderr)
        sys.exit(1)

    content = (body.get("choices") or [{}])[0].get("message", {}).get("content", "{}")
    citations = body.get("citations") or body.get("search_results") or []

    print("=== ITEMS (JSON strict du modèle) ===")
    print(content)
    print("\n=== CITATIONS ===")
    print(json.dumps(citations, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()
