import logging
import uuid

from django.contrib.auth.models import User
from django.db import models
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext_lazy, pgettext_lazy
from django_celery_beat.models import PeriodicTask
from rest_framework.authtoken.models import Token
from sequences import get_next_value
from solo.models import SingletonModel

from console.models import SensorConnectedMixin, UniqueNameDescriptionModel
from core.fields import IntegerField

_log = logging.getLogger(__name__)


class IncidentCategory(UniqueNameDescriptionModel):
    """ Category of incident """
    pass


class IncidentEffect(UniqueNameDescriptionModel):
    """ Possible incident effect """
    pass

    class Meta:
        verbose_name = gettext_lazy('Incident effect')


class IncidentRecommendations(UniqueNameDescriptionModel):
    """ Recommendations how to close incident """
    pass

    class Meta:
        verbose_name = gettext_lazy('Incident recommendation')


class Incident(SensorConnectedMixin):
    """ Incident model """

    IMPORTANCE_MIN = 0
    IMPORTANCE_MAX = 100

    class Status(models.IntegerChoices):
        NOT_ASSIGNED = 0, gettext_lazy('Not assigned')
        ASSIGNED = 1, gettext_lazy('Assigned')
        DELAYED = 2, gettext_lazy('Delayed')
        RESOLVED = 3, gettext_lazy('Resolved')
        FALSE_ALARM = 4, gettext_lazy('False alarm')

    user_friendly_id = IntegerField(blank=True, null=True)
    timestamp = models.DateTimeField(default=timezone.now,
                                     verbose_name=gettext_lazy('Timestamp'),
                                     help_text=gettext_lazy('Date and time, when incident occurs'))
    incident_id = models.UUIDField(primary_key=True,
                                   default=uuid.uuid4,
                                   verbose_name=gettext_lazy('ID'),
                                   help_text=gettext_lazy('ID of incident'))
    title = models.CharField(max_length=128,
                             verbose_name=gettext_lazy('Title'),
                             help_text=gettext_lazy('Title'))
    category = models.ForeignKey(IncidentCategory,
                                 on_delete=models.SET_NULL,
                                 verbose_name=gettext_lazy('Category'),
                                 help_text=gettext_lazy("Incident's category"),
                                 null=True,
                                 blank=True)
    importance = IntegerField(min_value=IMPORTANCE_MIN,
                              max_value=IMPORTANCE_MAX,
                              verbose_name=gettext_lazy('Importance'),
                              help_text=gettext_lazy('Hazard level of incident'))
    status = IntegerField(choices=Status.choices,
                          verbose_name=gettext_lazy('Status'),
                          help_text=gettext_lazy('Incident status'),
                          default=Status.NOT_ASSIGNED)
    assigned_to = models.ForeignKey(User,
                                    on_delete=models.SET_NULL,
                                    verbose_name=gettext_lazy('Assigned'),
                                    help_text=gettext_lazy('User assigned to resolve incident'),
                                    null=True,
                                    blank=True)
    event_count = IntegerField(min_value=1,
                               verbose_name=gettext_lazy("Event's number"),
                               help_text=gettext_lazy("Amount of events in the incident"))
    created = models.DateTimeField(auto_now_add=True,
                                   verbose_name=gettext_lazy('Created'),
                                   help_text=gettext_lazy('Date and time, when incident was created'))
    updated = models.DateTimeField(auto_now=True,
                                   verbose_name=gettext_lazy('Updated'),
                                   help_text=gettext_lazy('Date and time, when incident was updated'))
    description = models.TextField(verbose_name=gettext_lazy('Description'),
                                   help_text=gettext_lazy('Incident description'),
                                   null=True,
                                   blank=True)
    deadline = models.DateField(verbose_name=gettext_lazy('Deadline'),
                                help_text=gettext_lazy("Deadline when incident must be resolved"),
                                null=True,
                                blank=True)
    comment = models.TextField(verbose_name=gettext_lazy('Comment'),
                               help_text=gettext_lazy('Incident comment'),
                               null=True,
                               blank=True)
    close_recommendations = models.ManyToManyField(IncidentRecommendations,
                                                   verbose_name=gettext_lazy('Resolve recommendations'),
                                                   help_text=gettext_lazy('How to resolve the incident'),
                                                   blank=True)
    effects = models.ManyToManyField(IncidentEffect,
                                     verbose_name=pgettext_lazy('as consequences', 'Effects'),
                                     help_text=gettext_lazy('Consequences of the incident'),
                                     blank=True)
    events = models.JSONField(verbose_name=gettext_lazy("Events"),
                              help_text=gettext_lazy("List of events, related to incident"))

    def save(self, *args, **kwargs):
        if self._state.adding:
            self.user_friendly_id = get_next_value('incidents_user_friendly_id')
        else:
            self.user_friendly_id = self.user_friendly_id
        if self.assigned_to is not None and self.status < self.Status.ASSIGNED:
            self.status = self.Status.ASSIGNED
        if self.assigned_to is None and self.status <= self.Status.ASSIGNED:
            self.status = self.Status.NOT_ASSIGNED
        super(Incident, self).save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('incident_view', kwargs={'incident_id': self.incident_id})

    class Meta:
        ordering = ['-timestamp']
