from __future__ import annotations

import os
from typing import Any, Optional


def _non_empty(value: Any) -> Optional[str]:
    if value is None:
        return None
    text = str(value).strip()
    return text or None


def _from_attrs(obj: Any) -> Optional[str]:
    """
    Best-effort token extraction from CCS client-like objects.
    """
    if obj is None:
        return None

    candidate_attrs = (
        "accessToken",
        "access_token",
        "token",
        "bearerToken",
        "bearer_token",
    )
    for attr in candidate_attrs:
        if hasattr(obj, attr):
            token = _non_empty(getattr(obj, attr))
            if token:
                return token

    # Nested config patterns
    for container_name in ("config", "configuration", "auth"):
        container = getattr(obj, container_name, None)
        if container is None:
            continue
        token = _from_attrs(container)
        if token:
            return token

    # Method patterns
    for method_name in ("get_access_token", "getAccessToken", "get_token", "getToken"):
        method = getattr(obj, method_name, None)
        if callable(method):
            try:
                token = _non_empty(method())
                if token:
                    return token
            except Exception:
                continue

    # Mapping-like fallback
    if isinstance(obj, dict):
        for key in ("accessToken", "access_token", "token", "bearerToken", "bearer_token"):
            token = _non_empty(obj.get(key))
            if token:
                return token
        for key in ("config", "configuration", "auth"):
            token = _from_attrs(obj.get(key))
            if token:
                return token

    return None


def _from_ccs_config_token_storage() -> Optional[str]:
    """
    Preferred token source from `ccs.config`.

    Uses TokenStorage.BearerAccessToken when available.
    """
    try:
        # Keep imports explicit for compatibility with user environments.
        from ccs.config import BaseUrl, CCSConfig, TokenStorage  # noqa: F401
    except Exception:
        return None

    # Preferred attribute requested by user.
    token = _non_empty(getattr(TokenStorage, "BearerAccessToken", None))
    if token:
        return token.replace("Bearer ", "").strip()

    # Compatibility fallbacks in some ccs versions.
    get_token = getattr(TokenStorage, "getToken", None)
    if callable(get_token):
        try:
            token = _non_empty(get_token())
            if token:
                return token.replace("Bearer ", "").strip()
        except Exception:
            pass

    get_auth_header = getattr(TokenStorage, "getAuthHeader", None)
    if callable(get_auth_header):
        try:
            header = _non_empty(get_auth_header())
            if header and header.lower().startswith("bearer "):
                return header[7:].strip()
        except Exception:
            pass

    return None


def resolve_bearer_token(user_token: Optional[str] = None) -> Optional[str]:
    """
    Resolve bearer token priority:
    1) explicit user_token argument
    2) initialized CCS client token (when available)
    3) env fallbacks
    """
    explicit = _non_empty(user_token)
    if explicit:
        return explicit

    # Preferred ccs.config TokenStorage path.
    token = _from_ccs_config_token_storage()
    if token:
        return token

    # CCS client fallback
    try:
        from ..config import get_ccs_client

        client = get_ccs_client()
        token = _from_attrs(client)
        if token:
            return token
    except Exception:
        pass

    # Environment fallbacks
    for env_key in ("CCS_ACCESS_TOKEN", "ACCESS_TOKEN", "A2A_ACCESS_TOKEN"):
        token = _non_empty(os.getenv(env_key))
        if token:
            return token

    return None
