from typing import Any, TYPE_CHECKING, Union

from django.apps import apps
from django.utils import timezone

from concordia.events.trail import ConcordEventsTrail
from console_deps.datetime_truncate import truncate_day
from console_base.models import BaseIntegerPKModel, BaseUUIDPKModel
from console_base.views import LCDetailViewBase

if TYPE_CHECKING:
    ActivityStreamBase = LCDetailViewBase
else:
    ActivityStreamBase = object


# ----------------------------------------------------------------------
class ActivityStreamViewerMixin(ActivityStreamBase):
    def update_last_viewed(self) -> None:
        self.request.user.last_viewed_events = timezone.now()
        self.request.user.save(update_fields=['last_viewed_events'])

    def get_context_data(self, **kwargs: dict[Any, Any]) -> dict[Any, Any]:
        user = self.request.user
        events = ConcordEventsTrail(user.last_viewed_events)
        if not events.unviewed_events_exist():
            # use truncate_date to retain the timezone
            events.date = truncate_day(timezone.localtime())

        self.update_last_viewed()

        return super().get_context_data(
            events_since=events.date,
            event_stream=events.unviewed_events(),
            **kwargs,
        )


# ----------------------------------------------------------------------
class ActivityStreamRecordViewerMixin(ActivityStreamBase):
    """
    Get activity stream for entire life cycle of this record
    """

    def get_record(self) -> Union['BaseIntegerPKModel', 'BaseUUIDPKModel']:
        Model = apps.get_model(app_label=self.kwargs['app'], model_name=self.kwargs['model'])
        self.object = Model.objects.filter(cid=self.kwargs['cid']).first()  # noqa
        return self.object

    def get_context_data(self, **kwargs: dict[Any, Any]) -> dict[Any, Any]:
        if record := self.get_record():
            events_since = record.created
            record_css_icon = record.css_icon
            events = ConcordEventsTrail(record.created).record_events(target=record)
        else:
            events_since = timezone.localtime()
            record_css_icon = ''
            events = []

        return super().get_context_data(
            record_model_name=record.__class__.__name__,
            record_css_icon=record_css_icon,
            events_since=events_since,
            event_stream=events,
            **kwargs,
        )


# ----------------------------------------------------------------------
class ActivityStreamModelViewerMixin(ActivityStreamBase):
    """
    Get activity stream for this model.
    """

    def get_event_model(self) -> type['BaseIntegerPKModel'] | type['BaseUUIDPKModel']:
        return apps.get_model(app_label=self.kwargs['app'], model_name=self.kwargs['model'])

    def get_context_data(self, **kwargs: dict[Any, Any]) -> dict[Any, Any]:
        record_model = self.get_event_model()()
        events = ConcordEventsTrail().model_events(
            event_model=record_model.pgh_event_model,
            operations=self.kwargs['operations'].split(','),
        )

        return super().get_context_data(
            record_model_name=record_model.__class__.__name__,
            record_css_icon=record_model.css_icon,
            event_stream=events,
            **kwargs,
        )
