"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from .basesdk import BaseSDK
from .httpclient import AsyncHttpClient, ClientOwner, HttpClient, close_clients
from .sdkconfiguration import SDKConfiguration
from .utils.logger import Logger, get_default_logger
from .utils.retries import RetryConfig
import httpx
import importlib
from squadcast_sdk import models, utils
from squadcast_sdk._hooks import SDKHooks
from squadcast_sdk.types import OptionalNullable, UNSET
import sys
from typing import Any, Callable, Dict, Optional, TYPE_CHECKING, Union, cast
import weakref

if TYPE_CHECKING:
    from squadcast_sdk.additionalresponders import AdditionalResponders
    from squadcast_sdk.analytics import Analytics
    from squadcast_sdk.auditlogs import AuditLogs
    from squadcast_sdk.auth import Auth
    from squadcast_sdk.communicationcards import CommunicationCards
    from squadcast_sdk.componentgroups import ComponentGroups
    from squadcast_sdk.components import Components
    from squadcast_sdk.dedupkeys import DedupKeys
    from squadcast_sdk.escalationpolicies_sdk import EscalationPoliciesSDK
    from squadcast_sdk.exports import Exports
    from squadcast_sdk.exportschedule import ExportSchedule
    from squadcast_sdk.extensions import Extensions
    from squadcast_sdk.globaleventrules import GlobalEventRules
    from squadcast_sdk.globaloncallreminderrules_sdk import GlobalOncallReminderRulesSDK
    from squadcast_sdk.incidents import Incidents
    from squadcast_sdk.issues import Issues
    from squadcast_sdk.maintenances import Maintenances
    from squadcast_sdk.overlays import Overlays
    from squadcast_sdk.overrides import Overrides
    from squadcast_sdk.postmortems_sdk import PostmortemsSDK
    from squadcast_sdk.rotations import Rotations
    from squadcast_sdk.rules import Rules
    from squadcast_sdk.rulesets import Rulesets
    from squadcast_sdk.runbooks_sdk import RunbooksSDK
    from squadcast_sdk.schedules_sdk import SchedulesSDK
    from squadcast_sdk.services_sdk import ServicesSDK
    from squadcast_sdk.slos_sdk import SlosSDK
    from squadcast_sdk.snoozenotifications import SnoozeNotifications
    from squadcast_sdk.squads_sdk import SquadsSDK
    from squadcast_sdk.squadsv4 import SquadsV4
    from squadcast_sdk.statuspages_sdk_1 import StatusPagesSDK1
    from squadcast_sdk.statuspages_sdk_2 import StatuspagesSDK2
    from squadcast_sdk.subscribers import Subscribers
    from squadcast_sdk.teams import Teams
    from squadcast_sdk.users import Users
    from squadcast_sdk.webforms_sdk import WebformsSDK
    from squadcast_sdk.webhooks import Webhooks
    from squadcast_sdk.workflows_sdk import WorkflowsSDK


