# Path: core/models.py
# class Visit(models.Model):
#     VOLUNTEER = 'VOLUNTEER'
#     FIX = 'FIX'
#     BUILD = 'BUILD'
#     WORKSHOP = 'WORKSHOP'
#     VISIT = 'VISIT'
#     DONATE = 'DONATE'
#     STAFF = 'STAFF'
#     PARTS = 'PARTS'
#     BUY_BIKE = 'BUY_BIKE'
#     TOUR = 'TOUR'
# 
#     visit_choices = (
#         (VOLUNTEER, 'volunteer'),
#         (FIX, 'fix bike'),
#         (BUILD, 'build bike'),
#         (WORKSHOP, 'workshop'),
#         (VISIT, 'visit'),
#         (DONATE, 'donate'),
#         (STAFF, 'staff'),
#         (PARTS, 'parts'),
#         (BUY_BIKE, 'buy bike'),
#         (TOUR, 'tour / visit')
#     )
# 
#     member = models.ForeignKey(
#         'registration.Member',
#         on_delete=models.CASCADE
#     )
#     created_at = models.DateTimeField(default=timezone.now)
#     purpose = models.CharField(max_length=50, choices=visit_choices)
# 
#     def __str__(self):
#         return '<Visit purpose: {purpose} created_at: {created_at}>'.format(purpose=self.purpose,
#                                                                             created_at=self.created_at.isoformat())
# 
# Path: registration/models.py
# class Member(models.Model):
#     involvement_choices = (
#         ('21cd9799b6', 'General (receive email)'),
#         ('3a5a719017', 'Volunteering'),
#         ('0ebb0b5468', 'Events'),
#         ('84309225e7', 'Workshops'),
#         ('c96d389517', 'Shop'),
#     )
# 
#     user = models.OneToOneField(CustomUser, on_delete=models.CASCADE,
#                                 null=True, blank=True)
#     email = models.EmailField(
#         verbose_name='email address',
#         max_length=255,
#         unique=False,
#         null=True,
#         blank=True,
#         )
#     email_consent = models.BooleanField(default=False, blank=False)
#     first_name = models.CharField(max_length=255, null=False, blank=False)
#     last_name = models.CharField(max_length=255, null=False, blank=False)
#     preferred_name = models.CharField(max_length=255, null=True, blank=True)
#     date_of_birth = models.DateField(null=True, blank=True)
#     guardian_name = models.CharField(max_length=255, null=True, blank=True)
#     phone = models.CharField(max_length=20, null=True, blank=True)
#     street = models.CharField(max_length=255, null=True, blank=True)
#     city = models.CharField(max_length=255, null=True, blank=True)
#     province = models.CharField(max_length=255, null=True, blank=True)
#     country = models.CharField(max_length=255, null=True, blank=True)
#     post_code = models.CharField(max_length=20, null=True, blank=False)
#     waiver = models.DateTimeField(null=True, blank=True)
#     is_active = models.BooleanField(default=True)
#     notes = models.TextField(null=True, blank=True)
#     suspended = models.BooleanField(default=False)
#     banned = models.BooleanField(default=False)
#     created_at = models.DateTimeField(auto_now_add=True)
#     modified_at = models.DateTimeField(auto_now=True)
#     involvement = MultiSelectField(choices=involvement_choices, null=True, blank=True)
# 
#     @property
#     def full_name(self):
#         return self.get_full_name()
# 
#     def get_full_name(self):
#         # The user is identified by their email address
#         return '{0} {1}'.format(self.first_name, self.last_name)
# 
#     def get_short_name(self):
#         # The user is identified by their email address
#         if self.email:
#             return self.email
#         else:
#             return self.last_name
# 
#     def __str__(self):              # __unicode__ on Python 2
#         return self.email
# 
# Path: registration/utils.py
# def signin_member(member: Member, purpose: str) -> Visit:
#     """
#     Signs in a member, creating a new `Visit`
#     :param member: the member to be signed in
#     :param purpose: The reason for visit. E.g. Fix a bike or volunteer
#     :return: a new `Visit`
#     :raise: `AlreadySignedInError` or `ValidationError`
#     """
#     if not member_signed_in(member):
#         instance = Visit.objects.create(member=member, purpose=purpose)
#         form = VisitForm(instance=instance, data={'member': member, 'purpose': purpose})
#         if form.is_valid():
#             return instance
#         raise ValidationError(instance)
# 
#     raise AlreadySignedInError
# 
# class AlreadySignedInError(ValueError):
#     pass
# 
# def member_signed_in(member: Member, window: int = 4) -> bool:
#     return get_signed_in_members(window=window).filter(member_id__in=[member.id]).exists()
# 
# def get_signed_in_members(window: int = 4, end: Optional[datetime] = None) -> QuerySet:
#     new_end = end if end else timezone.now()
#     start = new_end - timedelta(hours=window)
#     visits = Visit.objects.filter(created_at__lte=new_end, created_at__gte=start)
#     return visits


from datetime import timedelta
from django.test import TestCase
from django.utils import timezone
from model_mommy import mommy
from core.models import Visit
from registration.models import Member
from registration.utils import signin_member, AlreadySignedInError, member_signed_in, get_signed_in_members




class GetSignedInMembersTests(TestCase):
    def setUp(self):
        self.now = timezone.now()

        self.member1 = mommy.make(Member)
        self.member2 = mommy.make(Member)
        self.member3 = mommy.make(Member)

        three_hours_ago = self.now - timedelta(hours=3)
        five_hours_ago = self.now - timedelta(hours=5)


