"""Resletter API Client."""

from __future__ import annotations

from typing import Any

import httpx

from resletter.exceptions import ResletterError
from resletter.resources.campaigns import CampaignsResource
from resletter.resources.events import EventsResource
from resletter.resources.groups import GroupsResource
from resletter.resources.subscribers import SubscribersResource

DEFAULT_BASE_URL = "https://app.resletter.com"
DEFAULT_TIMEOUT = 30.0


class Resletter:
    """Resletter API Client.

    Example:
        >>> from resletter import Resletter
        >>>
        >>> client = Resletter("rsl_your_api_key")
        >>>
        >>> # Create a subscriber
        >>> subscriber = client.subscribers.create(
        ...     email="user@example.com",
        ...     name="John Doe",
        ... )
        >>> print(f"Created subscriber: {subscriber['id']}")

    Args:
        api_key: Your Resletter API key (starts with 'rsl_').
        base_url: Custom base URL for self-hosted instances.
        timeout: Request timeout in seconds (default: 30).

    Raises:
        ValueError: If api_key is empty or in invalid format.
    """

    def __init__(
        self,
        api_key: str,
        *,
        base_url: str = DEFAULT_BASE_URL,
        timeout: float = DEFAULT_TIMEOUT,
    ) -> None:
        if not api_key:
            raise ValueError("API key is required")

        if not api_key.startswith("rsl_"):
            raise ValueError('Invalid API key format. API keys should start with "rsl_"')

        self._api_key = api_key
        self._base_url = base_url.rstrip("/")
        self._timeout = timeout

        # Initialize HTTP client
        self._client = httpx.Client(
            base_url=f"{self._base_url}/api/v1",
            headers={
                "Authorization": f"Bearer {self._api_key}",
                "Content-Type": "application/json",
                "User-Agent": "resletter-python-sdk/1.0.0",
            },
            timeout=self._timeout,
        )

        # Initialize resources
        self.subscribers = SubscribersResource(self)
        """Subscriber management methods."""

        self.groups = GroupsResource(self)
        """Group management methods."""

        self.campaigns = CampaignsResource(self)
        """Campaign management methods."""

        self.events = EventsResource(self)
        """Event tracking methods."""

    def close(self) -> None:
        """Close the HTTP client connection."""
        self._client.close()

    def __enter__(self) -> Resletter:
        return self

    def __exit__(self, *args: Any) -> None:
        self.close()

    def _request(
        self,
        method: str,
        path: str,
        *,
        params: dict[str, Any] | None = None,
        json: dict[str, Any] | None = None,
    ) -> Any:
        """Make an API request.

        Args:
            method: HTTP method (GET, POST, PATCH, DELETE).
            path: API path (e.g., '/subscribers').
            params: Query parameters.
            json: JSON body.

        Returns:
            Response data from the API.

        Raises:
            ResletterError: If the request fails.
        """
        # Filter out None values from params
        if params:
            params = {k: v for k, v in params.items() if v is not None}

        try:
            response = self._client.request(
                method,
                path,
                params=params,
                json=json,
            )
        except httpx.TimeoutException as e:
            raise ResletterError("Request timed out", status=408, code="TIMEOUT") from e
        except httpx.RequestError as e:
            raise ResletterError(str(e), status=0, code="NETWORK_ERROR") from e

        try:
            data = response.json()
        except ValueError as e:
            raise ResletterError(
                f"Invalid JSON response: {response.text[:100]}",
                status=response.status_code,
                code="INVALID_RESPONSE",
            ) from e

        if not response.is_success or not data.get("success"):
            error_info = data.get("error", {})
            raise ResletterError(
                error_info.get("message", f"Request failed with status {response.status_code}"),
                status=response.status_code,
                code=error_info.get("code"),
                data=data,
            )

        return data.get("data")
