"""
TOXO API client — lightweight HTTP client for the TOXO Cloud API.

Use this when your processing runs on the TOXO API (GCP). No heavy local
dependencies (torch, chromadb, weasyprint, etc.) required.
"""

import base64
from pathlib import Path
from typing import Any, Dict, List, Optional

import requests


DEFAULT_API_URL = "https://toxo-api-cwsddklqcq-uc.a.run.app"


class ToxoClient:
    """
    Client for the TOXO Cloud API.

    All heavy processing (LLM, document conversion, RAG) runs on the server.
    You only need a .toxo layer file and an API key.
    """

    def __init__(self, api_url: Optional[str] = None, api_key: Optional[str] = None):
        self.api_url = (api_url or "").rstrip("/") or DEFAULT_API_URL
        self.api_key = api_key

    def _layer_base64(self, layer: str | Path) -> str:
        path = Path(layer)
        if not path.exists():
            raise FileNotFoundError(f"Layer file not found: {path}")
        raw = path.read_bytes()
        return base64.b64encode(raw).decode("ascii")

    def query(
        self,
        layer: str | Path,
        question: str,
        *,
        api_key: Optional[str] = None,
        model: str = "gemini-2.5-flash-lite",
        provider: str = "gemini",
        context: Optional[Dict[str, Any]] = None,
        response_depth: str = "balanced",
    ) -> str:
        """
        Send a text query to the TOXO API.

        Args:
            layer: Path to .toxo file
            question: Query text
            api_key: LLM API key (or use constructor / env GEMINI_API_KEY)
            model: Model name
            provider: Provider (gemini, openai, claude)
            context: Optional context dict
            response_depth: concise, balanced, or detailed

        Returns:
            Response text from the API.
        """
        key = api_key or self.api_key
        payload = {
            "layer_base64": self._layer_base64(layer),
            "question": question,
            "api_key": key,
            "model": model,
            "provider": provider,
            "context": context,
            "response_depth": response_depth,
        }
        r = requests.post(
            f"{self.api_url}/v1/query",
            json=payload,
            timeout=120,
        )
        r.raise_for_status()
        data = r.json()
        return data.get("response", "")

    def query_multimodal(
        self,
        layer: str | Path,
        question: str,
        *,
        image_path: Optional[str | Path] = None,
        document_path: Optional[str | Path] = None,
        image_base64: Optional[str] = None,
        document_base64: Optional[str] = None,
        mime_type: Optional[str] = None,
        api_key: Optional[str] = None,
        model: str = "gemini-2.5-flash-lite",
        provider: str = "gemini",
        context: Optional[Dict[str, Any]] = None,
        response_depth: str = "balanced",
    ) -> str:
        """
        Send a multimodal query (image or document) to the TOXO API.

        Provide exactly one of: image_path, document_path, image_base64, document_base64.

        Args:
            layer: Path to .toxo file
            question: Query text
            image_path: Path to image file
            document_path: Path to document (PDF, DOCX, etc.)
            image_base64: Base64 image (alternative to image_path)
            document_base64: Base64 document (alternative to document_path)
            mime_type: MIME type if using base64
            api_key: LLM API key
            model, provider, context, response_depth: Same as query()

        Returns:
            Response text.
        """
        sources = [image_path, document_path, image_base64, document_base64]
        if sum(1 for x in sources if x) != 1:
            raise ValueError(
                "Provide exactly one of: image_path, document_path, image_base64, document_base64"
            )

        img_b64 = image_base64
        doc_b64 = document_base64
        if image_path:
            img_b64 = base64.b64encode(Path(image_path).read_bytes()).decode("ascii")
        if document_path:
            doc_b64 = base64.b64encode(Path(document_path).read_bytes()).decode("ascii")

        key = api_key or self.api_key
        payload = {
            "layer_base64": self._layer_base64(layer),
            "question": question,
            "image_base64": img_b64,
            "document_base64": doc_b64,
            "mime_type": mime_type,
            "api_key": key,
            "model": model,
            "provider": provider,
            "context": context,
            "response_depth": response_depth,
        }
        r = requests.post(
            f"{self.api_url}/v1/query_multimodal",
            json=payload,
            timeout=180,
        )
        r.raise_for_status()
        data = r.json()
        return data.get("response", "")

    def feedback(
        self,
        layer: str | Path,
        question: str,
        response: str,
        *,
        rating: Optional[float] = None,
        suggestions: Optional[List[str]] = None,
    ) -> bool:
        """
        Send feedback to improve layer performance.

        Args:
            layer: Path to .toxo file
            question: Original question
            response: Response that was returned
            rating: Optional 0–10 rating
            suggestions: Optional list of suggestion strings

        Returns:
            True if successful.
        """
        payload = {
            "layer_base64": self._layer_base64(layer),
            "question": question,
            "response": response,
            "rating": rating,
            "suggestions": suggestions,
        }
        r = requests.post(
            f"{self.api_url}/v1/feedback",
            json=payload,
            timeout=30,
        )
        r.raise_for_status()
        return True

    def health(self) -> Dict[str, Any]:
        """Check API health. Returns status dict."""
        r = requests.get(f"{self.api_url}/health", timeout=10)
        r.raise_for_status()
        return r.json()