# Path: core/models.py
# class Visit(models.Model):
#     VOLUNTEER = 'VOLUNTEER'
#     FIX = 'FIX'
#     BUILD = 'BUILD'
#     WORKSHOP = 'WORKSHOP'
#     VISIT = 'VISIT'
#     DONATE = 'DONATE'
#     STAFF = 'STAFF'
#     PARTS = 'PARTS'
#     BUY_BIKE = 'BUY_BIKE'
#     TOUR = 'TOUR'
# 
#     visit_choices = (
#         (VOLUNTEER, 'volunteer'),
#         (FIX, 'fix bike'),
#         (BUILD, 'build bike'),
#         (WORKSHOP, 'workshop'),
#         (VISIT, 'visit'),
#         (DONATE, 'donate'),
#         (STAFF, 'staff'),
#         (PARTS, 'parts'),
#         (BUY_BIKE, 'buy bike'),
#         (TOUR, 'tour / visit')
#     )
# 
#     member = models.ForeignKey(
#         'registration.Member',
#         on_delete=models.CASCADE
#     )
#     created_at = models.DateTimeField(default=timezone.now)
#     purpose = models.CharField(max_length=50, choices=visit_choices)
# 
#     def __str__(self):
#         return '<Visit purpose: {purpose} created_at: {created_at}>'.format(purpose=self.purpose,
#                                                                             created_at=self.created_at.isoformat())
# 
# Path: registration/models.py
# class Member(models.Model):
#     involvement_choices = (
#         ('21cd9799b6', 'General (receive email)'),
#         ('3a5a719017', 'Volunteering'),
#         ('0ebb0b5468', 'Events'),
#         ('84309225e7', 'Workshops'),
#         ('c96d389517', 'Shop'),
#     )
# 
#     user = models.OneToOneField(CustomUser, on_delete=models.CASCADE,
#                                 null=True, blank=True)
#     email = models.EmailField(
#         verbose_name='email address',
#         max_length=255,
#         unique=False,
#         null=True,
#         blank=True,
#         )
#     email_consent = models.BooleanField(default=False, blank=False)
#     first_name = models.CharField(max_length=255, null=False, blank=False)
#     last_name = models.CharField(max_length=255, null=False, blank=False)
#     preferred_name = models.CharField(max_length=255, null=True, blank=True)
#     date_of_birth = models.DateField(null=True, blank=True)
#     guardian_name = models.CharField(max_length=255, null=True, blank=True)
#     phone = models.CharField(max_length=20, null=True, blank=True)
#     street = models.CharField(max_length=255, null=True, blank=True)
#     city = models.CharField(max_length=255, null=True, blank=True)
#     province = models.CharField(max_length=255, null=True, blank=True)
#     country = models.CharField(max_length=255, null=True, blank=True)
#     post_code = models.CharField(max_length=20, null=True, blank=False)
#     waiver = models.DateTimeField(null=True, blank=True)
#     is_active = models.BooleanField(default=True)
#     notes = models.TextField(null=True, blank=True)
#     suspended = models.BooleanField(default=False)
#     banned = models.BooleanField(default=False)
#     created_at = models.DateTimeField(auto_now_add=True)
#     modified_at = models.DateTimeField(auto_now=True)
#     involvement = MultiSelectField(choices=involvement_choices, null=True, blank=True)
# 
#     @property
#     def full_name(self):
#         return self.get_full_name()
# 
#     def get_full_name(self):
#         # The user is identified by their email address
#         return '{0} {1}'.format(self.first_name, self.last_name)
# 
#     def get_short_name(self):
#         # The user is identified by their email address
#         if self.email:
#             return self.email
#         else:
#             return self.last_name
# 
#     def __str__(self):              # __unicode__ on Python 2
#         return self.email
# 
# Path: registration/utils.py
# def signin_member(member: Member, purpose: str) -> Visit:
#     """
#     Signs in a member, creating a new `Visit`
#     :param member: the member to be signed in
#     :param purpose: The reason for visit. E.g. Fix a bike or volunteer
#     :return: a new `Visit`
#     :raise: `AlreadySignedInError` or `ValidationError`
#     """
#     if not member_signed_in(member):
#         instance = Visit.objects.create(member=member, purpose=purpose)
#         form = VisitForm(instance=instance, data={'member': member, 'purpose': purpose})
#         if form.is_valid():
#             return instance
#         raise ValidationError(instance)
# 
#     raise AlreadySignedInError
# 
# class AlreadySignedInError(ValueError):
#     pass
# 
# def member_signed_in(member: Member, window: int = 4) -> bool:
#     return get_signed_in_members(window=window).filter(member_id__in=[member.id]).exists()
# 
# def get_signed_in_members(window: int = 4, end: Optional[datetime] = None) -> QuerySet:
#     new_end = end if end else timezone.now()
#     start = new_end - timedelta(hours=window)
#     visits = Visit.objects.filter(created_at__lte=new_end, created_at__gte=start)
#     return visits


# Path: registration/tests/test_utils.py
from datetime import timedelta
from django.test import TestCase
from django.utils import timezone
from model_mommy import mommy
from core.models import Visit
from registration.models import Member
from registration.utils import signin_member, AlreadySignedInError, member_signed_in, get_signed_in_members





class GetSignedInMembersTests(TestCase):
    def setUp(self):
        self.now = timezone.now()

        self.member1 = mommy.make(Member)
        self.member2 = mommy.make(Member)
        self.member3 = mommy.make(Member)

        three_hours_ago = self.now - timedelta(hours=3)
        five_hours_ago = self.now - timedelta(hours=5)


        self.visit1 = Visit.objects.create(member=self.member1, purpose=Visit.DONATE, created_at=self.now)