class SquadcastSDK(BaseSDK):
    r"""Squadcast: ## Overview
    The Squadcast API provides developers the capability to extend and utilize Squadcast in conjunction with other services. Our API has resource-oriented URLs, accepts JSON-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.

    > **Note:** Customers using the V2 version of the Squadcast API would need to migrate to Squadcast API V3, as the former would be deprecated shortly.

    ### Service Regions

    Squadcast allows customers to choose the geographic region of the Squadcast data centers that host their account. When signing up, you can choose the service region. Currently, the available options are the United States (US) and Europe (EU).

    | Service Region | API Endpoints |
    |---|---|
    | US | Authentication: https://auth.squadcast.com · Other APIs: https://api.squadcast.com |
    | EU | Authentication: https://auth.eu.squadcast.com · Other APIs: https://api.eu.squadcast.com |

    ### Authentication

    In order to access the API programmatically, HTTP bearer authentication needs to be used. HTTP bearer authentication must be constructed using an `access_token`, passed as the `Authorization` header for each request, for example `Authorization: Bearer eyJleHAiOjE2MzU1OTE1OTIsImp0aSI6Im`.

    Steps to procure the `access_token`:

    1. Generate a `refresh_token` (API Token) from the Squadcast web app. More details on how to get the `refresh_token` can be found in the Squadcast support documentation.
    2. Call the authentication API with the `refresh_token` to obtain an `access_token`.
    3. Use the `access_token` as a Bearer token in the `Authorization` header for all subsequent API requests.

    #### Example — Generating an Access Token

    ```bash
    curl --location --request GET 'https://auth.squadcast.com/oauth/access-token' \ 
    --header 'X-Refresh-Token: 0d2a1a9a454dxxxxxxxxxxxx'
    ```

    The API response will look similar to:

    ```json
    {
    \"data\": {
    \"access_token\": \"eyJhbGciOiJIUxxxxx.xxxxxxxxxxxxxxx.xxxxxxxxxxxxxxx\",
    \"expires_at\": 1587412870,
    \"issued_at\": 1587240070,
    \"refresh_token\": \"0d2a1a9a454dxxxxxxxxxxxx\",
    \"type\": \"bearer\" 
    }
    }
    ```

    ### Access Control

    There are three different types of user roles in Squadcast: `account_owner`, `stakeholder`, and `user`. Refresh tokens upon creation are mapped with one of the mentioned user roles, and access to different resources is dependent on the permissions granted to these roles. For more information, please refer to the Squadcast support documentation.

    ### Authorization

    The access token authorizes users the ability to access different APIs, based on the user roles described above. Pass the access token as a Bearer token in the `Authorization` header of every request.
    """

    auth: "Auth"
    analytics: "Analytics"
    audit_logs: "AuditLogs"
    escalation_policies: "EscalationPoliciesSDK"
    exports: "Exports"
    extensions: "Extensions"
    webhooks: "Webhooks"
    incidents: "Incidents"
    global_event_rules: "GlobalEventRules"
    rulesets: "Rulesets"
    rules: "Rules"
    global_oncall_reminder_rules: "GlobalOncallReminderRulesSDK"
    postmortems: "PostmortemsSDK"
    communication_cards: "CommunicationCards"
    runbooks: "RunbooksSDK"
    additional_responders: "AdditionalResponders"
    snooze_notifications: "SnoozeNotifications"
    users: "Users"
    services: "ServicesSDK"
    dedup_keys: "DedupKeys"
    overlays: "Overlays"
    slos: "SlosSDK"
    teams: "Teams"
    webforms: "WebformsSDK"
    workflows: "WorkflowsSDK"
    schedules: "SchedulesSDK"
    export_schedule: "ExportSchedule"
    overrides: "Overrides"
    rotations: "Rotations"
    squads: "SquadsSDK"
    squads_v4: "SquadsV4"
    status_pages: "StatusPagesSDK1"
    components: "Components"
    component_groups: "ComponentGroups"
    issues: "Issues"
    maintenances: "Maintenances"
    statuspages: "StatuspagesSDK2"
    subscribers: "Subscribers"
    _sub_sdk_map = {
        "auth": ("squadcast_sdk.auth", "Auth"),
        "analytics": ("squadcast_sdk.analytics", "Analytics"),
        "audit_logs": ("squadcast_sdk.auditlogs", "AuditLogs"),
        "escalation_policies": (
            "squadcast_sdk.escalationpolicies_sdk",
            "EscalationPoliciesSDK",
        ),
        "exports": ("squadcast_sdk.exports", "Exports"),
        "extensions": ("squadcast_sdk.extensions", "Extensions"),
        "webhooks": ("squadcast_sdk.webhooks", "Webhooks"),
        "incidents": ("squadcast_sdk.incidents", "Incidents"),
        "global_event_rules": ("squadcast_sdk.globaleventrules", "GlobalEventRules"),
        "rulesets": ("squadcast_sdk.rulesets", "Rulesets"),
        "rules": ("squadcast_sdk.rules", "Rules"),
        "global_oncall_reminder_rules": (
            "squadcast_sdk.globaloncallreminderrules_sdk",
            "GlobalOncallReminderRulesSDK",
        ),
        "postmortems": ("squadcast_sdk.postmortems_sdk", "PostmortemsSDK"),
        "communication_cards": (
            "squadcast_sdk.communicationcards",
            "CommunicationCards",
        ),
        "runbooks": ("squadcast_sdk.runbooks_sdk", "RunbooksSDK"),
        "additional_responders": (
            "squadcast_sdk.additionalresponders",
            "AdditionalResponders",
        ),
        "snooze_notifications": (
            "squadcast_sdk.snoozenotifications",
            "SnoozeNotifications",
        ),
        "users": ("squadcast_sdk.users", "Users"),
        "services": ("squadcast_sdk.services_sdk", "ServicesSDK"),
        "dedup_keys": ("squadcast_sdk.dedupkeys", "DedupKeys"),
        "overlays": ("squadcast_sdk.overlays", "Overlays"),
        "slos": ("squadcast_sdk.slos_sdk", "SlosSDK"),
        "teams": ("squadcast_sdk.teams", "Teams"),
        "webforms": ("squadcast_sdk.webforms_sdk", "WebformsSDK"),
        "workflows": ("squadcast_sdk.workflows_sdk", "WorkflowsSDK"),
        "schedules": ("squadcast_sdk.schedules_sdk", "SchedulesSDK"),
        "export_schedule": ("squadcast_sdk.exportschedule", "ExportSchedule"),
        "overrides": ("squadcast_sdk.overrides", "Overrides"),
        "rotations": ("squadcast_sdk.rotations", "Rotations"),
        "squads": ("squadcast_sdk.squads_sdk", "SquadsSDK"),
        "squads_v4": ("squadcast_sdk.squadsv4", "SquadsV4"),
        "status_pages": ("squadcast_sdk.statuspages_sdk_1", "StatusPagesSDK1"),
        "components": ("squadcast_sdk.components", "Components"),
        "component_groups": ("squadcast_sdk.componentgroups", "ComponentGroups"),
        "issues": ("squadcast_sdk.issues", "Issues"),
        "maintenances": ("squadcast_sdk.maintenances", "Maintenances"),
        "statuspages": ("squadcast_sdk.statuspages_sdk_2", "StatuspagesSDK2"),
        "subscribers": ("squadcast_sdk.subscribers", "Subscribers"),
    }

    def __init__(
        self,
        bearer_auth: Optional[Union[Optional[str], Callable[[], Optional[str]]]] = None,
        server_idx: Optional[int] = None,
        url_params: Optional[Dict[str, str]] = None,
        server_url: Optional[str] = None,
        client: Optional[HttpClient] = None,
        async_client: Optional[AsyncHttpClient] = None,
        retry_config: OptionalNullable[RetryConfig] = UNSET,
        timeout_ms: Optional[int] = None,
        debug_logger: Optional[Logger] = None,
    ) -> None:
        r"""Instantiates the SDK configuring it with the provided parameters.

        :param bearer_auth: The bearer_auth required for authentication
        :param server_idx: The index of the server to use for all methods
        :param server_url: The server URL to use for all methods
        :param url_params: Parameters to optionally template the server URL with
        :param client: The HTTP client to use for all synchronous methods
        :param async_client: The Async HTTP client to use for all asynchronous methods
        :param retry_config: The retry configuration to use for all supported methods
        :param timeout_ms: Optional request timeout applied to each operation in milliseconds
        """
        client_supplied = True
        if client is None:
            client = httpx.Client(follow_redirects=True)
            client_supplied = False

        assert issubclass(
            type(client), HttpClient
        ), "The provided client must implement the HttpClient protocol."

        async_client_supplied = True
        if async_client is None:
            async_client = httpx.AsyncClient(follow_redirects=True)
            async_client_supplied = False

        if debug_logger is None:
            debug_logger = get_default_logger()

        assert issubclass(
            type(async_client), AsyncHttpClient
        ), "The provided async_client must implement the AsyncHttpClient protocol."

        security: Any = None
        if callable(bearer_auth):
            # pylint: disable=unnecessary-lambda-assignment
            security = lambda: models.Security(bearer_auth=bearer_auth())
        else:
            security = models.Security(bearer_auth=bearer_auth)

        if server_url is not None:
            if url_params is not None:
                server_url = utils.template_url(server_url, url_params)

        BaseSDK.__init__(
            self,
            SDKConfiguration(
                client=client,
                client_supplied=client_supplied,
                async_client=async_client,
                async_client_supplied=async_client_supplied,
                security=security,
                server_url=server_url,
                server_idx=server_idx,
                retry_config=retry_config,
                timeout_ms=timeout_ms,
                debug_logger=debug_logger,
            ),
            parent_ref=self,
        )

        hooks = SDKHooks()

        # pylint: disable=protected-access
        self.sdk_configuration.__dict__["_hooks"] = hooks

        self.sdk_configuration = hooks.sdk_init(self.sdk_configuration)

        weakref.finalize(
            self,
            close_clients,
            cast(ClientOwner, self.sdk_configuration),
            self.sdk_configuration.client,
            self.sdk_configuration.client_supplied,
            self.sdk_configuration.async_client,
            self.sdk_configuration.async_client_supplied,
        )

    def dynamic_import(self, modname, retries=3):
        for attempt in range(retries):
            try:
                return importlib.import_module(modname)
            except KeyError:
                # Clear any half-initialized module and retry
                sys.modules.pop(modname, None)
                if attempt == retries - 1:
                    break
        raise KeyError(f"Failed to import module '{modname}' after {retries} attempts")

    def __getattr__(self, name: str):
        if name in self._sub_sdk_map:
            module_path, class_name = self._sub_sdk_map[name]
            try:
                module = self.dynamic_import(module_path)
                klass = getattr(module, class_name)
                instance = klass(self.sdk_configuration, parent_ref=self)
                setattr(self, name, instance)
                return instance
            except ImportError as e:
                raise AttributeError(
                    f"Failed to import module {module_path} for attribute {name}: {e}"
                ) from e
            except AttributeError as e:
                raise AttributeError(
                    f"Failed to find class {class_name} in module {module_path} for attribute {name}: {e}"
                ) from e

        raise AttributeError(
            f"'{type(self).__name__}' object has no attribute '{name}'"
        )

    def __dir__(self):
        default_attrs = list(super().__dir__())
        lazy_attrs = list(self._sub_sdk_map.keys())
        return sorted(list(set(default_attrs + lazy_attrs)))

    def __enter__(self):
        return self

    async def __aenter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if (
            self.sdk_configuration.client is not None
            and not self.sdk_configuration.client_supplied
        ):
            self.sdk_configuration.client.close()
        self.sdk_configuration.client = None

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        if (
            self.sdk_configuration.async_client is not None
            and not self.sdk_configuration.async_client_supplied
        ):
            await self.sdk_configuration.async_client.aclose()
        self.sdk_configuration.async_client = None
