#!/usr/bin/env python3
"""A small Felo Data API tool for an agent's authorized execution environment."""
import argparse
import getpass
import json
import os
from pathlib import Path
import sys
import tempfile
import urllib.error
import urllib.request

ENDPOINT = "https://openapi.felo.ai/v1/beta/tavily/search"


def credential_path():
    return Path.home() / ".felo-data-api" / "credentials.json"


def configure():
    key = getpass.getpass("Felo API key: ").strip()
    if not key or "\n" in key or "\r" in key:
        raise ValueError("A non-empty API key is required")
    path = credential_path()
    path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
    with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", dir=path.parent, delete=False) as file:
        temporary = Path(file.name)
        json.dump({"FELO_API_KEY": key}, file)
    try:
        temporary.chmod(0o600)
        temporary.replace(path)
    finally:
        temporary.unlink(missing_ok=True)
    print(f"Configured: {path}")


def load_key():
    key = os.environ.get("FELO_API_KEY", "").strip()
    if not key:
        try:
            key = json.loads(credential_path().read_text(encoding="utf-8"))["FELO_API_KEY"]
            if not isinstance(key, str):
                raise ValueError("Invalid API key configuration")
            key = key.strip()
        except (FileNotFoundError, KeyError, TypeError, json.JSONDecodeError):
            raise ValueError("Run configure in this execution environment, or set FELO_API_KEY") from None
    if not key or "\n" in key or "\r" in key:
        raise ValueError("Invalid API key configuration")
    return key


class NoRedirect(urllib.request.HTTPRedirectHandler):
    def redirect_request(self, request, file, code, message, headers, newurl):
        return None


def search(query):
    if not query.strip():
        raise ValueError("A search query is required")
    request = urllib.request.Request(
        ENDPOINT,
        data=json.dumps({"query": query, "max_results": 3}).encode("utf-8"),
        headers={"Authorization": f"Bearer {load_key()}", "Content-Type": "application/json"},
        method="POST",
    )
    try:
        with urllib.request.build_opener(NoRedirect()).open(request, timeout=30) as response:
            data = json.loads(response.read(8 * 1024 * 1024).decode("utf-8"))
    except urllib.error.HTTPError as error:
        raise ValueError(f"Felo Data API returned HTTP {error.code}") from None
    except urllib.error.URLError:
        raise ValueError("Could not reach Felo Data API; check network access") from None
    if not isinstance(data, dict) or not isinstance(data.get("results"), list):
        raise ValueError("Unexpected response: expected a results array")
    return {
        "query": data.get("query", query),
        "results": [{field: item.get(field, "") for field in ("title", "url", "content")} for item in data["results"] if isinstance(item, dict)],
        "request_id": data.get("request_id"),
    }


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    commands = parser.add_subparsers(dest="command", required=True)
    commands.add_parser("configure", help="Save a key locally without echoing it")
    query = commands.add_parser("search", help="Call the Felo Tavily search endpoint")
    query.add_argument("query")
    args = parser.parse_args()
    try:
        if args.command == "configure":
            configure()
        else:
            print(json.dumps(search(args.query), ensure_ascii=False, indent=2))
    except (ValueError, OSError) as error:
        print(str(error), file=sys.stderr)
        return 1
    return 0


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