from datetime import datetime

from apiflask import APIBlueprint
from flask import abort

from ..schemas import MessageSchema, TimeAvailabilityCreateSchema, TemporaryProjectSupervisorSchema, \
    ListOfFreeTimesSchema, ListOfTermOfDefenceSchema
from ...dependencies import db
from ..models import ProjectSupervisor
from ...examination_schedule.models import ExaminationSchedule, TemporaryAvailability, TermOfDefence

bp = APIBlueprint("enrollments", __name__, url_prefix="/")


@bp.post('/<int:examination_schedule_id>/enrollments/')
@bp.input(TimeAvailabilityCreateSchema)
@bp.output(MessageSchema)
def set_your_free_time_to_examination_schedule(examination_schedule_id: int, data: dict) -> dict:
    # this code will be removed
    project_supervisor = db.session.query(ProjectSupervisor).filter(
        ProjectSupervisor.id == data['project_supervisor_id']).first()
    if project_supervisor is None:
        abort(404, "ProjectSupervisor doesn't exist!")
    ################

    es = ExaminationSchedule.query.filter(ExaminationSchedule.id == examination_schedule_id).first()
    if es is None:
        abort(404, "Examination schedule doesn't exist!")

    sd = data['start_date']
    ed = data['end_date']
    if sd > ed:
        abort(400, "Invalid data! End date must be greater than start date!")

    print(es.start_date.timestamp() >= sd.timestamp())
    print(es.end_date.timestamp() <= ed.timestamp())
    if not (es.start_date.timestamp() <= sd.timestamp() and es.end_date.timestamp() >= ed.timestamp()):
        abort(400, "Invalid date ranges!")

    now = datetime.utcnow()
    if es.start_date_for_enrollment_students is not None and \
            es.start_date_for_enrollment_students.timestamp() < now.timestamp():
        abort(403, "Enrollment has started! You cannot set your free time!")

    ta_query = TemporaryAvailability.query.filter(
        TemporaryAvailability.examination_schedule_id == examination_schedule_id). \
        filter(TemporaryAvailability.project_supervisor_id == project_supervisor.id)
    if ta_query.first() is not None:
        # implement logic
        pass

    ta = TemporaryAvailability(**data, examination_schedule_id=examination_schedule_id)
    db.session.add(ta)
    db.session.commit()

    return {"message": "You have just assigned your free time!"}


@bp.delete('/<int:examination_schedule_id>/enrollments/<int:temporary_availability_id>/')
@bp.input(TemporaryProjectSupervisorSchema)
@bp.output(MessageSchema)
def delete_your_free_time_from_examination_schedule(examination_schedule_id: int, temporary_availability_id: int,
                                                    data: dict) -> dict:
    # this code will be removed
    project_supervisor = db.session.query(ProjectSupervisor).filter(ProjectSupervisor.id == data['id']).first()
    if project_supervisor is None:
        abort(404, "ProjectSupervisor doesn't exist!")
    ################
    ta = TemporaryAvailability.query.filter(TemporaryAvailability.examination_schedule_id == examination_schedule_id,
                                            TemporaryAvailability.project_supervisor_id == project_supervisor.id,
                                            TemporaryAvailability.id == temporary_availability_id).first()

    if ta is None:
        abort(404, "Your free time doesn't exist!")

    db.session.delete(ta)
    db.session.commit()
    return {"message": "You have just removed your free time!"}


@bp.get('/<int:examination_schedule_id>/temporary-availabilities/')
@bp.input(TemporaryProjectSupervisorSchema, location='query')
@bp.output(ListOfFreeTimesSchema)
def list_enrollments_for_project_supervisor(examination_schedule_id: int, data: dict) -> dict:
    # this code will be removed
    project_supervisor = db.session.query(ProjectSupervisor).filter(ProjectSupervisor.id == data['id']).first()
    if project_supervisor is None:
        abort(404, "ProjectSupervisor doesn't exist!")
    ################
    es = ExaminationSchedule.query.filter(ExaminationSchedule.id == examination_schedule_id,
                                          ExaminationSchedule.year_group_id).first()

    if es is None:
        abort(404, "Examination schedule doesn't exist!")

    now = datetime.utcnow()
    start_date = es.start_date_for_enrollment_students
    if start_date is not None and start_date.timestamp() < now.timestamp():
        abort(403, "Forbidden! Enrollment has just started! You cannot assign to the exam committees!")

    # list of your term of defences first enrollment
    ta = TemporaryAvailability.query.filter(TemporaryAvailability.examination_schedule_id == examination_schedule_id,
                                            TemporaryAvailability.project_supervisor_id == project_supervisor.id).all()
    return {"free_times": ta}


@bp.get('/<int:examination_schedule_id>/term-of-defences/')
@bp.input(TemporaryProjectSupervisorSchema, location='query')
@bp.output(ListOfTermOfDefenceSchema)
def list_created_term_of_defences_by_coordinator_for_project_supervisor(examination_schedule_id: int,
                                                                        data: dict) -> dict:
    # this code will be removed
    project_supervisor = db.session.query(ProjectSupervisor).filter(ProjectSupervisor.id == data['id']).first()
    if project_supervisor is None:
        abort(404, "ProjectSupervisor doesn't exist!")
    ################
    es = ExaminationSchedule.query.filter(ExaminationSchedule.id == examination_schedule_id,
                                          ExaminationSchedule.year_group_id).first()
    if es is None:
        abort(404, "Examination schedule doesn't exist!")

    # list of your free times first enrollment
    td = TermOfDefence.query.join(TermOfDefence.members_of_committee). \
        filter(TermOfDefence.examination_schedule_id == examination_schedule_id). \
        filter_by(id=project_supervisor.id).all()
    return {"term_of_defences": td}