"""LangChain tools wrapping egg-verify's x402 research API."""

from __future__ import annotations

import json
from typing import Any, List, Optional, Type

from langchain_core.tools import BaseTool
from pydantic import BaseModel, Field, PrivateAttr

from langchain_egg_verify.client import EggVerifyClient, PaidResult


def _format(result: PaidResult) -> str:
    out: dict[str, Any] = {"result": result.body}
    if result.transaction:
        out["payment"] = {
            "transaction": result.transaction,
            "network": result.settlement.get("network"),
            "payer": result.settlement.get("payer"),
        }
    return json.dumps(out, default=str)


class _EggTool(BaseTool):
    client: Optional[EggVerifyClient] = None
    _client: EggVerifyClient = PrivateAttr()
    model_config = {"arbitrary_types_allowed": True}

    def model_post_init(self, __context: Any) -> None:
        self._client = self.client or EggVerifyClient()


class _VerifyArgs(BaseModel):
    claim: str = Field(..., max_length=500, description="The factual claim to check.")
    url: str = Field(..., description="Public http(s) URL (HTML or PDF) to check it against.")


class EggVerifyClaimTool(_EggTool):
    """Paid ($0.05 USDC on Base via x402): fact-check a claim against a URL."""

    name: str = "egg_verify_claim"
    description: str = (
        "Fact-check one claim against one public web page or PDF. Returns SUPPORTED, "
        "REFUTED or UNCLEAR with a confidence and verbatim quotes from the page. "
        "Costs $0.05 USDC per call, paid automatically over x402; failed calls are not "
        "charged. The verdict is an automated keyword-overlap heuristic, so treat "
        "UNCLEAR as 'read the quotes yourself'."
    )
    args_schema: Type[BaseModel] = _VerifyArgs

    def _run(self, claim: str, url: str, run_manager: Any = None) -> str:
        return _format(self._client.verify(claim, url))


class _BriefArgs(BaseModel):
    brief: str = Field(..., max_length=500, description="What you want to learn.")
    urls: List[str] = Field(..., min_length=1, description="Public URLs to read.")


class EggScoutTool(_EggTool):
    """Paid ($0.50): extractive summary of up to 3 URLs."""

    name: str = "egg_scout"
    description: str = (
        "Summarise up to 3 public URLs against a brief: summary, key points per source "
        "and verbatim quotes (extractive, no LLM). Costs $0.50 USDC per call over x402. "
        "Needs max_usdc_per_call >= 0.50 on the client."
    )
    args_schema: Type[BaseModel] = _BriefArgs

    def _run(self, brief: str, urls: List[str], run_manager: Any = None) -> str:
        return _format(self._client.scout(brief, urls))


class EggDeepDiveTool(_EggTool):
    """Paid ($2.00): cross-source synthesis of up to 8 URLs."""

    name: str = "egg_deepdive"
    description: str = (
        "Cross-source synthesis of up to 8 public URLs against a brief, with per-source "
        "quotes and open questions. Costs $2.00 USDC per call over x402. Needs "
        "max_usdc_per_call >= 2.00 on the client."
    )
    args_schema: Type[BaseModel] = _BriefArgs

    def _run(self, brief: str, urls: List[str], run_manager: Any = None) -> str:
        return _format(self._client.deepdive(brief, urls))


class _NoArgs(BaseModel):
    pass


class EggServiceCardTool(_EggTool):
    """Free: egg-verify's endpoints and prices."""

    name: str = "egg_service_card"
    description: str = "Free. egg-verify's endpoints, prices and payment network."
    args_schema: Type[BaseModel] = _NoArgs

    def _run(self, run_manager: Any = None) -> str:
        card = self._client.service_card()
        return json.dumps({k: card.get(k) for k in ("name", "endpoints", "prices", "network")})


def get_egg_verify_tools(client: Optional[EggVerifyClient] = None) -> list[BaseTool]:
    """All tools sharing one client (one wallet, one spend cap)."""
    client = client or EggVerifyClient()
    return [
        EggServiceCardTool(client=client),
        EggVerifyClaimTool(client=client),
        EggScoutTool(client=client),
        EggDeepDiveTool(client=client),
    ]
