# 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 webhooks client for the X API.

This module provides a client for interacting with the webhooks endpoints of the X API.

All methods, parameters, and response models are generated from the OpenAPI specification.

Generated automatically - do not edit manually.
"""

from __future__ import annotations
from typing import Dict, List, Optional, Any, Union, cast, TYPE_CHECKING, Iterator
import requests
import time
import urllib.parse


if TYPE_CHECKING:
    from ..client import Client
from .models import (
    ValidateResponse,
    DeleteResponse,
    CreateWebhookReplayJobRequest,
    CreateWebhookReplayJobResponse,
    GetStreamLinksResponse,
    GetResponse,
    CreateRequest,
    CreateResponse,
    CreateStreamLinkResponse,
    DeleteStreamLinkResponse,
)


class WebhooksClient:
    """Client for webhooks operations"""


    def __init__(self, client: Client):
        self.client = client


    def validate(self, webhook_id: Any) -> ValidateResponse:
        """
        Validate webhook
        Triggers a CRC check for a given webhook.
        Args:
            webhook_id: The ID of the webhook to check.
            Returns:
            ValidateResponse: Response data
        """
        url = self.client.base_url + "/2/webhooks/{webhook_id}"
        url = url.replace("{webhook_id}", str(webhook_id))
        # Priority: bearer_token > access_token (matches TypeScript behavior)
        if self.client.bearer_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.bearer_token}"
            )
        elif self.client.access_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.access_token}"
            )
        # UserToken: OAuth1.0a authentication - header will be built dynamically in request
        # OAuth1 header must be built per-request with method, URL, and body
        # This is handled in the request logic below
        params = {}
        headers = {}
        # Prepare request data
        json_data = None
        # Select authentication method based on endpoint requirements and available credentials
        # Priority strategy (matches TypeScript):
        # 1. If endpoint only accepts one method, use that (if available)
        # 2. If endpoint accepts multiple methods:
        #    - For write operations (POST/PUT/DELETE/PATCH): Prefer OAuth1 > OAuth2 User Token > Bearer Token
        #    - For read operations (GET): Prefer Bearer Token > OAuth2 User Token > OAuth1
        # 3. If no security requirements: Bearer Token > OAuth2 User Token > OAuth1
        selected_auth = None
        # Check what auth methods we have available
        available_bearer = bool(self.client.bearer_token)
        available_oauth2 = bool(self.client.access_token)
        available_oauth1 = bool(self.client.auth and self.client.auth.access_token)
        # Count acceptable schemes
        acceptable_schemes = []
        acceptable_schemes.append("BearerToken")
        acceptable_schemes.append("UserToken")
        # If only one scheme is acceptable, use it if available
        if len(acceptable_schemes) == 1:
            scheme = acceptable_schemes[0]
            if scheme == "BearerToken" and available_bearer:
                selected_auth = "bearer_token"
            elif scheme == "OAuth2UserToken" and available_oauth2:
                selected_auth = "oauth2_user_context"
            elif scheme == "UserToken" and available_oauth1:
                selected_auth = "oauth1"
        # Multiple schemes acceptable - use priority based on operation type
        elif len(acceptable_schemes) > 1:
            is_write_operation = "put" in ["POST", "PUT", "DELETE", "PATCH"]
            if is_write_operation:
                # Priority for write operations: OAuth1 > OAuth2 User Token > Bearer Token
                if "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
            else:
                # Priority for read operations: Bearer Token > OAuth2 User Token > OAuth1
                if "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
        # Apply selected authentication
        if selected_auth == "oauth1":
            # OAuth1 authentication - build proper OAuth1 header dynamically
            # Build OAuth1 header with method, URL, and body
            # For OAuth1, we need to include query params in the URL for signature
            full_url = url
            if params:
                query_string = urllib.parse.urlencode(params)
                full_url = f"{url}?{query_string}" if query_string else url
            # Prepare body for OAuth1 signature (form-encoded, not JSON)
            body_string = ""
            # Build OAuth1 authorization header
            oauth_header = self.client.auth.build_request_header(
                method="put", url=full_url, body=body_string
            )
            headers["Authorization"] = oauth_header
        elif selected_auth == "bearer_token":
            # Bearer token authentication
            if self.client.bearer_token:
                headers["Authorization"] = f"Bearer {self.client.bearer_token}"
            elif self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
        elif selected_auth == "oauth2_user_context":
            # OAuth2 User Token authentication
            if self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
                # Check if token needs refresh
                if self.client.oauth2_auth and self.client.token:
                    if self.client.is_token_expired():
                        self.client.refresh_token()
                        if self.client.access_token:
                            headers["Authorization"] = (
                                f"Bearer {self.client.access_token}"
                            )
        # Make the request
        if not selected_auth:
            # No suitable auth method found - validate authentication
            required_schemes = (
                acceptable_schemes if "acceptable_schemes" in locals() else []
            )
            if required_schemes:
                available = []
                if available_bearer and "BearerToken" in required_schemes:
                    available.append("BearerToken")
                if available_oauth2 and "OAuth2UserToken" in required_schemes:
                    available.append("OAuth2UserToken")
                if available_oauth1 and "UserToken" in required_schemes:
                    available.append("UserToken")
                if not available:
                    raise ValueError(
                        f"Authentication required for this endpoint. Required schemes: {required_schemes}. Available: {[s for s in required_schemes if (s == 'BearerToken' and available_bearer) or (s == 'OAuth2UserToken' and available_oauth2) or (s == 'UserToken' and available_oauth1)]}"
                    )
        response = self.client.session.put(
            url,
            params=params,
            headers=headers,
        )
        # Check for errors
        response.raise_for_status()
        # Parse the response data
        response_data = response.json()
        # Convert to Pydantic model if applicable
        return ValidateResponse.model_validate(response_data)


    def delete(self, webhook_id: Any) -> DeleteResponse:
        """
        Delete webhook
        Deletes an existing webhook configuration.
        Args:
            webhook_id: The ID of the webhook to delete.
            Returns:
            DeleteResponse: Response data
        """
        url = self.client.base_url + "/2/webhooks/{webhook_id}"
        url = url.replace("{webhook_id}", str(webhook_id))
        # Priority: bearer_token > access_token (matches TypeScript behavior)
        if self.client.bearer_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.bearer_token}"
            )
        elif self.client.access_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.access_token}"
            )
        # UserToken: OAuth1.0a authentication - header will be built dynamically in request
        # OAuth1 header must be built per-request with method, URL, and body
        # This is handled in the request logic below
        params = {}
        headers = {}
        # Prepare request data
        json_data = None
        # Select authentication method based on endpoint requirements and available credentials
        # Priority strategy (matches TypeScript):
        # 1. If endpoint only accepts one method, use that (if available)
        # 2. If endpoint accepts multiple methods:
        #    - For write operations (POST/PUT/DELETE/PATCH): Prefer OAuth1 > OAuth2 User Token > Bearer Token
        #    - For read operations (GET): Prefer Bearer Token > OAuth2 User Token > OAuth1
        # 3. If no security requirements: Bearer Token > OAuth2 User Token > OAuth1
        selected_auth = None
        # Check what auth methods we have available
        available_bearer = bool(self.client.bearer_token)
        available_oauth2 = bool(self.client.access_token)
        available_oauth1 = bool(self.client.auth and self.client.auth.access_token)
        # Count acceptable schemes
        acceptable_schemes = []
        acceptable_schemes.append("BearerToken")
        acceptable_schemes.append("UserToken")
        # If only one scheme is acceptable, use it if available
        if len(acceptable_schemes) == 1:
            scheme = acceptable_schemes[0]
            if scheme == "BearerToken" and available_bearer:
                selected_auth = "bearer_token"
            elif scheme == "OAuth2UserToken" and available_oauth2:
                selected_auth = "oauth2_user_context"
            elif scheme == "UserToken" and available_oauth1:
                selected_auth = "oauth1"
        # Multiple schemes acceptable - use priority based on operation type
        elif len(acceptable_schemes) > 1:
            is_write_operation = "delete" in ["POST", "PUT", "DELETE", "PATCH"]
            if is_write_operation:
                # Priority for write operations: OAuth1 > OAuth2 User Token > Bearer Token
                if "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
            else:
                # Priority for read operations: Bearer Token > OAuth2 User Token > OAuth1
                if "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
        # Apply selected authentication
        if selected_auth == "oauth1":
            # OAuth1 authentication - build proper OAuth1 header dynamically
            # Build OAuth1 header with method, URL, and body
            # For OAuth1, we need to include query params in the URL for signature
            full_url = url
            if params:
                query_string = urllib.parse.urlencode(params)
                full_url = f"{url}?{query_string}" if query_string else url
            # Prepare body for OAuth1 signature (form-encoded, not JSON)
            body_string = ""
            # Build OAuth1 authorization header
            oauth_header = self.client.auth.build_request_header(
                method="delete", url=full_url, body=body_string
            )
            headers["Authorization"] = oauth_header
        elif selected_auth == "bearer_token":
            # Bearer token authentication
            if self.client.bearer_token:
                headers["Authorization"] = f"Bearer {self.client.bearer_token}"
            elif self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
        elif selected_auth == "oauth2_user_context":
            # OAuth2 User Token authentication
            if self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
                # Check if token needs refresh
                if self.client.oauth2_auth and self.client.token:
                    if self.client.is_token_expired():
                        self.client.refresh_token()
                        if self.client.access_token:
                            headers["Authorization"] = (
                                f"Bearer {self.client.access_token}"
                            )
        # Make the request
        if not selected_auth:
            # No suitable auth method found - validate authentication
            required_schemes = (
                acceptable_schemes if "acceptable_schemes" in locals() else []
            )
            if required_schemes:
                available = []
                if available_bearer and "BearerToken" in required_schemes:
                    available.append("BearerToken")
                if available_oauth2 and "OAuth2UserToken" in required_schemes:
                    available.append("OAuth2UserToken")
                if available_oauth1 and "UserToken" in required_schemes:
                    available.append("UserToken")
                if not available:
                    raise ValueError(
                        f"Authentication required for this endpoint. Required schemes: {required_schemes}. Available: {[s for s in required_schemes if (s == 'BearerToken' and available_bearer) or (s == 'OAuth2UserToken' and available_oauth2) or (s == 'UserToken' and available_oauth1)]}"
                    )
        response = self.client.session.delete(
            url,
            params=params,
            headers=headers,
        )
        # Check for errors
        response.raise_for_status()
        # Parse the response data
        response_data = response.json()
        # Convert to Pydantic model if applicable
        return DeleteResponse.model_validate(response_data)


    def create_webhook_replay_job(
        self, body: Optional[CreateWebhookReplayJobRequest] = None
    ) -> CreateWebhookReplayJobResponse:
        """
        Create replay job for webhook
        Creates a replay job to retrieve events from up to the past 24 hours for all events delivered or attempted to be delivered to the webhook.
        body: Request body
        Returns:
            CreateWebhookReplayJobResponse: Response data
        """
        url = self.client.base_url + "/2/webhooks/replay"
        # Priority: bearer_token > access_token (matches TypeScript behavior)
        if self.client.bearer_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.bearer_token}"
            )
        elif self.client.access_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.access_token}"
            )
        params = {}
        headers = {}
        headers["Content-Type"] = "application/json"
        # Prepare request data
        json_data = None
        if body is not None:
            json_data = (
                body.model_dump(exclude_none=True)
                if hasattr(body, "model_dump")
                else body
            )
        # Select authentication method based on endpoint requirements and available credentials
        # Priority strategy (matches TypeScript):
        # 1. If endpoint only accepts one method, use that (if available)
        # 2. If endpoint accepts multiple methods:
        #    - For write operations (POST/PUT/DELETE/PATCH): Prefer OAuth1 > OAuth2 User Token > Bearer Token
        #    - For read operations (GET): Prefer Bearer Token > OAuth2 User Token > OAuth1
        # 3. If no security requirements: Bearer Token > OAuth2 User Token > OAuth1
        selected_auth = None
        # Check what auth methods we have available
        available_bearer = bool(self.client.bearer_token)
        available_oauth2 = bool(self.client.access_token)
        available_oauth1 = bool(self.client.auth and self.client.auth.access_token)
        # Count acceptable schemes
        acceptable_schemes = []
        acceptable_schemes.append("BearerToken")
        # If only one scheme is acceptable, use it if available
        if len(acceptable_schemes) == 1:
            scheme = acceptable_schemes[0]
            if scheme == "BearerToken" and available_bearer:
                selected_auth = "bearer_token"
            elif scheme == "OAuth2UserToken" and available_oauth2:
                selected_auth = "oauth2_user_context"
            elif scheme == "UserToken" and available_oauth1:
                selected_auth = "oauth1"
        # Multiple schemes acceptable - use priority based on operation type
        elif len(acceptable_schemes) > 1:
            is_write_operation = "post" in ["POST", "PUT", "DELETE", "PATCH"]
            if is_write_operation:
                # Priority for write operations: OAuth1 > OAuth2 User Token > Bearer Token
                if "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
            else:
                # Priority for read operations: Bearer Token > OAuth2 User Token > OAuth1
                if "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
        # Apply selected authentication
        if selected_auth == "oauth1":
            # OAuth1 authentication - build proper OAuth1 header dynamically
            # Build OAuth1 header with method, URL, and body
            # For OAuth1, we need to include query params in the URL for signature
            full_url = url
            if params:
                query_string = urllib.parse.urlencode(params)
                full_url = f"{url}?{query_string}" if query_string else url
            # Prepare body for OAuth1 signature (form-encoded, not JSON)
            body_string = ""
            if json_data:
                # OAuth1 spec: JSON bodies are NOT included in signature
                # But we still need to pass the body for the request
                body_string = ""
            # Build OAuth1 authorization header
            oauth_header = self.client.auth.build_request_header(
                method="post", url=full_url, body=body_string
            )
            headers["Authorization"] = oauth_header
        elif selected_auth == "bearer_token":
            # Bearer token authentication
            if self.client.bearer_token:
                headers["Authorization"] = f"Bearer {self.client.bearer_token}"
            elif self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
        elif selected_auth == "oauth2_user_context":
            # OAuth2 User Token authentication
            if self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
                # Check if token needs refresh
                if self.client.oauth2_auth and self.client.token:
                    if self.client.is_token_expired():
                        self.client.refresh_token()
                        if self.client.access_token:
                            headers["Authorization"] = (
                                f"Bearer {self.client.access_token}"
                            )
        # Make the request
        if not selected_auth:
            # No suitable auth method found - validate authentication
            required_schemes = (
                acceptable_schemes if "acceptable_schemes" in locals() else []
            )
            if required_schemes:
                available = []
                if available_bearer and "BearerToken" in required_schemes:
                    available.append("BearerToken")
                if available_oauth2 and "OAuth2UserToken" in required_schemes:
                    available.append("OAuth2UserToken")
                if available_oauth1 and "UserToken" in required_schemes:
                    available.append("UserToken")
                if not available:
                    raise ValueError(
                        f"Authentication required for this endpoint. Required schemes: {required_schemes}. Available: {[s for s in required_schemes if (s == 'BearerToken' and available_bearer) or (s == 'OAuth2UserToken' and available_oauth2) or (s == 'UserToken' and available_oauth1)]}"
                    )
        response = self.client.session.post(
            url,
            params=params,
            headers=headers,
            json=json_data,
        )
        # Check for errors
        response.raise_for_status()
        # Parse the response data
        response_data = response.json()
        # Convert to Pydantic model if applicable
        return CreateWebhookReplayJobResponse.model_validate(response_data)


    def get_stream_links(
        self,
    ) -> GetStreamLinksResponse:
        """
        Get stream links
        Get a list of webhook links associated with a filtered stream ruleset.
        Returns:
            GetStreamLinksResponse: Response data
        """
        url = self.client.base_url + "/2/tweets/search/webhooks"
        # Priority: bearer_token > access_token (matches TypeScript behavior)
        if self.client.bearer_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.bearer_token}"
            )
        elif self.client.access_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.access_token}"
            )
        params = {}
        headers = {}
        # Prepare request data
        json_data = None
        # Select authentication method based on endpoint requirements and available credentials
        # Priority strategy (matches TypeScript):
        # 1. If endpoint only accepts one method, use that (if available)
        # 2. If endpoint accepts multiple methods:
        #    - For write operations (POST/PUT/DELETE/PATCH): Prefer OAuth1 > OAuth2 User Token > Bearer Token
        #    - For read operations (GET): Prefer Bearer Token > OAuth2 User Token > OAuth1
        # 3. If no security requirements: Bearer Token > OAuth2 User Token > OAuth1
        selected_auth = None
        # Check what auth methods we have available
        available_bearer = bool(self.client.bearer_token)
        available_oauth2 = bool(self.client.access_token)
        available_oauth1 = bool(self.client.auth and self.client.auth.access_token)
        # Count acceptable schemes
        acceptable_schemes = []
        acceptable_schemes.append("BearerToken")
        # If only one scheme is acceptable, use it if available
        if len(acceptable_schemes) == 1:
            scheme = acceptable_schemes[0]
            if scheme == "BearerToken" and available_bearer:
                selected_auth = "bearer_token"
            elif scheme == "OAuth2UserToken" and available_oauth2:
                selected_auth = "oauth2_user_context"
            elif scheme == "UserToken" and available_oauth1:
                selected_auth = "oauth1"
        # Multiple schemes acceptable - use priority based on operation type
        elif len(acceptable_schemes) > 1:
            is_write_operation = "get" in ["POST", "PUT", "DELETE", "PATCH"]
            if is_write_operation:
                # Priority for write operations: OAuth1 > OAuth2 User Token > Bearer Token
                if "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
            else:
                # Priority for read operations: Bearer Token > OAuth2 User Token > OAuth1
                if "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
        # Apply selected authentication
        if selected_auth == "oauth1":
            # OAuth1 authentication - build proper OAuth1 header dynamically
            # Build OAuth1 header with method, URL, and body
            # For OAuth1, we need to include query params in the URL for signature
            full_url = url
            if params:
                query_string = urllib.parse.urlencode(params)
                full_url = f"{url}?{query_string}" if query_string else url
            # Prepare body for OAuth1 signature (form-encoded, not JSON)
            body_string = ""
            # Build OAuth1 authorization header
            oauth_header = self.client.auth.build_request_header(
                method="get", url=full_url, body=body_string
            )
            headers["Authorization"] = oauth_header
        elif selected_auth == "bearer_token":
            # Bearer token authentication
            if self.client.bearer_token:
                headers["Authorization"] = f"Bearer {self.client.bearer_token}"
            elif self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
        elif selected_auth == "oauth2_user_context":
            # OAuth2 User Token authentication
            if self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
                # Check if token needs refresh
                if self.client.oauth2_auth and self.client.token:
                    if self.client.is_token_expired():
                        self.client.refresh_token()
                        if self.client.access_token:
                            headers["Authorization"] = (
                                f"Bearer {self.client.access_token}"
                            )
        # Make the request
        if not selected_auth:
            # No suitable auth method found - validate authentication
            required_schemes = (
                acceptable_schemes if "acceptable_schemes" in locals() else []
            )
            if required_schemes:
                available = []
                if available_bearer and "BearerToken" in required_schemes:
                    available.append("BearerToken")
                if available_oauth2 and "OAuth2UserToken" in required_schemes:
                    available.append("OAuth2UserToken")
                if available_oauth1 and "UserToken" in required_schemes:
                    available.append("UserToken")
                if not available:
                    raise ValueError(
                        f"Authentication required for this endpoint. Required schemes: {required_schemes}. Available: {[s for s in required_schemes if (s == 'BearerToken' and available_bearer) or (s == 'OAuth2UserToken' and available_oauth2) or (s == 'UserToken' and available_oauth1)]}"
                    )
        response = self.client.session.get(
            url,
            params=params,
            headers=headers,
        )
        # Check for errors
        response.raise_for_status()
        # Parse the response data
        response_data = response.json()
        # Convert to Pydantic model if applicable
        return GetStreamLinksResponse.model_validate(response_data)


    def get(self, webhook_config_fields: List = None) -> GetResponse:
        """
        Get webhook
        Get a list of webhook configs associated with a client app.
        Args:
            webhook_config_fields: A comma separated list of WebhookConfig fields to display.
            Returns:
            GetResponse: Response data
        """
        url = self.client.base_url + "/2/webhooks"
        # Priority: bearer_token > access_token (matches TypeScript behavior)
        if self.client.bearer_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.bearer_token}"
            )
        elif self.client.access_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.access_token}"
            )
        params = {}
        if webhook_config_fields is not None:
            params["webhook_config.fields"] = ",".join(
                str(item) for item in webhook_config_fields
            )
        headers = {}
        # Prepare request data
        json_data = None
        # Select authentication method based on endpoint requirements and available credentials
        # Priority strategy (matches TypeScript):
        # 1. If endpoint only accepts one method, use that (if available)
        # 2. If endpoint accepts multiple methods:
        #    - For write operations (POST/PUT/DELETE/PATCH): Prefer OAuth1 > OAuth2 User Token > Bearer Token
        #    - For read operations (GET): Prefer Bearer Token > OAuth2 User Token > OAuth1
        # 3. If no security requirements: Bearer Token > OAuth2 User Token > OAuth1
        selected_auth = None
        # Check what auth methods we have available
        available_bearer = bool(self.client.bearer_token)
        available_oauth2 = bool(self.client.access_token)
        available_oauth1 = bool(self.client.auth and self.client.auth.access_token)
        # Count acceptable schemes
        acceptable_schemes = []
        acceptable_schemes.append("BearerToken")
        # If only one scheme is acceptable, use it if available
        if len(acceptable_schemes) == 1:
            scheme = acceptable_schemes[0]
            if scheme == "BearerToken" and available_bearer:
                selected_auth = "bearer_token"
            elif scheme == "OAuth2UserToken" and available_oauth2:
                selected_auth = "oauth2_user_context"
            elif scheme == "UserToken" and available_oauth1:
                selected_auth = "oauth1"
        # Multiple schemes acceptable - use priority based on operation type
        elif len(acceptable_schemes) > 1:
            is_write_operation = "get" in ["POST", "PUT", "DELETE", "PATCH"]
            if is_write_operation:
                # Priority for write operations: OAuth1 > OAuth2 User Token > Bearer Token
                if "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
            else:
                # Priority for read operations: Bearer Token > OAuth2 User Token > OAuth1
                if "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
        # Apply selected authentication
        if selected_auth == "oauth1":
            # OAuth1 authentication - build proper OAuth1 header dynamically
            # Build OAuth1 header with method, URL, and body
            # For OAuth1, we need to include query params in the URL for signature
            full_url = url
            if params:
                query_string = urllib.parse.urlencode(params)
                full_url = f"{url}?{query_string}" if query_string else url
            # Prepare body for OAuth1 signature (form-encoded, not JSON)
            body_string = ""
            # Build OAuth1 authorization header
            oauth_header = self.client.auth.build_request_header(
                method="get", url=full_url, body=body_string
            )
            headers["Authorization"] = oauth_header
        elif selected_auth == "bearer_token":
            # Bearer token authentication
            if self.client.bearer_token:
                headers["Authorization"] = f"Bearer {self.client.bearer_token}"
            elif self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
        elif selected_auth == "oauth2_user_context":
            # OAuth2 User Token authentication
            if self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
                # Check if token needs refresh
                if self.client.oauth2_auth and self.client.token:
                    if self.client.is_token_expired():
                        self.client.refresh_token()
                        if self.client.access_token:
                            headers["Authorization"] = (
                                f"Bearer {self.client.access_token}"
                            )
        # Make the request
        if not selected_auth:
            # No suitable auth method found - validate authentication
            required_schemes = (
                acceptable_schemes if "acceptable_schemes" in locals() else []
            )
            if required_schemes:
                available = []
                if available_bearer and "BearerToken" in required_schemes:
                    available.append("BearerToken")
                if available_oauth2 and "OAuth2UserToken" in required_schemes:
                    available.append("OAuth2UserToken")
                if available_oauth1 and "UserToken" in required_schemes:
                    available.append("UserToken")
                if not available:
                    raise ValueError(
                        f"Authentication required for this endpoint. Required schemes: {required_schemes}. Available: {[s for s in required_schemes if (s == 'BearerToken' and available_bearer) or (s == 'OAuth2UserToken' and available_oauth2) or (s == 'UserToken' and available_oauth1)]}"
                    )
        response = self.client.session.get(
            url,
            params=params,
            headers=headers,
        )
        # Check for errors
        response.raise_for_status()
        # Parse the response data
        response_data = response.json()
        # Convert to Pydantic model if applicable
        return GetResponse.model_validate(response_data)


    def create(self, body: Optional[CreateRequest] = None) -> CreateResponse:
        """
        Create webhook
        Creates a new webhook configuration.
        body: Request body
        Returns:
            CreateResponse: Response data
        """
        url = self.client.base_url + "/2/webhooks"
        # Priority: bearer_token > access_token (matches TypeScript behavior)
        if self.client.bearer_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.bearer_token}"
            )
        elif self.client.access_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.access_token}"
            )
        # UserToken: OAuth1.0a authentication - header will be built dynamically in request
        # OAuth1 header must be built per-request with method, URL, and body
        # This is handled in the request logic below
        params = {}
        headers = {}
        headers["Content-Type"] = "application/json"
        # Prepare request data
        json_data = None
        if body is not None:
            json_data = (
                body.model_dump(exclude_none=True)
                if hasattr(body, "model_dump")
                else body
            )
        # Select authentication method based on endpoint requirements and available credentials
        # Priority strategy (matches TypeScript):
        # 1. If endpoint only accepts one method, use that (if available)
        # 2. If endpoint accepts multiple methods:
        #    - For write operations (POST/PUT/DELETE/PATCH): Prefer OAuth1 > OAuth2 User Token > Bearer Token
        #    - For read operations (GET): Prefer Bearer Token > OAuth2 User Token > OAuth1
        # 3. If no security requirements: Bearer Token > OAuth2 User Token > OAuth1
        selected_auth = None
        # Check what auth methods we have available
        available_bearer = bool(self.client.bearer_token)
        available_oauth2 = bool(self.client.access_token)
        available_oauth1 = bool(self.client.auth and self.client.auth.access_token)
        # Count acceptable schemes
        acceptable_schemes = []
        acceptable_schemes.append("BearerToken")
        acceptable_schemes.append("UserToken")
        # If only one scheme is acceptable, use it if available
        if len(acceptable_schemes) == 1:
            scheme = acceptable_schemes[0]
            if scheme == "BearerToken" and available_bearer:
                selected_auth = "bearer_token"
            elif scheme == "OAuth2UserToken" and available_oauth2:
                selected_auth = "oauth2_user_context"
            elif scheme == "UserToken" and available_oauth1:
                selected_auth = "oauth1"
        # Multiple schemes acceptable - use priority based on operation type
        elif len(acceptable_schemes) > 1:
            is_write_operation = "post" in ["POST", "PUT", "DELETE", "PATCH"]
            if is_write_operation:
                # Priority for write operations: OAuth1 > OAuth2 User Token > Bearer Token
                if "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
            else:
                # Priority for read operations: Bearer Token > OAuth2 User Token > OAuth1
                if "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
        # Apply selected authentication
        if selected_auth == "oauth1":
            # OAuth1 authentication - build proper OAuth1 header dynamically
            # Build OAuth1 header with method, URL, and body
            # For OAuth1, we need to include query params in the URL for signature
            full_url = url
            if params:
                query_string = urllib.parse.urlencode(params)
                full_url = f"{url}?{query_string}" if query_string else url
            # Prepare body for OAuth1 signature (form-encoded, not JSON)
            body_string = ""
            if json_data:
                # OAuth1 spec: JSON bodies are NOT included in signature
                # But we still need to pass the body for the request
                body_string = ""
            # Build OAuth1 authorization header
            oauth_header = self.client.auth.build_request_header(
                method="post", url=full_url, body=body_string
            )
            headers["Authorization"] = oauth_header
        elif selected_auth == "bearer_token":
            # Bearer token authentication
            if self.client.bearer_token:
                headers["Authorization"] = f"Bearer {self.client.bearer_token}"
            elif self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
        elif selected_auth == "oauth2_user_context":
            # OAuth2 User Token authentication
            if self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
                # Check if token needs refresh
                if self.client.oauth2_auth and self.client.token:
                    if self.client.is_token_expired():
                        self.client.refresh_token()
                        if self.client.access_token:
                            headers["Authorization"] = (
                                f"Bearer {self.client.access_token}"
                            )
        # Make the request
        if not selected_auth:
            # No suitable auth method found - validate authentication
            required_schemes = (
                acceptable_schemes if "acceptable_schemes" in locals() else []
            )
            if required_schemes:
                available = []
                if available_bearer and "BearerToken" in required_schemes:
                    available.append("BearerToken")
                if available_oauth2 and "OAuth2UserToken" in required_schemes:
                    available.append("OAuth2UserToken")
                if available_oauth1 and "UserToken" in required_schemes:
                    available.append("UserToken")
                if not available:
                    raise ValueError(
                        f"Authentication required for this endpoint. Required schemes: {required_schemes}. Available: {[s for s in required_schemes if (s == 'BearerToken' and available_bearer) or (s == 'OAuth2UserToken' and available_oauth2) or (s == 'UserToken' and available_oauth1)]}"
                    )
        response = self.client.session.post(
            url,
            params=params,
            headers=headers,
            json=json_data,
        )
        # Check for errors
        response.raise_for_status()
        # Parse the response data
        response_data = response.json()
        # Convert to Pydantic model if applicable
        return CreateResponse.model_validate(response_data)


    def create_stream_link(
        self,
        webhook_id: Any,
        tweet_fields: str = None,
        expansions: str = None,
        media_fields: str = None,
        poll_fields: str = None,
        user_fields: str = None,
        place_fields: str = None,
    ) -> CreateStreamLinkResponse:
        """
        Create stream link
        Creates a link to deliver FilteredStream events to the given webhook.
        Args:
            webhook_id: The webhook ID to link to your FilteredStream ruleset.
            tweet_fields: A comma separated list of Tweet fields to display.
            expansions: A comma separated list of fields to expand.
            media_fields: A comma separated list of Media fields to display.
            poll_fields: A comma separated list of Poll fields to display.
            user_fields: A comma separated list of User fields to display.
            place_fields: A comma separated list of Place fields to display.
            Returns:
            CreateStreamLinkResponse: Response data
        """
        url = self.client.base_url + "/2/tweets/search/webhooks/{webhook_id}"
        url = url.replace("{webhook_id}", str(webhook_id))
        # Priority: bearer_token > access_token (matches TypeScript behavior)
        if self.client.bearer_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.bearer_token}"
            )
        elif self.client.access_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.access_token}"
            )
        params = {}
        if tweet_fields is not None:
            params["tweet.fields"] = tweet_fields
        if expansions is not None:
            params["expansions"] = expansions
        if media_fields is not None:
            params["media.fields"] = media_fields
        if poll_fields is not None:
            params["poll.fields"] = poll_fields
        if user_fields is not None:
            params["user.fields"] = user_fields
        if place_fields is not None:
            params["place.fields"] = place_fields
        headers = {}
        # Prepare request data
        json_data = None
        # Select authentication method based on endpoint requirements and available credentials
        # Priority strategy (matches TypeScript):
        # 1. If endpoint only accepts one method, use that (if available)
        # 2. If endpoint accepts multiple methods:
        #    - For write operations (POST/PUT/DELETE/PATCH): Prefer OAuth1 > OAuth2 User Token > Bearer Token
        #    - For read operations (GET): Prefer Bearer Token > OAuth2 User Token > OAuth1
        # 3. If no security requirements: Bearer Token > OAuth2 User Token > OAuth1
        selected_auth = None
        # Check what auth methods we have available
        available_bearer = bool(self.client.bearer_token)
        available_oauth2 = bool(self.client.access_token)
        available_oauth1 = bool(self.client.auth and self.client.auth.access_token)
        # Count acceptable schemes
        acceptable_schemes = []
        acceptable_schemes.append("BearerToken")
        # If only one scheme is acceptable, use it if available
        if len(acceptable_schemes) == 1:
            scheme = acceptable_schemes[0]
            if scheme == "BearerToken" and available_bearer:
                selected_auth = "bearer_token"
            elif scheme == "OAuth2UserToken" and available_oauth2:
                selected_auth = "oauth2_user_context"
            elif scheme == "UserToken" and available_oauth1:
                selected_auth = "oauth1"
        # Multiple schemes acceptable - use priority based on operation type
        elif len(acceptable_schemes) > 1:
            is_write_operation = "post" in ["POST", "PUT", "DELETE", "PATCH"]
            if is_write_operation:
                # Priority for write operations: OAuth1 > OAuth2 User Token > Bearer Token
                if "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
            else:
                # Priority for read operations: Bearer Token > OAuth2 User Token > OAuth1
                if "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
        # Apply selected authentication
        if selected_auth == "oauth1":
            # OAuth1 authentication - build proper OAuth1 header dynamically
            # Build OAuth1 header with method, URL, and body
            # For OAuth1, we need to include query params in the URL for signature
            full_url = url
            if params:
                query_string = urllib.parse.urlencode(params)
                full_url = f"{url}?{query_string}" if query_string else url
            # Prepare body for OAuth1 signature (form-encoded, not JSON)
            body_string = ""
            # Build OAuth1 authorization header
            oauth_header = self.client.auth.build_request_header(
                method="post", url=full_url, body=body_string
            )
            headers["Authorization"] = oauth_header
        elif selected_auth == "bearer_token":
            # Bearer token authentication
            if self.client.bearer_token:
                headers["Authorization"] = f"Bearer {self.client.bearer_token}"
            elif self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
        elif selected_auth == "oauth2_user_context":
            # OAuth2 User Token authentication
            if self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
                # Check if token needs refresh
                if self.client.oauth2_auth and self.client.token:
                    if self.client.is_token_expired():
                        self.client.refresh_token()
                        if self.client.access_token:
                            headers["Authorization"] = (
                                f"Bearer {self.client.access_token}"
                            )
        # Make the request
        if not selected_auth:
            # No suitable auth method found - validate authentication
            required_schemes = (
                acceptable_schemes if "acceptable_schemes" in locals() else []
            )
            if required_schemes:
                available = []
                if available_bearer and "BearerToken" in required_schemes:
                    available.append("BearerToken")
                if available_oauth2 and "OAuth2UserToken" in required_schemes:
                    available.append("OAuth2UserToken")
                if available_oauth1 and "UserToken" in required_schemes:
                    available.append("UserToken")
                if not available:
                    raise ValueError(
                        f"Authentication required for this endpoint. Required schemes: {required_schemes}. Available: {[s for s in required_schemes if (s == 'BearerToken' and available_bearer) or (s == 'OAuth2UserToken' and available_oauth2) or (s == 'UserToken' and available_oauth1)]}"
                    )
        response = self.client.session.post(
            url,
            params=params,
            headers=headers,
        )
        # Check for errors
        response.raise_for_status()
        # Parse the response data
        response_data = response.json()
        # Convert to Pydantic model if applicable
        return CreateStreamLinkResponse.model_validate(response_data)


    def delete_stream_link(self, webhook_id: Any) -> DeleteStreamLinkResponse:
        """
        Delete stream link
        Deletes a link from FilteredStream events to the given webhook.
        Args:
            webhook_id: The webhook ID to link to your FilteredStream ruleset.
            Returns:
            DeleteStreamLinkResponse: Response data
        """
        url = self.client.base_url + "/2/tweets/search/webhooks/{webhook_id}"
        url = url.replace("{webhook_id}", str(webhook_id))
        # Priority: bearer_token > access_token (matches TypeScript behavior)
        if self.client.bearer_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.bearer_token}"
            )
        elif self.client.access_token:
            self.client.session.headers["Authorization"] = (
                f"Bearer {self.client.access_token}"
            )
        params = {}
        headers = {}
        # Prepare request data
        json_data = None
        # Select authentication method based on endpoint requirements and available credentials
        # Priority strategy (matches TypeScript):
        # 1. If endpoint only accepts one method, use that (if available)
        # 2. If endpoint accepts multiple methods:
        #    - For write operations (POST/PUT/DELETE/PATCH): Prefer OAuth1 > OAuth2 User Token > Bearer Token
        #    - For read operations (GET): Prefer Bearer Token > OAuth2 User Token > OAuth1
        # 3. If no security requirements: Bearer Token > OAuth2 User Token > OAuth1
        selected_auth = None
        # Check what auth methods we have available
        available_bearer = bool(self.client.bearer_token)
        available_oauth2 = bool(self.client.access_token)
        available_oauth1 = bool(self.client.auth and self.client.auth.access_token)
        # Count acceptable schemes
        acceptable_schemes = []
        acceptable_schemes.append("BearerToken")
        # If only one scheme is acceptable, use it if available
        if len(acceptable_schemes) == 1:
            scheme = acceptable_schemes[0]
            if scheme == "BearerToken" and available_bearer:
                selected_auth = "bearer_token"
            elif scheme == "OAuth2UserToken" and available_oauth2:
                selected_auth = "oauth2_user_context"
            elif scheme == "UserToken" and available_oauth1:
                selected_auth = "oauth1"
        # Multiple schemes acceptable - use priority based on operation type
        elif len(acceptable_schemes) > 1:
            is_write_operation = "delete" in ["POST", "PUT", "DELETE", "PATCH"]
            if is_write_operation:
                # Priority for write operations: OAuth1 > OAuth2 User Token > Bearer Token
                if "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
            else:
                # Priority for read operations: Bearer Token > OAuth2 User Token > OAuth1
                if "BearerToken" in acceptable_schemes and available_bearer:
                    selected_auth = "bearer_token"
                elif "OAuth2UserToken" in acceptable_schemes and available_oauth2:
                    selected_auth = "oauth2_user_context"
                elif "UserToken" in acceptable_schemes and available_oauth1:
                    selected_auth = "oauth1"
        # Apply selected authentication
        if selected_auth == "oauth1":
            # OAuth1 authentication - build proper OAuth1 header dynamically
            # Build OAuth1 header with method, URL, and body
            # For OAuth1, we need to include query params in the URL for signature
            full_url = url
            if params:
                query_string = urllib.parse.urlencode(params)
                full_url = f"{url}?{query_string}" if query_string else url
            # Prepare body for OAuth1 signature (form-encoded, not JSON)
            body_string = ""
            # Build OAuth1 authorization header
            oauth_header = self.client.auth.build_request_header(
                method="delete", url=full_url, body=body_string
            )
            headers["Authorization"] = oauth_header
        elif selected_auth == "bearer_token":
            # Bearer token authentication
            if self.client.bearer_token:
                headers["Authorization"] = f"Bearer {self.client.bearer_token}"
            elif self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
        elif selected_auth == "oauth2_user_context":
            # OAuth2 User Token authentication
            if self.client.access_token:
                headers["Authorization"] = f"Bearer {self.client.access_token}"
                # Check if token needs refresh
                if self.client.oauth2_auth and self.client.token:
                    if self.client.is_token_expired():
                        self.client.refresh_token()
                        if self.client.access_token:
                            headers["Authorization"] = (
                                f"Bearer {self.client.access_token}"
                            )
        # Make the request
        if not selected_auth:
            # No suitable auth method found - validate authentication
            required_schemes = (
                acceptable_schemes if "acceptable_schemes" in locals() else []
            )
            if required_schemes:
                available = []
                if available_bearer and "BearerToken" in required_schemes:
                    available.append("BearerToken")
                if available_oauth2 and "OAuth2UserToken" in required_schemes:
                    available.append("OAuth2UserToken")
                if available_oauth1 and "UserToken" in required_schemes:
                    available.append("UserToken")
                if not available:
                    raise ValueError(
                        f"Authentication required for this endpoint. Required schemes: {required_schemes}. Available: {[s for s in required_schemes if (s == 'BearerToken' and available_bearer) or (s == 'OAuth2UserToken' and available_oauth2) or (s == 'UserToken' and available_oauth1)]}"
                    )
        response = self.client.session.delete(
            url,
            params=params,
            headers=headers,
        )
        # Check for errors
        response.raise_for_status()
        # Parse the response data
        response_data = response.json()
        # Convert to Pydantic model if applicable
        return DeleteStreamLinkResponse.model_validate(response_data)
