"""
Market2Agent — The Trust Hook
This is the file that makes trust scoring a one-liner.

    from market2agent import trust
    result = trust("stripe.com")

That's it. That's the integration.

The hook manages a singleton client, reads the API key from the
environment, and provides the simplest possible interface.

Configuration (pick one):
    1. Environment variable: MARKET2AGENT_API_KEY=m2a_live_...
    2. Explicit:             configure(api_key="m2a_live_...")
    3. Constructor:          TrustClient(api_key="m2a_live_...")

Why a global hook?
    Because the model works on FRICTION REDUCTION.
    The fewer lines it takes to check trust, the more people check trust.
    The more people check trust, the more scores get pulled.
    The more scores get pulled, the more data accumulates.
    The more data accumulates, the better the scores get.
    Flywheel.
"""
import os
import functools
from typing import Optional, Callable, Any

from market2agent.client import TrustClient, AsyncTrustClient, TrustResult


# ── Singleton Configuration ───────────────────────

_config = {
    "api_key": None,
    "base_url": "https://api.market2agent.ai",
    "timeout": 15.0,
}

_sync_client: Optional[TrustClient] = None
_async_client: Optional[AsyncTrustClient] = None


def configure(
    api_key: Optional[str] = None,
    base_url: Optional[str] = None,
    timeout: Optional[float] = None,
):
    """
    Configure the global trust hook.

    Call this once at app startup, or just set MARKET2AGENT_API_KEY
    in your environment and never call this at all.

        import market2agent
        market2agent.configure(api_key="m2a_live_...")

    Or:
        export MARKET2AGENT_API_KEY=m2a_live_...
    """
    global _sync_client, _async_client

    if api_key is not None:
        _config["api_key"] = api_key
    if base_url is not None:
        _config["base_url"] = base_url
    if timeout is not None:
        _config["timeout"] = timeout

    # Reset clients so they pick up new config
    _sync_client = None
    _async_client = None


def _get_api_key() -> str:
    """Resolve API key from config or environment."""
    key = _config["api_key"] or os.environ.get("MARKET2AGENT_API_KEY", "")
    if not key:
        raise ValueError(
            "No API key configured. Either:\n"
            "  1. Set MARKET2AGENT_API_KEY environment variable\n"
            "  2. Call market2agent.configure(api_key='m2a_live_...')\n"
            "  3. Use TrustClient(api_key='m2a_live_...') directly\n\n"
            "Get your key at https://market2agent.ai"
        )
    return key


def _get_sync_client() -> TrustClient:
    """Get or create the singleton sync client."""
    global _sync_client
    if _sync_client is None:
        _sync_client = TrustClient(
            api_key=_get_api_key(),
            base_url=_config["base_url"],
            timeout=_config["timeout"],
        )
    return _sync_client


def _get_async_client() -> AsyncTrustClient:
    """Get or create the singleton async client."""
    global _async_client
    if _async_client is None:
        _async_client = AsyncTrustClient(
            api_key=_get_api_key(),
            base_url=_config["base_url"],
            timeout=_config["timeout"],
        )
    return _async_client


# ── The Hook ──────────────────────────────────────

def trust(target: str) -> TrustResult:
    """
    Check the trust score of any entity. One line.

        from market2agent import trust

        result = trust("stripe.com")
        result.score        # 875
        result.grade        # "AAA"
        result.is_safe      # True
        result.risk_summary # "stripe.com: Highly trusted (AAA, score 875)"

        result = trust("sketchy-payments.xyz")
        result.score        # 120
        result.should_reject  # True

    Accepts anything: domain, URL, company name, email, agent ID.
    Returns a TrustResult with score, grade, recommendation, and signals.

    This calls the Market2Agent API. Each call counts against your quota.
    Free preview available at market2agent.ai — no key required.
    """
    return _get_sync_client().score(target)


async def trust_async(target: str) -> TrustResult:
    """
    Async version of trust(). For AI agent frameworks, async web servers, etc.

        from market2agent import trust_async

        result = await trust_async("stripe.com")
        if result.is_safe:
            await execute_transaction()
    """
    return await _get_async_client().score(target)


# ── The Decorator ─────────────────────────────────

def require_trust(
    target: str,
    min_score: int = 500,
    on_fail: str = "raise",
):
    """
    Decorator that gates a function behind a trust check.

        from market2agent import require_trust

        @require_trust("stripe.com", min_score=600)
        def process_payment():
            ...

        @require_trust("api.partner.io", min_score=400, on_fail="skip")
        def sync_data():
            ...

    Args:
        target: Entity to check (domain, URL, name, etc.)
        min_score: Minimum trust score required (0-1000)
        on_fail: What to do if trust check fails:
            "raise" — raise TrustCheckError (default)
            "skip"  — return None silently
            "log"   — log warning and proceed anyway

    The trust score is fetched ONCE and cached for the function's lifetime.
    """
    def decorator(func: Callable) -> Callable:
        _cached_result: dict = {}

        @functools.wraps(func)
        def wrapper(*args, **kwargs) -> Any:
            # Check trust (cached after first call)
            if "result" not in _cached_result:
                _cached_result["result"] = trust(target)

            result = _cached_result["result"]

            if result.score >= min_score:
                return func(*args, **kwargs)

            # Trust check failed
            msg = (
                f"Trust check failed for '{target}': "
                f"score {result.score} < required {min_score} "
                f"(grade: {result.grade}, rec: {result.recommendation})"
            )

            if on_fail == "raise":
                from market2agent.client import TrustCheckError
                raise TrustCheckError(msg, status_code=0)
            elif on_fail == "skip":
                return None
            elif on_fail == "log":
                import logging
                logging.warning(f"[market2agent] {msg}")
                return func(*args, **kwargs)
            else:
                return func(*args, **kwargs)

        return wrapper
    return decorator
