from typer.testing import CliRunner

import os

from timerdo.main import app, sqlite_file_name
from timerdo.tables import ToDo, Timer
from sqlmodel import create_engine, Session, select
from datetime import datetime, timedelta

try:
    os.rename('/home/cmts/.config/timerdo/timerdo_db.db',
              '/home/cmts/.config/timerdo/timerdo_db_moved.db')
except FileNotFoundError:
    pass


sqlite_url = f'sqlite:///{sqlite_file_name}'

engine = create_engine(sqlite_url, echo=True)

runner = CliRunner()


def test_add_none():
    """Test add function with no argument"""
    result = runner.invoke(app, ['add'])

    assert result.exit_code == 2


def test_add_task():
    """Test add function with task argument"""
    task = 'test add'
    result = runner.invoke(app, ['add', task])
    with Session(engine) as session:
        query = session.exec(select(ToDo).where(ToDo.task == task)).one()
        task = query.task
        status = query.status

    assert result.exit_code == 0
    assert task == task
    assert status == 'to do'


def test_add_status():
    """Test status"""
    task = 'Test status'
    status = 'dif'
    result = runner.invoke(app, ['add', task, '--status', status])

    assert result.exit_code == 1
    assert 'status must be "to do" or "doing"\n' in result.stdout


def test_add_due_date():
    """Test due date"""
    task = 'Test due date'
    date = datetime.strftime(datetime.now(), '%Y-%m-%d')
    result = runner.invoke(app, ['add', task, '--due-date', date])

    assert result.exit_code == 1
    assert f'due date must be grater than {datetime.today().date()}\n' in \
           result.stdout


def test_add_reminder():
    """Test reminder"""
    task = 'Test reminder'
    date = datetime.strftime(datetime.now(), '%Y-%m-%d')
    result = runner.invoke(app, ['add', task, '--reminder', date])

    assert result.exit_code == 1
    assert f'reminder must be grater than {datetime.today().date()}\n' in \
           result.stdout


def test_add_due_date_reminder():
    """Test due-date and reminder"""
    task = 'Test due-date and reminder'
    due_date = datetime.strftime(
        datetime.now() + timedelta(days=2), '%Y-%m-%d')
    reminder = datetime.strftime(
        datetime.now() + timedelta(days=2), '%Y-%m-%d')
    result = runner.invoke(app, ['add', task, '--reminder', reminder,
                                 '--due-date', due_date])

    assert result.exit_code == 1
    assert f'reminder must be smaller than {due_date}\n' in \
           result.stdout


def test_add_full_entry():
    """Test add full task"""
    task = 'something'
    project = 'test project'
    due_date = datetime.strftime(
        datetime.now() + timedelta(days=2), '%Y-%m-%d')
    reminder = datetime.strftime(
        datetime.now() + timedelta(days=1), '%Y-%m-%d')
    status = 'doing'
    tag = 'tag'

    result = runner.invoke(app, ['add', task,
                                 '--project', project,
                                 '--due-date', due_date,
                                 '--reminder', reminder,
                                 '--status', status,
                                 '--tag', tag])

    assert result.exit_code == 0

    with Session(engine) as session:
        query = session.exec(select(ToDo).where(ToDo.task == task,
                                                ToDo.project == project,
                                                ToDo.status == status,
                                                ToDo.tag == tag)).one()
        assert query is not None


def test_start():
    """Test start"""
    todo_id = '1'
    result = runner.invoke(app, ['start', todo_id])

    assert result.exit_code == 0

    with Session(engine) as session:
        query = session.exec(select(ToDo.status).where(ToDo.id ==
                                                       todo_id)).one()

        assert query == 'doing'


def test_start_running():
    """Test start when running"""
    todo_id = '1'
    result = runner.invoke(app, ['start', todo_id])

    assert result.exit_code == 1
    assert 'The Timer must be stopped first' in result.stdout


def test_stop():
    """Test stop"""
    result = runner.invoke(app, ['stop'])

    assert result.exit_code == 0


def test_stop_no_run():
    """Test stop with no run"""
    result = runner.invoke(app, ['stop'])

    assert result.exit_code == 1


def test_duration():
    """test duration"""
    todo_id = 1
    with Session(engine) as session:
        todo = session.exec(select(ToDo.duration).where(ToDo.id ==
                                                        todo_id)).one()
        timer = session.exec(select(Timer.duration).where(Timer.id_todo
                                                          == todo_id)).one()

        assert todo is not None and todo == timer


def test_return_db():
    try:
        os.remove('/home/cmts/.config/timerdo/timerdo_db.db')
        os.rename('/home/cmts/.config/timerdo/timerdo_db_moved.db',
                  '/home/cmts/.config/timerdo/timerdo_db.db')
    except FileNotFoundError:
        pass
