"""Meowdel API Client"""

import os
from typing import List, Optional, Dict, Any
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

from .exceptions import AuthenticationError, RateLimitError, APIError, MeowdelError
from .types import ChatRequest, ChatResponse, CombineRequest, CombineResponse, Message


class MeowdelClient:
    """
    Official Python client for the Meowdel AI API.

    Usage:
        client = MeowdelClient(api_key="mdl_your_key_here")
        response = client.chat("How do I fix this bug?")
        print(response.message)
    """

    def __init__(
        self,
        api_key: Optional[str] = None,
        base_url: Optional[str] = None,
        timeout: int = 30,
        max_retries: int = 3,
    ):
        """
        Initialize Meowdel client.

        Args:
            api_key: Meowdel API key (defaults to MEOWDEL_API_KEY env var)
            base_url: API base URL (defaults to https://meowdel.ai)
            timeout: Request timeout in seconds
            max_retries: Maximum number of retry attempts
        """
        self.api_key = api_key or os.environ.get("MEOWDEL_API_KEY")
        if not self.api_key:
            raise AuthenticationError(
                "API key required. Set MEOWDEL_API_KEY env var or pass api_key parameter."
            )

        self.base_url = (base_url or os.environ.get("MEOWDEL_API_URL") or "https://meowdel.ai").rstrip("/")
        self.timeout = timeout

        # Configure session with retries
        self.session = requests.Session()
        retry_strategy = Retry(
            total=max_retries,
            backoff_factor=1,
            status_forcelist=[429, 500, 502, 503, 504],
            allowed_methods=["GET", "POST"],
        )
        adapter = HTTPAdapter(max_retries=retry_strategy)
        self.session.mount("http://", adapter)
        self.session.mount("https://", adapter)

        # Set default headers
        self.session.headers.update({
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json",
            "User-Agent": "meowdel-python/0.1.0",
        })

    def _request(self, method: str, endpoint: str, **kwargs) -> Dict[str, Any]:
        """Make HTTP request with error handling."""
        url = f"{self.base_url}/api/v1{endpoint}"

        try:
            response = self.session.request(
                method=method,
                url=url,
                timeout=self.timeout,
                **kwargs,
            )

            # Handle errors
            if response.status_code == 401:
                raise AuthenticationError("Invalid or expired API key")
            elif response.status_code == 429:
                raise RateLimitError("Rate limit exceeded. Please slow down.")
            elif response.status_code >= 400:
                error_msg = response.json().get("error", "Unknown error")
                raise APIError(f"API error ({response.status_code}): {error_msg}")

            return response.json()

        except requests.exceptions.Timeout:
            raise MeowdelError(f"Request timeout after {self.timeout}s")
        except requests.exceptions.ConnectionError:
            raise MeowdelError(f"Connection error to {url}")
        except requests.exceptions.RequestException as e:
            raise MeowdelError(f"Request failed: {str(e)}")

    def chat(
        self,
        message: str,
        personality: str = "mittens",
        use_brain_context: bool = False,
        conversation_history: Optional[List[Message]] = None,
    ) -> ChatResponse:
        """
        Send a chat message to Meowdel.

        Args:
            message: The user's message
            personality: AI personality to use (mittens, luna, professor, etc.)
            use_brain_context: Whether to use Brain knowledge graph context
            conversation_history: Previous conversation messages

        Returns:
            ChatResponse with AI's reply

        Example:
            response = client.chat(
                "Explain quantum computing",
                personality="professor",
                use_brain_context=True
            )
            print(response.message)
        """
        request_data = ChatRequest(
            message=message,
            personality=personality,
            useBrainContext=use_brain_context,
            conversationHistory=[msg.dict() for msg in (conversation_history or [])],
        )

        data = self._request("POST", "/chat", json=request_data.dict())
        return ChatResponse(**data)

    def combine(
        self,
        query: str,
        operations: List[str],
        primary_personality: str = "mittens",
        secondary_personality: str = "professor",
    ) -> CombineResponse:
        """
        Combine multiple AI operations in one request.

        Args:
            query: The user's query
            operations: List of operations to perform (e.g., ["search", "analyze", "summarize"])
            primary_personality: Primary AI personality
            secondary_personality: Secondary AI personality for review

        Returns:
            CombineResponse with results from all operations

        Example:
            response = client.combine(
                query="What is machine learning?",
                operations=["search", "explain", "visualize"],
                primary_personality="professor"
            )
            print(response.result)
        """
        request_data = CombineRequest(
            query=query,
            operations=operations,
            primaryPersonality=primary_personality,
            secondaryPersonality=secondary_personality,
        )

        data = self._request("POST", "/combine", json=request_data.dict())
        return CombineResponse(**data)

    def health_check(self) -> Dict[str, Any]:
        """
        Check API health status.

        Returns:
            Health check response with status and uptime
        """
        response = requests.get(f"{self.base_url}/api/health", timeout=5)
        return response.json()

    def close(self):
        """Close the HTTP session."""
        self.session.close()

    def __enter__(self):
        """Context manager entry."""
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Context manager exit."""
        self.close()
