# 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 .compliance.client import ComplianceClient

from .news.client import NewsClient

from .webhooks.client import WebhooksClient

from .activity.client import ActivityClient

from .users.client import UsersClient

from .spaces.client import SpacesClient

from .community_notes.client import CommunityNotesClient

from .direct_messages.client import DirectMessagesClient

from .usage.client import UsageClient

from .posts.client import PostsClient

from .general.client import GeneralClient

from .communities.client import CommunitiesClient

from .trends.client import TrendsClient

from .account_activity.client import AccountActivityClient

from .stream.client import StreamClient

from .connections.client import ConnectionsClient

from .lists.client import ListsClient

from .media.client import MediaClient


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.4"})
        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.compliance = ComplianceClient(self)
        self.news = NewsClient(self)
        self.webhooks = WebhooksClient(self)
        self.activity = ActivityClient(self)
        self.users = UsersClient(self)
        self.spaces = SpacesClient(self)
        self.community_notes = CommunityNotesClient(self)
        self.direct_messages = DirectMessagesClient(self)
        self.usage = UsageClient(self)
        self.posts = PostsClient(self)
        self.general = GeneralClient(self)
        self.communities = CommunitiesClient(self)
        self.trends = TrendsClient(self)
        self.account_activity = AccountActivityClient(self)
        self.stream = StreamClient(self)
        self.connections = ConnectionsClient(self)
        self.lists = ListsClient(self)
        self.media = MediaClient(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()
