"""
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
"""

from typing import Optional, Union

from microsoft_teams.common.http import Client, ClientOptions

from ...models import ConversationResource
from ..api_client_settings import ApiClientSettings
from ..base_client import BaseClient
from .activity import ActivityParams, ConversationActivityClient
from .member import ConversationMemberClient
from .params import CreateConversationParams


class ConversationOperations:
    """Base class for conversation operations."""

    def __init__(self, client: "ConversationClient", conversation_id: str) -> None:
        self._client = client
        self._conversation_id = conversation_id


class ActivityOperations(ConversationOperations):
    """Operations for managing activities in a conversation."""

    async def create(self, activity: ActivityParams):
        return await self._client.activities_client.create(self._conversation_id, activity)

    async def update(self, activity_id: str, activity: ActivityParams):
        return await self._client.activities_client.update(self._conversation_id, activity_id, activity)

    async def reply(self, activity_id: str, activity: ActivityParams):
        return await self._client.activities_client.reply(self._conversation_id, activity_id, activity)

    async def delete(self, activity_id: str):
        await self._client.activities_client.delete(self._conversation_id, activity_id)

    async def get_members(self, activity_id: str):
        return await self._client.activities_client.get_members(self._conversation_id, activity_id)

    async def create_targeted(self, activity: ActivityParams):
        """Create a new targeted activity visible only to the specified recipient."""
        return await self._client.activities_client.create_targeted(self._conversation_id, activity)

    async def update_targeted(self, activity_id: str, activity: ActivityParams):
        """Update an existing targeted activity."""
        return await self._client.activities_client.update_targeted(self._conversation_id, activity_id, activity)

    async def delete_targeted(self, activity_id: str):
        """Delete a targeted activity."""
        await self._client.activities_client.delete_targeted(self._conversation_id, activity_id)


class MemberOperations(ConversationOperations):
    """Operations for managing members in a conversation."""

    async def get_all(self):
        return await self._client.members_client.get(self._conversation_id)

    async def get_paged(self, page_size: Optional[int] = None, continuation_token: Optional[str] = None):
        return await self._client.members_client.get_paged(self._conversation_id, page_size, continuation_token)

    async def get(self, member_id: str):
        return await self._client.members_client.get_by_id(self._conversation_id, member_id)


class ConversationClient(BaseClient):
    """Client for managing Teams conversations."""

    def __init__(
        self,
        service_url: str,
        options: Optional[Union[Client, ClientOptions]] = None,
        api_client_settings: Optional[ApiClientSettings] = None,
    ) -> None:
        """Initialize the client.

        Args:
            service_url: The Teams service URL.
            options: Either an HTTP client instance or client options. If None, a default client is created.
            api_client_settings: Optional API client settings.
        """
        super().__init__(options, api_client_settings)
        self.service_url = service_url.rstrip("/")

        self._activities_client = ConversationActivityClient(self.service_url, self.http, self._api_client_settings)
        self._members_client = ConversationMemberClient(self.service_url, self.http, self._api_client_settings)

    @property
    def http(self) -> Client:
        """Get the HTTP client instance."""
        return self._http

    @http.setter
    def http(self, value: Client) -> None:
        """Set the HTTP client instance and propagate to sub-clients."""
        self._http = value
        self._activities_client.http = value
        self._members_client.http = value

    @property
    def activities_client(self) -> ConversationActivityClient:
        """Get the activities client."""
        return self._activities_client

    @property
    def members_client(self) -> ConversationMemberClient:
        """Get the members client."""
        return self._members_client

    def activities(self, conversation_id: str) -> ActivityOperations:
        """Get activity operations for a conversation.

        Args:
            conversation_id: The ID of the conversation.

        Returns:
            An operations object for managing activities in the conversation.
        """
        return ActivityOperations(self, conversation_id)

    def members(self, conversation_id: str) -> MemberOperations:
        """Get member operations for a conversation.

        Args:
            conversation_id: The ID of the conversation.

        Returns:
            An operations object for managing members in the conversation.
        """
        return MemberOperations(self, conversation_id)

    async def create(self, params: CreateConversationParams) -> ConversationResource:
        """Create a new conversation.

        Args:
            params: Parameters for creating the conversation.

        Returns:
            The created conversation resource.
        """
        response = await self.http.post(
            f"{self.service_url}/v3/conversations",
            json=params.model_dump(by_alias=True, exclude_none=True),
        )
        return ConversationResource.model_validate(response.json())
