"""
The Docker Container "database" needs to run to execute this tests properly
"""
import random
import unittest
from datetime import datetime, timedelta

from app import db
from Models.UserModel import UserModel
from Models.ProjectModel import ProjectModel
from Models.GroupMatchingDeclarationModel import GroupMatchingDeclarationModel
from Matching.ConcreteMatcher import StudyGroupMatcher
from Rest.MatchesREST import MatchesREST
from Rest.Answer import MessageCodes

random.seed(1000)


def prepare_db():
    db.session.commit()
    db.drop_all()
    db.create_all()
    db.session.commit()


def create_random_user(number):
    random_users = []

    def random_date():
        start = datetime.strptime('1/1/2000 1:00 AM', '%m/%d/%Y %I:%M %p')
        end = datetime.strptime('1/1/2020 1:00 AM', '%m/%d/%Y %I:%M %p')
        delta = end - start
        int_delta = (delta.days * 24 * 60 * 60) + delta.seconds
        random_second = random.randrange(int_delta)
        return start + timedelta(seconds=random_second)

    interests = ["interest{}".format(i) for i in range(30)]
    for i in range(number):
        user = UserModel.create("user" + str(i), "password123#", "no_real_mail" + str(i) + "@mail.de")
        user.personal_information.interest_list = random.sample(interests, random.randrange(3, 20, 1))
        user.personal_information.matriculation_date = random_date()
        random_users.append(user)
    db.session.commit()
    return random_users


def setup_one():
    """
    two users
    """
    prepare_db()
    user_one = UserModel.create("user_one", "password123#", "not_a_real_mail_1@mail.de")
    user_two = UserModel.create("user_two", "password123#", "not_a_real_mail_2@mail.de")

    return {"user_one": user_one, "user_two": user_two}


def setup_two():
    """
    30 users with random interests / ages
    group matching declaration with all of them as matchable user
    """
    prepare_db()
    users = create_random_user(30)
    gmdm = GroupMatchingDeclarationModel()
    gmdm.matchable_users.extend(users)
    db.session.add(gmdm)
    db.session.commit()
    return {"users": users, "gmdm": gmdm}


class TestGroupMatching(unittest.TestCase):

    def test_group_matching_declaration_success(self):
        # SETUP
        setup = setup_one()
        user_one = setup['user_one']
        user_two = setup['user_two']

        # ACTION
        user_one_post_result = MatchesREST.post_group_matching(user_one.id, None, True)
        user_two_post_result = MatchesREST.post_group_matching(user_two.id, None, True)

        # RESULT
        # right message code
        self.assertEqual(user_two_post_result.message, MessageCodes.WORKED.value)
        self.assertEqual(user_one_post_result.message, MessageCodes.WORKED.value)
        # gmdm exists
        gmdm = GroupMatchingDeclarationModel.query.first()
        self.assertTrue(gmdm)
        # both user are in the matchable user list
        self.assertTrue(user_one in gmdm.matchable_users)
        self.assertTrue(user_two in gmdm.matchable_users)

    def test_group_matching_success(self):
        # SETUP
        setup = setup_two()
        users = setup['users']
        gmdm = setup['gmdm']
        self.assertTrue(GroupMatchingDeclarationModel.query.first())

        # ACTION
        sgm = StudyGroupMatcher.StudyGroupMatcher()
        groups = sgm.trigger_matching((4, 6))

        # RESULT
        # projects were create
        print([[user.display_name for user in group.attendees] for group in groups])
        self.assertTrue(ProjectModel.query.all())
        # all users are in a project
        for user in users:
            for group in groups:
                if user in group.attendees:
                    break
            else:
                self.assertTrue(False)
        # gmdm matchable users in empty
        self.assertFalse(gmdm.matchable_users)
