import requests
from typing import List, Dict, Any, Optional
from datetime import datetime

class ZenithTradeClient:
    def __init__(self, mode: str = "localhost", tailscale_host: Optional[str] = None, port: int = 8000):
        """
        Python client for Zenith-Trade backend.

        Args:
            mode (str): Either "localhost" (default) or "tailscale".
            tailscale_host (str, optional): Required if mode="tailscale""
            port (int): Backend port (default: 8000)

        Raises:
            ValueError: If mode is invalid, or required args are missing.

        Example:
            # Localhost
            client = ZenithTradeClient()

            # Remote via Tailscale
            client = ZenithTradeClient(mode="tailscale", tailscale_host="", port=8000)
        """
        if mode not in ("localhost", "tailscale"):
            raise ValueError("mode must be either 'localhost' or 'tailscale'")

        if mode == "localhost":
            base_url = f"http://localhost:{port}"
        elif mode == "tailscale":
            if not tailscale_host:
                raise ValueError("tailscale_host is required when mode='tailscale'")
            base_url = f"http://{tailscale_host}:{port}"

        # Validate port
        if not isinstance(port, int) or not (1 <= port <= 65535):
            raise ValueError("port must be an integer between 1 and 65535")

        self.base_url = base_url.rstrip("/")

    # -------------------------------
    # Input validation
    # -------------------------------
    @staticmethod
    def _validate_dates(from_date: str, to_date: str):
        """Validate that dates are in YYYY-MM-DD format and from_date <= to_date."""
        try:
            start = datetime.strptime(from_date, "%Y-%m-%d")
            end = datetime.strptime(to_date, "%Y-%m-%d")
        except ValueError:
            raise ValueError("Dates must be in 'YYYY-MM-DD' format")
        if end < start:
            raise ValueError("to_date must be greater than or equal to from_date")

    # -------------------------------
    # Exchange APIs
    # -------------------------------
    def list_exchanges(self) -> Dict[str, Any]:
        """Get all available exchanges with metadata."""
        url = f"{self.base_url}/exchanges"
        resp = requests.get(url)
        resp.raise_for_status()
        return resp.json()

    def get_exchange_info(self, exchange: str, datasource: str = None) -> Dict[str, Any]:
        """Get exchange metadata. If datasource provided, return datasource-specific info."""
        if datasource is None:
            url = f"{self.base_url}/exchanges/{exchange}"
        else:
            url = f"{self.base_url}/exchanges/{exchange}/{datasource}"

        resp = requests.get(url)
        resp.raise_for_status()
        return resp.json()

    # -------------------------------
    # Data APIs
    # -------------------------------
    def check_data_availability(
        self, 
        exchange: str, 
        symbols: List[str], 
        data_types: List[str], 
        from_date: str, 
        to_date: str
    ) -> Dict[str, Any]:
        """
        symbols: list of strings, e.g., ["BTCUSDT", "ETHUSDT"]
        data_types: list of strings, e.g., ["book_snapshot_5", "trades"]
        from_date, to_date: 'YYYY-MM-DD' format
        Raises ValueError if dates invalid
        """
        # Validate dates first
        self._validate_dates(from_date, to_date)

        url = f"{self.base_url}/data"
        payload = {
            "exchange": exchange,
            "symbols": symbols,
            "data_types": data_types,
            "from_date": from_date,
            "to_date": to_date
        }
        resp = requests.post(url, json=payload)
        resp.raise_for_status()
        return resp.json()
