from plone import api
from zope.interface.interfaces import ComponentLookupError

import logging
import pika
import transaction

logger = logging.getLogger(__name__)
logging.getLogger("pika").setLevel(logging.WARNING)


def _send_hook(status, recipients, message):
    if not status:
        return
    try:
        exchange = api.portal.get_registry_record(
            "ploneintranet.layout.push_exchange", default=""
        )
        writer_host = api.portal.get_registry_record(
            "ploneintranet.layout.push_server_writer_host", default=""
        )
        username = api.portal.get_registry_record(
            "ploneintranet.layout.push_server_writer_login", default=""
        )
        password = api.portal.get_registry_record(
            "ploneintranet.layout.push_server_writer_password", default=""
        )
    except Exception:
        logger.error("Failed to get the records from the registry")
        return

    if not exchange or not writer_host:
        return

    host, port = writer_host.partition(":")[::2]
    credentials = pika.PlainCredentials(username=username, password=password)
    params = pika.ConnectionParameters(host=host, port=port, credentials=credentials)
    try:
        connection = pika.BlockingConnection(params)
        channel = connection.channel()
        for recipient in recipients:
            channel.basic_publish(
                exchange=exchange, routing_key=recipient, body=message
            )
        connection.close()
    except Exception:
        logger.exception("Something wrong happened when sending message to the queue")


def _send(
    recipients: str | list[str],
    message: str,
) -> None:
    """helper method used to send messages to the queue server using pika
    This is typically used like this:

    from ploneintranet import api as pi_api
    pi_api.push._send(recipients, message)

    """
    if not recipients:
        return
    try:
        exchange = api.portal.get_registry_record(
            "ploneintranet.layout.push_exchange", default=""
        )
    except ComponentLookupError:
        # This happens when no registry is setup
        return

    if not exchange:
        return

    if isinstance(recipients, str):
        recipients = [recipients]

    current_transaction = transaction.get()
    current_transaction.addAfterCommitHook(
        _send_hook, kws={"recipients": recipients, "message": message}
    )


def incoming_message_for(
    recipients: str | list[str],
) -> None:
    """Notify the recipients that a new message arrived"""
    _send(recipients, "incoming_message")


def notification_counter_changed_for(
    recipients: str | list[str],
) -> None:
    """Notify the notification counter has changed"""
    _send(recipients, "notification_counter_changed")


def browser_new_notification_for(
    recipients: str | list[str],
) -> None:
    """Notify the browser that a new notification has arrived"""
    _send(recipients, "browser_new_notification")


def browser_incoming_message_for(
    recipients: str | list[str],
) -> None:
    """Notify the browser that a new message arrived"""
    _send(recipients, "browser_incoming_message")
