# AUTO-GENERATED FILE - DO NOT EDIT
# This file was automatically generated by the XDK build tool.
# Any manual changes will be overwritten on the next generation.
"""
Auto-generated main client for the X API.

This module provides the primary Client class for interacting with the X API.
It coordinates all sub-clients and handles authentication, session management,
and OAuth2 PKCE flows. All functionality is generated from the OpenAPI specification.

Generated automatically - do not edit manually.
"""

import requests
from typing import Dict, List, Optional, Union, Any, Callable

from .oauth2_auth import OAuth2PKCEAuth
from .paginator import Cursor, cursor, PaginationError

from .media.client import MediaClient

from .connections.client import ConnectionsClient

from .direct_messages.client import DirectMessagesClient

from .users.client import UsersClient

from .communities.client import CommunitiesClient

from .lists.client import ListsClient

from .usage.client import UsageClient

from .stream.client import StreamClient

from .community_notes.client import CommunityNotesClient

from .compliance.client import ComplianceClient

from .spaces.client import SpacesClient

from .webhooks.client import WebhooksClient

from .posts.client import PostsClient

from .general.client import GeneralClient

from .trends.client import TrendsClient

from .account_activity.client import AccountActivityClient

from .news.client import NewsClient

from .activity.client import ActivityClient


class Client:
    """Client for interacting with the X API."""


    def __init__(
        self,
        base_url: str = "https://api.x.com",
        bearer_token: str = None,
        access_token: str = None,
        client_id: str = None,
        client_secret: str = None,
        redirect_uri: str = None,
        token: Dict[str, Any] = None,
        scope: Union[str, List[str]] = None,
        authorization_base_url: str = "https://x.com/i",
    ):
        """Initialize the X API client.
        Args:
            base_url: The base URL for the X API (defaults to https://api.x.com).
            bearer_token: The bearer token for the X API (app-only authentication).
            access_token: The OAuth2 access token for user context (can be used directly as bearer token).
            client_id: The client ID for the X API (required for OAuth2 PKCE flow).
            client_secret: The client secret for the X API.
            redirect_uri: The redirect URI for OAuth2 authorization.
            token: An existing OAuth2 token dictionary (if available). If provided, access_token will be extracted.
            scope: Space-separated string or list of strings for OAuth2 authorization scopes.
            authorization_base_url: The base URL for OAuth2 authorization (defaults to https://x.com/i).
        """
        self.session = requests.Session()
        self.session.headers.update({"User-Agent": "xdk-python/0.4.3"})
        self.base_url = base_url
        self.bearer_token = bearer_token
        # Extract access_token from token dict if provided, otherwise use direct access_token parameter
        # This matches TypeScript's behavior where accessToken can be passed directly
        if token and isinstance(token, dict) and "access_token" in token:
            self._access_token = token["access_token"]
        else:
            self._access_token = access_token
        # Set up OAuth2 PKCE authentication if credentials are provided
        # This is only needed for OAuth2 flows (getting authorization URL, exchanging codes, refreshing tokens)
        self.oauth2_auth = None
        if client_id or token:
            self.oauth2_auth = OAuth2PKCEAuth(
                base_url=base_url,
                authorization_base_url=authorization_base_url,
                client_id=client_id,
                client_secret=client_secret,
                redirect_uri=redirect_uri,
                token=token,
                scope=scope,
            )
            # If we have oauth2_auth with a token, ensure access_token is set
            if (
                self.oauth2_auth
                and self.oauth2_auth.token
                and "access_token" in self.oauth2_auth.token
            ):
                self._access_token = self.oauth2_auth.token["access_token"]
        # Initialize clients for each tag
        self.media = MediaClient(self)
        self.connections = ConnectionsClient(self)
        self.direct_messages = DirectMessagesClient(self)
        self.users = UsersClient(self)
        self.communities = CommunitiesClient(self)
        self.lists = ListsClient(self)
        self.usage = UsageClient(self)
        self.stream = StreamClient(self)
        self.community_notes = CommunityNotesClient(self)
        self.compliance = ComplianceClient(self)
        self.spaces = SpacesClient(self)
        self.webhooks = WebhooksClient(self)
        self.posts = PostsClient(self)
        self.general = GeneralClient(self)
        self.trends = TrendsClient(self)
        self.account_activity = AccountActivityClient(self)
        self.news = NewsClient(self)
        self.activity = ActivityClient(self)

    @property


    def oauth2_session(self):
        """Get the OAuth2 session if available."""
        if self.oauth2_auth:
            return self.oauth2_auth.oauth2_session
        return None

    @property


    def token(self):
        """Get the current OAuth2 token if available."""
        if self.oauth2_auth:
            return self.oauth2_auth.token
        return None

    @property


    def access_token(self):
        """Get the current access token if available."""
        # First check if we have a direct access_token (matches TypeScript behavior)
        if hasattr(self, "_access_token") and self._access_token:
            return self._access_token
        # Fall back to oauth2_auth if available
        if self.oauth2_auth:
            return self.oauth2_auth.access_token
        return None

    @access_token.setter


    def access_token(self, value):
        """Set the access token."""
        self._access_token = value


    def get_authorization_url(self, state=None):
        """Get the authorization URL for the OAuth2 PKCE flow.
        Args:
            state: Optional state parameter for security.
        Returns:
            str: The authorization URL.
        """
        if not self.oauth2_auth:
            raise ValueError("OAuth2 credentials not configured")
        return self.oauth2_auth.get_authorization_url(state)


    def exchange_code(self, code, code_verifier=None):
        """Exchange authorization code for tokens (matches TypeScript API).
        Args:
            code: The authorization code from the callback.
            code_verifier: Optional code verifier (uses stored verifier if not provided).
        Returns:
            Dict[str, Any]: The token dictionary
        """
        if not self.oauth2_auth:
            raise ValueError("OAuth2 credentials not configured")
        token = self.oauth2_auth.exchange_code(code, code_verifier)
        # Update access_token after exchange (matches TypeScript behavior)
        if token and "access_token" in token:
            self._access_token = token["access_token"]
        return token


    def fetch_token(self, authorization_response):
        """Fetch token using authorization response URL (legacy method).
        Args:
            authorization_response: The full callback URL received after authorization.
        Returns:
            Dict[str, Any]: The token dictionary
        """
        if not self.oauth2_auth:
            raise ValueError("OAuth2 credentials not configured")
        token = self.oauth2_auth.fetch_token(authorization_response)
        # Update access_token after fetch (matches TypeScript behavior)
        if token and "access_token" in token:
            self._access_token = token["access_token"]
        return token


    def refresh_token(self):
        """Refresh the OAuth2 token."""
        if not self.oauth2_auth:
            raise ValueError("OAuth2 credentials not configured")
        token = self.oauth2_auth.refresh_token()
        # Update access_token after refresh (matches TypeScript behavior)
        if token and "access_token" in token:
            self._access_token = token["access_token"]
        return token


    def is_token_expired(self):
        """Check if the OAuth2 token is expired."""
        if not self.oauth2_auth:
            return True
        return self.oauth2_auth.is_token_expired()
