"""
Models for reverification features common to both lms and studio
"""
from datetime import datetime
import pytz

from django.core.exceptions import ValidationError
from django.db import models
from util.validate_on_save import ValidateOnSaveMixin


class MidcourseReverificationWindow(ValidateOnSaveMixin, models.Model):
    """
    Defines the start and end times for midcourse reverification for a particular course.

    There can be many MidcourseReverificationWindows per course, but they cannot have
    overlapping time ranges.  This is enforced by this class's clean() method.
    """
    # the course that this window is attached to
    course_id = models.CharField(max_length=255, db_index=True)
    start_date = models.DateTimeField(default=None, null=True, blank=True)
    end_date = models.DateTimeField(default=None, null=True, blank=True)

    def clean(self):
        """
        Gives custom validation for the MidcourseReverificationWindow model.
        Prevents overlapping windows for any particular course.
        """
        query = MidcourseReverificationWindow.objects.filter(
            course_id=self.course_id,
            end_date__gte=self.start_date,
            start_date__lte=self.end_date
        )
        if query.count() > 0:
            raise ValidationError('Reverification windows cannot overlap for a given course.')

    @classmethod
    def window_open_for_course(cls, course_id):
        """
        Returns a boolean, True if the course is currently asking for reverification, else False.
        """
        now = datetime.now(pytz.UTC)
        return cls.get_window(course_id, now) is not None

    @classmethod
    def get_window(cls, course_id, date):
        """
        Returns the window that is open for a particular course for a particular date.
        If no such window is open, or if more than one window is open, returns None.
        """
        try:
            return cls.objects.get(course_id=course_id, start_date__lte=date, end_date__gte=date)
        except cls.DoesNotExist:
            return None
