"""
Microsoft Teams module.

Provides flexible interfaces to Microsoft Teams messaging with support for
module-level singleton, multi-client, and context manager patterns.

Usage:
    # Module-level singleton (most common)
    >>> from fabias.integrations import teams
    >>> teams.client(
    ...     team_id="...",
    ...     channel_id="...",
    ...     auth=my_auth
    ... )
    >>>
    >>> # Send a simple message
    >>> teams.send("Pipeline completed!")
    >>>
    >>> # Send to a different channel
    >>> teams.channel("errors").send("Pipeline failed!")
    >>>
    >>> # Send an Adaptive Card
    >>> from fabias.integrations.teams import Adaptive, TextBlock
    >>> card = Adaptive(body=[TextBlock("Important!", weight="Bolder")])
    >>> teams.send(card)

    # Multi-client usage
    >>> teams_prod = teams.client(team_id="...", channel_id="...", auth=auth1)
    >>> teams_dev = teams.client(team_id="...", channel_id="...", auth=auth2)
    >>> teams_prod.send("Production message")
    >>> teams_dev.send("Dev message")
"""

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

from ..._shared.auth import AuthProvider
from ..._shared.exceptions import FabiasError
from .channel import Channel
from .client import TeamsClient

# Module-level singleton
_client: Optional[TeamsClient] = None
_configured: bool = False


def client(
    team_id: str,
    channel_id: str,
    auth: Optional[AuthProvider] = None,
    tenant_id: Optional[str] = None,
    client_id: Optional[str] = None,
    client_secret: Optional[str] = None,
) -> TeamsClient:
    """
    Create or configure the Teams client.

    When called as a module-level function, sets up the singleton for convenience.
    Returns the client instance for both module-level and explicit multi-client use.

    Args:
        team_id: Microsoft Teams team ID (GUID)
        channel_id: Default channel ID
        auth: Pre-configured AuthProvider (recommended)
        tenant_id: Azure AD tenant ID (alternative to auth)
        client_id: Application (client) ID (alternative to auth)
        client_secret: Client secret value (alternative to auth)

    Returns:
        TeamsClient: Configured client instance

    Examples:
        # Module-level singleton (most common)
        >>> import fabias.teams as teams
        >>> teams.client(
        ...     team_id="7a5233be-...",
        ...     channel_id="19:abc123@thread.tacv2",
        ...     auth=my_auth
        ... )
        >>> teams.send("Hello!")

        # Multi-client usage
        >>> teams_prod = teams.client(team_id="...", channel_id="...", auth=auth1)
        >>> teams_dev = teams.client(team_id="...", channel_id="...", auth=auth2)
        >>> teams_prod.send("Production message")

        # Context manager
        >>> with teams.client(team_id="...", channel_id="...", auth=my_auth) as client:
        ...     client.send("Hello!")
    """
    global _client, _configured

    new_client = TeamsClient(
        team_id=team_id,
        channel_id=channel_id,
        auth=auth,
        tenant_id=tenant_id,
        client_id=client_id,
        client_secret=client_secret,
    )

    # Set as module singleton
    _client = new_client
    _configured = True

    return new_client


def _get_client() -> TeamsClient:
    """Get the configured client or raise an error."""
    if _client is None:
        raise FabiasError("Teams module not configured. " "Call teams.client(...) first.")
    return _client


def reset() -> None:
    """Reset module state, clearing the cached client."""
    global _client, _configured
    _client = None
    _configured = False


# =============================================================================
# Module-level API
# =============================================================================


def send(content: Union[str, Any], subject: Optional[str] = None) -> dict:
    """
    Send a message to the default channel.

    Args:
        content: Message text or Adaptive Card
        subject: Optional message subject

    Returns:
        dict: API response with message ID

    Examples:
        >>> teams.send("Hello world!")
        >>> teams.send("Alert", subject="Important")
        >>> teams.send(my_adaptive_card)
    """
    return _get_client().send(content, subject)


def channel(channel_id: str) -> Channel:
    """
    Get a Channel object for a specific channel.

    Use this to send to channels other than the default.

    Args:
        channel_id: Channel ID

    Returns:
        Channel: Channel object for sending messages

    Examples:
        >>> teams.channel("19:errors@thread.tacv2").send("Error occurred!")
    """
    return _get_client().channel(channel_id)


def channels() -> List[Dict[str, Any]]:
    """
    List all channels in the configured team.

    Returns:
        list: List of channel metadata
    """
    return _get_client().listChannels()


# =============================================================================
# Dynamic attribute access for undefined endpoints
# =============================================================================


def __getattr__(name: str):
    """
    Fallback for undefined attributes - treats them as API endpoints.

    Allows access to Graph API endpoints that don't have explicit methods.
    """
    if name.startswith("_"):
        raise AttributeError(name)

    def dynamic_endpoint(**kwargs):
        client = _get_client()
        return client.getResource(name, **kwargs)

    return dynamic_endpoint


__all__ = [
    "client",
    "reset",
    "send",
    "channel",
    "channels",
    "TeamsClient",
    "Channel",
]
