"""Authenticated client utilities for CLI commands.

Provides a helper to get an TerminalUse client with stored credentials.
"""

from __future__ import annotations

import os

from terminaluse.lib.cli.utils.credentials import (
    get_stored_token,
    has_refresh_token,
    is_token_expired,
    refresh_credentials,
)
from terminaluse.lib.cli.utils.errors import CLIError
from terminaluse.lib.client import TerminalUse


def _create_instrumented_httpx_client():
    """Create an httpx client with trace context injection.

    Returns an httpx.Client that automatically injects W3C trace context headers
    (traceparent, tracestate) into all outgoing requests for distributed tracing.
    """
    import httpx

    from terminaluse.lib.cli.telemetry import get_trace_headers

    class TracingTransport(httpx.HTTPTransport):
        """HTTP transport that injects trace context headers."""

        def handle_request(self, request: httpx.Request) -> httpx.Response:
            # Inject trace context headers
            trace_headers = get_trace_headers()
            for key, value in trace_headers.items():
                request.headers[key] = value
            return super().handle_request(request)

    return httpx.Client(
        transport=TracingTransport(),
        timeout=httpx.Timeout(60.0, connect=10.0),
        follow_redirects=True,
    )


def get_authenticated_client() -> TerminalUse:
    """Get an TerminalUse client with stored credentials.

    If the token is expired but a refresh token is available, attempts to
    refresh the credentials automatically.

    The client is instrumented with OpenTelemetry trace context propagation
    for distributed tracing (CLI -> Nucleus -> Agent).

    If TERMINALUSE_API_KEY is set in the environment, it is used as the bearer
    token (and takes precedence over stored credentials). This enables
    non-interactive CLI use in environments where persisting credentials is not
    desirable (e.g., CI or deployed agents).

    Returns:
        TerminalUse client configured with the stored session token.

    Raises:
        CLIError: If not authenticated or token refresh failed.
    """
    env_token = os.getenv("TERMINALUSE_API_KEY")
    if env_token:
        # Treat the env var as authoritative; do not auto-refresh via stored creds,
        # and do not require a prior `tu login`.
        return TerminalUse(
            token=env_token,
            auto_refresh_token=False,
            httpx_client=_create_instrumented_httpx_client(),
        )

    # Check if we have any credentials at all (regardless of expiration)
    token = get_stored_token()
    if not token:
        raise CLIError.not_authenticated()

    # Try to refresh if token is expired
    if is_token_expired():
        if has_refresh_token() and refresh_credentials():
            # Silently refreshed, get the new token
            token = get_stored_token()
        else:
            raise CLIError.auth_expired()

    # Create client with instrumented httpx client for trace propagation
    return TerminalUse(
        token=token,
        httpx_client=_create_instrumented_httpx_client(),
    )
