"""
Cliente principal de OrbiQuant SDK
"""

import httpx
from typing import Optional, Any, Dict
from .config import Config, DEFAULT_CONFIG


class OrbiQuantClient:
    """
    Cliente principal para OrbiQuant Trading Platform.

    Ejemplo de uso:
        ```python
        from orbiquant_sdk import OrbiQuantClient, Config

        config = Config.from_env()
        client = OrbiQuantClient(config)

        # Obtener predicción
        prediction = await client.ml.get_prediction("BTCUSDT", "1h")

        # Enviar señal
        await client.signals.send_signal(signal_data)
        ```
    """

    def __init__(self, config: Optional[Config] = None):
        self.config = config or DEFAULT_CONFIG
        self._http_client: Optional[httpx.AsyncClient] = None

    @property
    def http(self) -> httpx.AsyncClient:
        """HTTP client lazy initialization"""
        if self._http_client is None:
            self._http_client = httpx.AsyncClient(
                timeout=self.config.timeout,
                headers=self._get_headers(),
            )
        return self._http_client

    def _get_headers(self) -> Dict[str, str]:
        """Get request headers"""
        headers = {"Content-Type": "application/json"}
        if self.config.access_token:
            headers["Authorization"] = f"Bearer {self.config.access_token}"
        if self.config.api_key:
            headers["X-API-Key"] = self.config.api_key
        return headers

    async def close(self):
        """Close HTTP client"""
        if self._http_client:
            await self._http_client.aclose()
            self._http_client = None

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self.close()

    # =========================================================================
    # ML Engine Methods
    # =========================================================================

    async def get_prediction(
        self, symbol: str, timeframe: str, lookback: int = 100
    ) -> Dict[str, Any]:
        """Get price prediction from ML Engine"""
        response = await self.http.post(
            f"{self.config.ml_engine_url}/api/v1/predict",
            json={"symbol": symbol, "timeframe": timeframe, "lookback": lookback},
        )
        response.raise_for_status()
        return response.json()

    async def get_signals(
        self, symbol: Optional[str] = None, active_only: bool = True
    ) -> list:
        """Get trading signals"""
        params = {"active": active_only}
        if symbol:
            params["symbol"] = symbol
        response = await self.http.get(
            f"{self.config.ml_engine_url}/api/v1/signals", params=params
        )
        response.raise_for_status()
        return response.json()

    async def run_backtest(
        self,
        symbol: str,
        timeframe: str,
        start_date: str,
        end_date: str,
        strategy: str,
        parameters: Optional[Dict] = None,
    ) -> Dict[str, Any]:
        """Run backtest"""
        response = await self.http.post(
            f"{self.config.ml_engine_url}/api/v1/backtest",
            json={
                "symbol": symbol,
                "timeframe": timeframe,
                "start_date": start_date,
                "end_date": end_date,
                "strategy": strategy,
                "parameters": parameters or {},
            },
        )
        response.raise_for_status()
        return response.json()

    # =========================================================================
    # LLM Agent Methods
    # =========================================================================

    async def chat(
        self,
        message: str,
        conversation_id: Optional[str] = None,
        context: Optional[Dict] = None,
    ) -> Dict[str, Any]:
        """Send message to LLM copilot"""
        response = await self.http.post(
            f"{self.config.llm_agent_url}/api/v1/chat",
            json={
                "message": message,
                "conversation_id": conversation_id,
                "context": context,
            },
        )
        response.raise_for_status()
        return response.json()

    async def analyze_market(self, symbol: str, timeframe: str) -> Dict[str, Any]:
        """Get market analysis from LLM"""
        response = await self.http.post(
            f"{self.config.llm_agent_url}/api/v1/analyze",
            json={"symbol": symbol, "timeframe": timeframe},
        )
        response.raise_for_status()
        return response.json()

    # =========================================================================
    # Trading Agents Methods
    # =========================================================================

    async def start_agent(self, agent_id: str) -> Dict[str, Any]:
        """Start a trading agent"""
        response = await self.http.post(
            f"{self.config.trading_agents_url}/api/v1/agents/{agent_id}/start"
        )
        response.raise_for_status()
        return response.json()

    async def stop_agent(self, agent_id: str) -> Dict[str, Any]:
        """Stop a trading agent"""
        response = await self.http.post(
            f"{self.config.trading_agents_url}/api/v1/agents/{agent_id}/stop"
        )
        response.raise_for_status()
        return response.json()

    async def get_agent_stats(self, agent_id: str) -> Dict[str, Any]:
        """Get agent statistics"""
        response = await self.http.get(
            f"{self.config.trading_agents_url}/api/v1/agents/{agent_id}/stats"
        )
        response.raise_for_status()
        return response.json()

    # =========================================================================
    # Data Service Methods
    # =========================================================================

    async def get_market_data(
        self, symbol: str, timeframe: str, limit: int = 100
    ) -> list:
        """Get market data (candles)"""
        response = await self.http.get(
            f"{self.config.data_service_url}/api/v1/candles/{symbol}",
            params={"timeframe": timeframe, "limit": limit},
        )
        response.raise_for_status()
        return response.json()

    async def get_ticker(self, symbol: str) -> Dict[str, Any]:
        """Get current ticker"""
        response = await self.http.get(
            f"{self.config.data_service_url}/api/v1/ticker/{symbol}"
        )
        response.raise_for_status()
        return response.json()

    # =========================================================================
    # Backend API Methods
    # =========================================================================

    async def get_user_portfolio(self) -> Dict[str, Any]:
        """Get user portfolio from backend"""
        response = await self.http.get(f"{self.config.backend_url}/api/v1/portfolio")
        response.raise_for_status()
        return response.json()

    async def get_positions(self) -> list:
        """Get open positions"""
        response = await self.http.get(
            f"{self.config.backend_url}/api/v1/trading/positions"
        )
        response.raise_for_status()
        return response.json()

    async def create_order(self, order_data: Dict[str, Any]) -> Dict[str, Any]:
        """Create a new order"""
        response = await self.http.post(
            f"{self.config.backend_url}/api/v1/trading/orders", json=order_data
        )
        response.raise_for_status()
        return response.json()

    # =========================================================================
    # Health Checks
    # =========================================================================

    async def health_check(self) -> Dict[str, bool]:
        """Check health of all services"""
        services = {
            "backend": self.config.backend_url,
            "ml_engine": self.config.ml_engine_url,
            "llm_agent": self.config.llm_agent_url,
            "trading_agents": self.config.trading_agents_url,
            "data_service": self.config.data_service_url,
        }

        results = {}
        for name, url in services.items():
            try:
                response = await self.http.get(f"{url}/health", timeout=5)
                results[name] = response.status_code == 200
            except Exception:
                results[name] = False

        return results
