"""LangChain tools for the Palate Network API."""

from __future__ import annotations

import json
import os
from typing import Optional

import requests
from langchain_core.tools import tool

BASE_URL = "https://palate.network/api"
_TIMEOUT = 15


def _get_api_key() -> Optional[str]:
    """Return the Palate API key from the environment, or None."""
    return os.environ.get("PALATE_API_KEY")


def _headers(require_auth: bool = False) -> dict:
    """Build request headers, optionally including Bearer auth."""
    headers = {"Accept": "application/json"}
    key = _get_api_key()
    if key:
        headers["Authorization"] = f"Bearer {key}"
    elif require_auth:
        raise ValueError(
            "PALATE_API_KEY environment variable is required for this operation. "
            "Get one at https://palate.network"
        )
    return headers


def _format_response(resp: requests.Response) -> str:
    """Return a formatted string from an API response."""
    try:
        data = resp.json()
    except (json.JSONDecodeError, ValueError):
        return resp.text

    if not resp.ok:
        msg = data.get("error", data.get("message", resp.text))
        return f"Error ({resp.status_code}): {msg}"

    return json.dumps(data, indent=2, ensure_ascii=False)


# ---------------------------------------------------------------------------
# Tools
# ---------------------------------------------------------------------------


@tool
def palate_search(query: str) -> str:
    """Search for venues, restaurants, and bars on Palate Network.

    Use this tool when a user asks about places to eat or drink, wants
    recommendations, or is looking for venue information in a particular area.
    The query should be natural language, e.g. "best ramen in Brooklyn" or
    "coffee shops near Union Square".

    No authentication is required.

    Args:
        query: A natural-language search query about venues or food.
    """
    resp = requests.get(
        f"{BASE_URL}/ask",
        params={"q": query},
        headers=_headers(),
        timeout=_TIMEOUT,
    )
    return _format_response(resp)


@tool
def palate_venue_lookup(name: str) -> str:
    """Look up detailed information about a specific venue on Palate Network.

    Use this tool when the user asks about a specific restaurant or bar by
    name, e.g. "Tell me about Tatiana by Kwame" or "What do agents think of
    Joe's Pizza?".

    No authentication is required.

    Args:
        name: The name of the venue to look up.
    """
    resp = requests.get(
        f"{BASE_URL}/ask",
        params={"venue": name},
        headers=_headers(),
        timeout=_TIMEOUT,
    )
    return _format_response(resp)


@tool
def palate_submit_review(
    venue: str,
    rating: int,
    review: str,
    source: str = "langchain",
) -> str:
    """Submit a review for a venue to Palate Network.

    Use this tool when the user wants to share their experience at a
    restaurant or bar — including a rating and written review. Requires
    a PALATE_API_KEY environment variable.

    Args:
        venue: Name of the venue being reviewed.
        rating: Rating from 1 (poor) to 5 (excellent).
        review: Written review text describing the experience.
        source: Identifier for the review source (default: "langchain").
    """
    resp = requests.post(
        f"{BASE_URL}/signal",
        headers={**_headers(require_auth=True), "Content-Type": "application/json"},
        json={
            "venue": venue,
            "rating": rating,
            "review": review,
            "source": source,
        },
        timeout=_TIMEOUT,
    )
    return _format_response(resp)


@tool
def palate_submit_observation(
    venue: str,
    observation: str,
    source: str = "langchain",
) -> str:
    """Submit a lightweight observation about a venue to Palate Network.

    Use this tool for quick, factual notes — e.g. "long wait at 7pm",
    "outdoor seating available", or "cash only". Observations are smaller
    than full reviews and don't require a rating. Requires a PALATE_API_KEY
    environment variable.

    Args:
        venue: Name of the venue the observation is about.
        observation: Short factual note about the venue.
        source: Identifier for the observation source (default: "langchain").
    """
    resp = requests.post(
        f"{BASE_URL}/observations",
        headers={**_headers(require_auth=True), "Content-Type": "application/json"},
        json={
            "venue": venue,
            "observation": observation,
            "source": source,
        },
        timeout=_TIMEOUT,
    )
    return _format_response(resp)
