from collective.ftw.upgrade import UpgradeStep
from ploneintranet.notifications.sql.saconfig import LoggedEvent
from ploneintranet.notifications.sql.saconfig import Notification
from ploneintranet.notifications.sql.saconfig import session

import logging

logger = logging.getLogger(__name__)


class FutureNewsAvoidSqlWriteConficts(UpgradeStep):
    """5842-future-news-avoid-sql-write-conficts."""

    def __call__(self):
        delete_future_news_unsent_notifications_and_reset_logged_events()


def delete_future_news_unsent_notifications_and_reset_logged_events():
    """Migrate from the old to the new paradigm for future news.

    Old:       process logged_event and store undispatched future notifications
    New:       keep logged_event unprocessed, no future notifications
    Migration: remove future notifications and mark logged_event as unprocessed
    """

    query = (
        session()
        .query(LoggedEvent, Notification)
        .filter(Notification.logged_event_uid == LoggedEvent.uid)
        .filter(LoggedEvent._zope_event == "newsitem_published")
        .filter(Notification.notified == None)  # noqa: E711
    )

    logged_events = {record.LoggedEvent for record in query.all()}
    notifications_uids = {record.Notification.uid for record in query.all()}

    count = (
        session()
        .query(Notification)
        .filter(Notification.uid.in_(notifications_uids))
        .delete()
    )
    logger.info("Deleted %r unsent newsitem_published notifications", count)

    count = 0
    for logged_event in logged_events:
        logged_event.processed = None
        count += 1
    logger.info(
        "Marked %r future newsitem_published logged_events as unprocessed", count
    )
