"""
RabbitMQ publisher for GlobalAuth commands.
"""
from uuid import UUID
from typing import Literal
from pydantic import BaseModel, field_validator

from faststream.rabbit import RabbitBroker

from opengater_globalauth_client.broker.events import CreateUserCommand


class GlobalAuthPublisher:
    """
    Publisher for sending commands to GlobalAuth via RabbitMQ.
    
    Uses existing RabbitBroker instance from your application.
    
    Args:
        broker: RabbitBroker instance
    
    Example:
        ```python
        from faststream.rabbit import RabbitBroker
        from opengater_globalauth_client.broker import GlobalAuthPublisher
        
        broker = RabbitBroker(settings.rabbitmq_url)
        publisher = GlobalAuthPublisher(broker)
        
        # Create user from Telegram bot
        await publisher.create_user(
            auth_type="telegram",
            identifier="123456789",
            extra_data={"username": "john", "first_name": "John"},
            invited_by_id="uuid-of-inviter"
        )
        ```
    """

    COMMANDS_QUEUE = "globalauth.commands"

    def __init__(self, broker: RabbitBroker, service_slug: str):
        self.broker = broker
        self.service_slug = service_slug

    async def _publish(self, message: BaseModel) -> None:
        """Publish message to commands queue"""
        await self.broker.publish(
            message.model_dump(mode="json"),
            queue=self.COMMANDS_QUEUE,
            persist=True,
        )

    async def create_user(
            self,
            command: CreateUserCommand
    ) -> None:
        """
        Send create_user command to GlobalAuth.
        
        GlobalAuth will create the user and publish user_created event.
        
        Args:
            auth_type: Authentication type ("telegram")
            identifier: User identifier (e.g., telegram_id)
            language: User language code (default: "ru")
            extra_data: Additional data (username, first_name, etc.)
            invited_by_id: UUID of inviter (referral)
            event_id: Event/campaign ID
            event_service: Service slug for event
        
        Note:
            invited_by_id and (event_id + event_service) are mutually exclusive.
            You can specify either a referrer OR an event, not both.
        
        Example:
            ```python
            # Referral registration
            await publisher.create_user(
                auth_type="telegram",
                identifier="123456789",
                language="en",
                invited_by_id="uuid-of-inviter"
            )
            
            # Event/campaign registration
            await publisher.create_user(
                auth_type="telegram", 
                identifier="123456789",
                event_id="black_friday_2025",
                event_service="opengater"
            )
            ```
        """
        if not command.event_service:
            command.event_service = self.service_slug

        await self._publish(command)

    async def send_command(self, command: str, **kwargs) -> None:
        """
        Send generic command to GlobalAuth.
        
        Use this for custom commands or future API extensions.
        
        Args:
            command: Command name
            **kwargs: Command parameters
        """
        message = {"command": command, **kwargs}

        await self.broker.publish(
            message,
            queue=self.COMMANDS_QUEUE,
            persist=True,
        )
