from aio_pika import DeliveryMode, ExchangeType, Message, connect

from architectonics.rabbit_mq.config.rabbit_mq_settings import BaseRabbitMQSettings
from architectonics.rabbit_mq.producer.exceptions import RabbitMQException


class BaseRabbitMQProducer:
    _settings: BaseRabbitMQSettings = BaseRabbitMQSettings()

    _exchange_name: str = NotImplemented
    _exchange_type: ExchangeType = NotImplemented
    _routing_key: str = ""

    async def connect(self):
        self.connection = await connect(
            host=self._settings.RABBITMQ_HOST,
            port=self._settings.RABBITMQ_PORT,
            login=self._settings.RABBITMQ_USER,
            password=self._settings.RABBITMQ_PASSWORD,
            virtualhost=self._settings.RABBITMQ_VHOST,
        )

        self.channel = await self.connection.channel()

        self.exchange = await self.channel.declare_exchange(
            name=self._exchange_name,
            type=self._exchange_type,
            durable=True,
        )

    async def publish(self, message: str):

        if self.connection is None:
            raise RabbitMQException("connection_not_created")

        if self.channel is None:
            raise RabbitMQException("channel_not_created")

        message_for_rabbit = Message(
            body=message.encode(),
            delivery_mode=DeliveryMode.PERSISTENT,
        )

        await self.exchange.publish(
            message=message_for_rabbit,
            routing_key=self._routing_key,
        )

    async def disconnect(self):
        await self.channel.close()
        await self.connection.close()
