import logging
import aio_pika

from uuid import uuid4

from cattle_grid.dependencies.fastapi import Broker
from cattle_grid.model.account import EventType

logger = logging.getLogger(__name__)


async def queue_for_connection(connection, username: str, event_type: EventType):
    channel = await connection.channel()
    await channel.set_qos(prefetch_count=1)

    exchange = await channel.declare_exchange(
        "amq.topic", aio_pika.ExchangeType.TOPIC, durable=True
    )

    queue = await channel.declare_queue(
        f"queue-{username}-{uuid4()}",
        durable=False,
    )
    await queue.bind(exchange, routing_key=f"receive.{username}.{event_type.value}")

    return queue


def get_message_streamer(broker: Broker):
    if broker._connection is None:
        raise RuntimeError("Broker not connected")

    connection: aio_pika.RobustConnection = broker._connection

    async def stream_messages(username: str, event_type: EventType):
        try:
            async with connection:
                queue = await queue_for_connection(connection, username, event_type)

                async with queue.iterator() as iterator:
                    try:
                        async for message in iterator:
                            async with message.process():
                                message_body = message.body.decode()
                                yield message_body
                    except Exception as e:
                        logger.exception(e)
        except Exception as e:
            logger.exception(e)

    return stream_messages
