import threading
from datetime import datetime, timedelta
from sqlalchemy import DateTime, cast, func
from flask_mail import Message
from flask import current_app
from app import db, mail
from app.models import User
from .lock import Lock
from .reservation import ReservationController
from .record import RecordController
from ..exceptions import ActiveReservationExistsError, \
    ActiveRecordExistsError, NoActiveRecordError, ReservationExpiredError, \
    NoFreeSpotError


class UserController():

    @classmethod
    def create(cls, name, email, telegram_id=None, telegram_chat_id=None, password=None):
        user = User()
        user.name = name
        user.email = email
        user.telegram_id = telegram_id
        user.telegram_chat_id = telegram_chat_id
        user.generate_new_token()

        if password is not None:
            user.set_password(password)

        db.session.add(user)
        db.session.commit()

        cls.send_confirm_email(user)


    @staticmethod
    def get(user_id):
        return User.query.get(user_id)


    @staticmethod
    def reserve(user):
        if ReservationController.has_active_reservation(user):
            raise ActiveReservationExistsError
        if RecordController.has_active_record(user):
            raise ActiveRecordExistsError

        return ReservationController.create(user)


    @staticmethod
    def start_record(user):
        if RecordController.has_active_record(user):
            raise ActiveRecordExistsError
        reservation = ReservationController.get_active_reservation(user)

        if reservation is not None:
            RecordController.create_from_reservation(reservation)
        else:
            RecordController.create(user)


    @staticmethod
    def terminate_record(user):
        record = RecordController.get_active_record(user)

        if record is None:
            raise NoActiveRecordError

        RecordController.terminate(record)


    @staticmethod
    def send_password_reset_email(user):
        user.generate_new_token()
        sesssion.commit()
        msg = Message(render_template('email.password_reset', user=user),
                  recipients=[user.email])
        mail.send(msg)


    @staticmethod
    def _send_confirm_email(user):
        msg = Message(render_template('email.confirm', user=user),
                  recipients=[user.email])
        mail.send(msg)