typer.testing.CliRunner datetime.datetime.now os.remove sqlmodel.Session datetime.timedelta os.rename datetime.datetime.today sqlmodel.select sqlmodel.create_engine
[((447, 483), 'sqlmodel.create_engine', 'create_engine', (['sqlite_url'], {'echo': '(True)'}), '(sqlite_url, echo=True)\n', (460, 483), False, 'from sqlmodel import create_engine, Session, select\n'), ((494, 505), 'typer.testing.CliRunner', 'CliRunner', ([], {}), '()\n', (503, 505), False, 'from typer.testing import CliRunner\n'), ((237, 344), 'os.rename', 'os.rename', (['"""/home/cmts/.config/timerdo/timerdo_db.db"""', '"""/home/cmts/.config/timerdo/timerdo_db_moved.db"""'], {}), "('/home/cmts/.config/timerdo/timerdo_db.db',\n    '/home/cmts/.config/timerdo/timerdo_db_moved.db')\n", (246, 344), False, 'import os\n'), ((797, 812), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (804, 812), False, 'from sqlmodel import create_engine, Session, select\n'), ((1407, 1421), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (1419, 1421), False, 'from datetime import datetime, timedelta\n'), ((1744, 1758), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (1756, 1758), False, 'from datetime import datetime, timedelta\n'), ((3204, 3219), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (3211, 3219), False, 'from sqlmodel import create_engine, Session, select\n'), ((3703, 3718), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (3710, 3718), False, 'from sqlmodel import create_engine, Session, select\n'), ((4450, 4465), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (4457, 4465), False, 'from sqlmodel import create_engine, Session, select\n'), ((4858, 4911), 'os.remove', 'os.remove', (['"""/home/cmts/.config/timerdo/timerdo_db.db"""'], {}), "('/home/cmts/.config/timerdo/timerdo_db.db')\n", (4867, 4911), False, 'import os\n'), ((4920, 5027), 'os.rename', 'os.rename', (['"""/home/cmts/.config/timerdo/timerdo_db_moved.db"""', '"""/home/cmts/.config/timerdo/timerdo_db.db"""'], {}), "('/home/cmts/.config/timerdo/timerdo_db_moved.db',\n    '/home/cmts/.config/timerdo/timerdo_db.db')\n", (4929, 5027), False, 'import os\n'), ((2129, 2143), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (2141, 2143), False, 'from datetime import datetime, timedelta\n'), ((2146, 2163), 'datetime.timedelta', 'timedelta', ([], {'days': '(2)'}), '(days=2)\n', (2155, 2163), False, 'from datetime import datetime, timedelta\n'), ((2219, 2233), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (2231, 2233), False, 'from datetime import datetime, timedelta\n'), ((2236, 2253), 'datetime.timedelta', 'timedelta', ([], {'days': '(2)'}), '(days=2)\n', (2245, 2253), False, 'from datetime import datetime, timedelta\n'), ((2668, 2682), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (2680, 2682), False, 'from datetime import datetime, timedelta\n'), ((2685, 2702), 'datetime.timedelta', 'timedelta', ([], {'days': '(2)'}), '(days=2)\n', (2694, 2702), False, 'from datetime import datetime, timedelta\n'), ((2758, 2772), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (2770, 2772), False, 'from datetime import datetime, timedelta\n'), ((2775, 2792), 'datetime.timedelta', 'timedelta', ([], {'days': '(1)'}), '(days=1)\n', (2784, 2792), False, 'from datetime import datetime, timedelta\n'), ((1579, 1595), 'datetime.datetime.today', 'datetime.today', ([], {}), '()\n', (1593, 1595), False, 'from datetime import datetime, timedelta\n'), ((1916, 1932), 'datetime.datetime.today', 'datetime.today', ([], {}), '()\n', (1930, 1932), False, 'from datetime import datetime, timedelta\n'), ((854, 866), 'sqlmodel.select', 'select', (['ToDo'], {}), '(ToDo)\n', (860, 866), False, 'from sqlmodel import create_engine, Session, select\n'), ((3261, 3273), 'sqlmodel.select', 'select', (['ToDo'], {}), '(ToDo)\n', (3267, 3273), False, 'from sqlmodel import create_engine, Session, select\n'), ((3760, 3779), 'sqlmodel.select', 'select', (['ToDo.status'], {}), '(ToDo.status)\n', (3766, 3779), False, 'from sqlmodel import create_engine, Session, select\n'), ((4506, 4527), 'sqlmodel.select', 'select', (['ToDo.duration'], {}), '(ToDo.duration)\n', (4512, 4527), False, 'from sqlmodel import create_engine, Session, select\n'), ((4646, 4668), 'sqlmodel.select', 'select', (['Timer.duration'], {}), '(Timer.duration)\n', (4652, 4668), False, 'from sqlmodel import create_engine, Session, select\n')]