"""Main client for the Fastn Auth SDK."""

from typing import Any, Optional

import aiohttp

from .errors import InvalidResponseError, NetworkError
from .session import AuthSession
from .types import AuthStatus, FastnAuthConfig, InitOptions, InitResponse

DEFAULT_BASE_URL = "https://live.fastn.ai/api"


class FastnAuth:
    """Main client for the Fastn Auth SDK.

    Use this to initialize connector authentication flows.

    Example:
        ```python
        client = FastnAuth(
            space_id="your-space-id",
            api_key="your-api-key",
        )

        session = await client.initialize(
            connector_id="google-sheets",
        )

        # Redirect user to: session.redirect_url
        result = await session.wait_for_completion()
        ```
    """

    def __init__(
        self,
        space_id: str,
        api_key: str,
        base_url: Optional[str] = None,
    ) -> None:
        """Create a new FastnAuth client.

        Args:
            space_id: The space/workspace ID.
            api_key: API key for authentication.
            base_url: Base URL for the Fastn API (optional).
        """
        self._config = FastnAuthConfig(
            space_id=space_id,
            api_key=api_key,
            base_url=base_url or DEFAULT_BASE_URL,
        )

    async def initialize(
        self,
        connector_id: str,
        org_id: Optional[str] = None,
        tenant_id: Optional[str] = None,
        connection_id: Optional[str] = None,
    ) -> AuthSession:
        """Initialize a connector authentication flow.

        Args:
            connector_id: The connector ID (e.g., "google-sheets", "salesforce").
            org_id: Organization ID (optional).
            tenant_id: Tenant ID (optional).
            connection_id: Connection instance ID (optional, defaults to "default").

        Returns:
            An AuthSession instance to manage the authentication flow.

        Raises:
            NetworkError: If the request fails.
            InvalidResponseError: If the response is invalid.
        """
        options = InitOptions(
            connector_id=connector_id,
            org_id=org_id,
            tenant_id=tenant_id,
            connection_id=connection_id,
        )

        actual_org_id = options.org_id or "default"
        url = f"{self._config.base_url}/connect/init/{actual_org_id}/{options.connector_id}"

        headers = self._build_headers(options)

        async with aiohttp.ClientSession() as session:
            async with session.post(url, headers=headers) as response:
                if not response.ok:
                    raise NetworkError(
                        f"Failed to initialize connection: {response.reason}",
                        status_code=response.status,
                    )

                data: dict[str, Any] = await response.json()

                if not data or "id" not in data or "stateKey" not in data:
                    raise InvalidResponseError("Invalid init response")

                init_response = InitResponse(
                    id=data["id"],
                    state_key=data["stateKey"],
                    status=AuthStatus(data.get("status", "INACTIVE")),
                    redirect_url=data.get("redirectUrl"),
                )

                redirect_url = (
                    f"{self._config.base_url}/connect/oauth/start/{init_response.state_key}"
                )

                return AuthSession(
                    id=init_response.id,
                    state_key=init_response.state_key,
                    redirect_url=redirect_url,
                    base_url=self._config.base_url,
                    headers=headers,
                    connector_id=options.connector_id,
                )

    def _build_headers(self, options: InitOptions) -> dict[str, str]:
        """Build HTTP headers for the API request.

        Args:
            options: Initialization options.

        Returns:
            Dictionary of HTTP headers.
        """
        headers: dict[str, str] = {
            "Content-Type": "application/json",
            "x-fastn-space-id": self._config.space_id,
            "Authorization": f"Bearer {self._config.api_key}",
        }

        if options.tenant_id:
            headers["x-fastn-space-tenantid"] = options.tenant_id

        if options.connection_id:
            headers["x-fastn-space-connection-id"] = options.connection_id
        else:
            headers["x-fastn-space-connection-id"] = "default"

        if options.org_id:
            headers["x-fastn-org-id"] = options.org_id

        return headers
