"""
Timeback PowerPath Client

Async client for PowerPath adaptive learning operations.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Literal, Protocol, cast

from .lib.transport import Transport
from .resources.assessment import AssessmentResource
from .resources.lesson_plans import LessonPlansResource
from .resources.placement import PlacementResource
from .resources.screening import ScreeningResource
from .resources.syllabus import SyllabusResource
from .resources.test_assignments import TestAssignmentsResource

if TYPE_CHECKING:
    from timeback_common import AuthCheckResult, Environment, PowerPathPaths, TimebackProvider

Platform = Literal["BEYOND_AI", "LEARNWITH_AI"]


class PowerPathTransportLike(Protocol):
    """Duck-typed transport interface for custom transports."""

    base_url: str
    paths: PowerPathPaths

    async def close(self) -> None:
        """Close the transport and release resources."""
        ...


class PowerPathClient:
    """
    PowerPath API client for adaptive learning operations.

    Provides access to placement testing, lesson plans, assessment flow,
    screening sessions, test assignments, and syllabus retrieval.

    Example: Environment mode (Timeback APIs)
        ```python
        client = PowerPathClient(
            env="staging",
            client_id="your-client-id",
            client_secret="your-client-secret",
        )
        ```

    Example: Environment variables fallback
        ```python
        # Set POWERPATH_CLIENT_ID and POWERPATH_CLIENT_SECRET
        client = PowerPathClient(env="staging")
        ```

    Example: Custom base URL
        ```python
        client = PowerPathClient(
            base_url="https://custom.example.com",
            client_id="your-client-id",
            client_secret="your-client-secret",
        )
        ```

    Example: Shared provider
        ```python
        from timeback_common import TimebackProvider

        provider = TimebackProvider(env="staging", client_id="...", client_secret="...")
        client = PowerPathClient(provider=provider)
        ```
    """

    def __init__(
        self,
        *,
        platform: Platform | None = None,
        env: str | None = None,
        transport: PowerPathTransportLike | None = None,
        base_url: str | None = None,
        auth_url: str | None = None,
        client_id: str | None = None,
        client_secret: str | None = None,
        timeout: float = 30.0,
        provider: TimebackProvider | None = None,
    ) -> None:
        """
        Initialize the PowerPath client.

        Args:
            platform: Target platform ("BEYOND_AI" or "LEARNWITH_AI"). Defaults to BEYOND_AI.
            env: Environment ("staging" or "production")
            transport: Custom transport (for testing)
            base_url: API base URL (overrides platform/env resolution)
            auth_url: Auth token URL (overrides platform/env resolution)
            client_id: OAuth2 client ID (or set POWERPATH_CLIENT_ID env var)
            client_secret: OAuth2 client secret (or set POWERPATH_CLIENT_SECRET env var)
            timeout: Request timeout in seconds
            provider: Optional TimebackProvider for shared auth
        """
        self._transport: Transport | PowerPathTransportLike
        if transport is not None:
            self._transport = transport
            self._provider = None
        else:
            from timeback_common import EnvVarNames, build_provider_env, build_provider_explicit

            env_vars = EnvVarNames(
                base_url=("TIMEBACK_API_BASE_URL", "TIMEBACK_BASE_URL", "POWERPATH_BASE_URL"),
                auth_url=(
                    "TIMEBACK_API_AUTH_URL",
                    "TIMEBACK_AUTH_URL",
                    "POWERPATH_TOKEN_URL",
                ),
                client_id=(
                    "TIMEBACK_API_CLIENT_ID",
                    "TIMEBACK_CLIENT_ID",
                    "POWERPATH_CLIENT_ID",
                ),
                client_secret=(
                    "TIMEBACK_API_CLIENT_SECRET",
                    "TIMEBACK_CLIENT_SECRET",
                    "POWERPATH_CLIENT_SECRET",
                ),
            )

            if provider is None:
                if env is not None:
                    provider = build_provider_env(
                        platform=platform,
                        env=cast("Environment", env),
                        client_id=client_id,
                        client_secret=client_secret,
                        timeout=timeout,
                        env_vars=env_vars,
                    )
                else:
                    provider = build_provider_explicit(
                        base_url=base_url,
                        auth_url=auth_url,
                        client_id=client_id,
                        client_secret=client_secret,
                        timeout=timeout,
                        env_vars=env_vars,
                    )

            self._provider = provider

            endpoint = provider.get_endpoint("powerpath")
            paths = provider.get_paths("powerpath")
            token_manager = provider.get_token_manager("powerpath")

            self._transport = Transport(
                base_url=endpoint.base_url,
                token_manager=token_manager,
                paths=paths,
                timeout=provider.timeout,
                no_auth=token_manager is None,
            )

        if not hasattr(self._transport, "paths"):
            raise TypeError(
                "Custom transport must have a 'paths' attribute with PowerPath path "
                "configuration. Use the PowerPath Transport class or ensure your "
                "transport includes a PowerPathPaths instance."
            )

        _transport = cast("Transport", self._transport)
        self.assessments = AssessmentResource(_transport)
        self.lesson_plans = LessonPlansResource(_transport)
        self.placement = PlacementResource(_transport)
        self.screening = ScreeningResource(_transport)
        self.syllabus = SyllabusResource(_transport)
        self.test_assignments = TestAssignmentsResource(_transport)

    def get_transport(self) -> Transport | PowerPathTransportLike:
        """
        Get the underlying transport for advanced use cases.

        Returns:
            The transport instance used by this client
        """
        return self._transport

    async def check_auth(self) -> AuthCheckResult:
        """
        Verify that OAuth authentication is working.

        Returns:
            Auth check result with ok, latency_ms, and checks

        Raises:
            RuntimeError: If client was initialized without a provider
        """
        if self._provider is None:
            raise RuntimeError("Cannot check auth: client initialized without provider")
        return await self._provider.check_auth()

    async def close(self) -> None:
        """Close the HTTP client and release resources."""
        await self._transport.close()

    async def __aenter__(self) -> PowerPathClient:
        """Async context manager entry."""
        return self

    async def __aexit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: object | None,
    ) -> None:
        """Async context manager exit."""
        await self.close()
