import pytest
from datetime import date, time
from chronophore import controller
from chronophore.models import Entry

UNREGISTERED_ID = '000000000'


def test_signed_in_users(db_session, test_users):
    """List all signed in users. Don't list users
    who forgot to sign out on previous days."""
    sam_id = test_users['sam'].user_id

    db_session.add(
        Entry(
            uuid='781d8a2a-104b-480c-baba-98c55f11e80b',
            date=date(2016, 2, 10),
            forgot_sign_out=True,
            time_in=time(10, 25, 7),
            time_out=None,
            user_id=sam_id,
            user_type='student',
        )
    )
    db_session.commit()

    signed_in_users = [
        user for user in controller.signed_in_users(db_session, today=date(2016, 2, 17))
    ]

    assert [test_users['pippin'], test_users['merry']] == signed_in_users
    assert test_users['sam'] not in signed_in_users


def test_sign_starting(db_session, test_users):
    """Frodo, who is registered, signs in."""
    status = controller.sign(
        test_users['frodo'].user_id,
        user_type='student',
        today=date(2016, 2, 17),
        session=db_session,
    )

    assert status.valid
    assert status.in_or_out == 'in'
    assert status.user_name == 'Frodo Baggins'
    assert status.user_type == 'student'
    assert (
        db_session
        .query(Entry)
        .filter(Entry.user_id == test_users['frodo'].user_id)
        .filter(Entry.time_out.is_(None))
        .one()
    )


def test_sign_finishing(db_session, test_users):
    """Merry is done. He signs out."""
    merry_id = test_users['merry'].user_id

    status = controller.sign(merry_id, today=date(2016, 2, 17), session=db_session)

    assert status.valid
    assert status.in_or_out == 'out'
    assert status.user_name == 'Merry Brandybuck'
    assert status.user_type == 'tutor'
    assert (
        db_session
        .query(Entry)
        .filter(Entry.user_id == merry_id)
        .filter(Entry.time_out.is_(None))
        .one_or_none()
    ) is None


def test_sign_not_registered(db_session, test_users):
    """Someone tries to sign in with an unregistered
    ID. They are told to register at the front desk.
    The entry is not added to the database.
    """
    with pytest.raises(controller.UnregisteredUser):
        controller.sign(UNREGISTERED_ID, session=db_session)

    assert (
        db_session
        .query(Entry)
        .filter(Entry.user_id == UNREGISTERED_ID)
        .one_or_none()
    ) is None


def test_sign_duplicates(db_session, test_users):
    """Somehow, Sam has 2 signed in entries in the
    database. When he tries to sign in, a message is
    displayed and the duplicate entries are all signed
    out.
    """
    sam_id = test_users['sam'].user_id

    db_session.add_all([
        Entry(
            uuid='781d8a2a-104b-480c-baba-98c55f11e80b',
            date=date(2016, 2, 17),
            time_in=time(10, 25, 7),
            time_out=None,
            user_id=sam_id,
            user_type='student',
        ),
        Entry(
            uuid='621d98db-92e0-46d1-9cd5-55013777a7d9',
            date=date(2016, 2, 17),
            time_in=time(13, 55, 00),
            time_out=None,
            user_id=sam_id,
            user_type='student',
        ),
    ])
    db_session.commit()

    status = controller.sign(
        sam_id, today=date(2016, 2, 17), session=db_session
    )