from typing import Any

from pghistory.models import Event, Events

from django.conf import settings
from django.db import models
from django.db.models import (
    DO_NOTHING,
    ForeignKey,
)
from django.utils.functional import cached_property
from console_base.choices import CSS
from ..choices import CRUD
from ..constants import OPERATION_KEY
from ..querysets import (
    ConsoleEventQuerySet,
    ConcordEventsQuerySet,
)


# ---------------------------------------------------------------------------
class ConcordEvent(Event):
    """
    Custom event for Console history tracking.
    Subclassed to add any project-wide custom functionality that might be useful.
    """

    pgh_id = models.BigAutoField(primary_key=True)  # type: ignore

    objects = ConsoleEventQuerySet.as_manager()

    class Meta:
        abstract = True


# ---------------------------------------------------------------------------
class ConcordEvents(Events):
    """
    Extend to add User Editor & Appliance Editor
    columns for easier filtering.
    """

    user = ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=DO_NOTHING,
        null=True,
    )

    objects = ConcordEventsQuerySet.as_manager()  # type: ignore[django-manager-missing,assignment,misc]

    class Meta:
        proxy = True
        app_label = 'concordia'
        verbose_name_plural = "concord events"

    @cached_property
    def operation(self):
        """
        Get CRUD operation
        """
        if self.pgh_diff:
            return CRUD.Update

        try:
            return self.pgh_context.metadata.get(OPERATION_KEY, CRUD.Create)
        except AttributeError:
            return CRUD.Create

    @cached_property
    def wizard_action(self) -> dict[str, str]:
        """
        Various wizards are used to keep records current.
        Get name & action if any exist in the context.
        """
        try:
            metadata: dict[str, Any] = self.pgh_context or {}
        except AttributeError:
            return {}

        wizard = metadata.get(settings.WIZARD_NAME)
        if not wizard:
            return {}

        return {
            OPERATION_KEY: metadata.get(settings.WIZARD_ACTION) or '',
            'name': wizard,
        }

    def color_class(self):
        if self.operation == CRUD.Update:
            return CSS.Info
        if self.operation == CRUD.Delete:
            return CSS.Danger
        if self.operation == CRUD.Toggle:
            return CSS.Warning
        return CSS.Success


__all__ = (
    'ConcordEvent',
    'ConcordEvents',
)
