from datetime import datetime
from typing import Optional

import typer
from sqlalchemy.orm.exc import UnmappedInstanceError
from sqlmodel import Session, select

from .database import engine
from .functions_aux import Status
from .tables import ToDo, Timer

app = typer.Typer()


@app.command()
def task(id: str, task: str = None,
         status: Optional[Status] = typer.Option(None),
         tag: str = None, remarks: str = None, project: str = None,
         due_date: datetime = typer.Option(None, formats=['%Y-%m-%d']),
         reminder: datetime = typer.Option(None, formats=['%Y-%m-%d'])):
    """Edit record from to-do list"""
    with Session(engine) as session:
        try:
            query = session.get(ToDo, id)

            if task is not None:
                query.task = task
            if tag is not None:
                query.tag = tag
            if remarks is not None:
                query.remarks = remarks
            if project is not None:
                query.project = project

            if status is None or status == query.status:
                pass
            elif status == 'done':
                query.status = status
                query.date_end = datetime.now().date()
            elif status == 'doing' and query.status == 'done':
                query.status = status
                query.date_end = None
            elif status == 'to do':
                timer = session.exec(select(Timer).where(
                    Timer.id_todo == id)).all()
                if len(timer) > 0:
                    typer.secho(f'\nTask already started\n',
                                fg=typer.colors.RED)
                    raise typer.Exit(code=1)
                else:
                    query.status = status
                    query.date_end = None
            else:
                query.status = status

            today = datetime.today()
            if due_date is not None and reminder \
                    is not None and reminder >= due_date:
                typer.secho(
                    f'\nreminder must be smaller than {due_date.date()}\n',
                    fg=typer.colors.RED)
                raise typer.Exit(code=1)

            elif due_date is not None and due_date <= today:
                typer.secho(f'\ndue date must be grater than {today.date()}\n',
                            fg=typer.colors.RED)
                raise typer.Exit(code=1)

            elif reminder is not None and reminder <= today:
                typer.secho(
                    f'\nreminder must be grater than {today.date()}\n',
                    fg=typer.colors.RED)
                raise typer.Exit(code=1)

            elif due_date is not None and query.reminder \
                    is not None and due_date < query.reminder:
                typer.secho(
                    f'\ndue date must be grater than {query.reminder.date()}\n',
                    fg=typer.colors.RED)
                raise typer.Exit(code=1)

            elif reminder is not None and query.due_date \
                    is not None and reminder >= query.due_date:
                typer.secho(
                    f'\nreminder must be smaller than {query.due_date.date()}\n',
                    fg=typer.colors.RED)
                raise typer.Exit(code=1)

            elif reminder is not None:
                query.reminder = reminder
            elif due_date is not None:
                query.due_date = due_date

            session.add(query)
            edit = typer.confirm(f"""Are you sure you want to edit:
                {query}""")
            if not edit:
                typer.secho("Not editing",
                            fg=typer.colors.RED)
                raise typer.Abort()
            typer.secho("Editing it!",
                        fg=typer.colors.RED)
            session.commit()
        except AttributeError:
            typer.secho(f'\nInvalid task id\n',
                        fg=typer.colors.RED)
            raise typer.Exit(code=1)
        except UnmappedInstanceError:
            typer.secho(f'\nInvalid task id\n',
                        fg=typer.colors.RED)
            raise typer.Exit(code=1)


@app.command()
def project(project: str, new_project: str):
    """Edit project name in tasks"""
    with Session(engine) as session:
        tasks = session.exec(select(ToDo).where(
            ToDo.project == project)).all()
        if len(tasks) > 0:
            for task in tasks:
                task.project = new_project
                session.add(task)
            edit = typer.confirm(f"""Are you sure you want to edit:
            {tasks}""")
            if not edit:
                typer.secho("Not editing",
                            fg=typer.colors.RED)
                raise typer.Abort()
            typer.secho("Editing it!",
                        fg=typer.colors.RED)
            session.commit()
        else:
            typer.secho(f'\nInvalid project\n',
                        fg=typer.colors.RED)
            raise typer.Exit(code=1)


@app.command()
def del_task(id: str):
    """Delete task"""
    try:
        with Session(engine) as session:
            task = session.get(ToDo, id)
            timers = session.exec(select(Timer).where(
                Timer.id_todo == task.id)).all()
            for timer in timers:
                session.delete(timer)
            session.delete(task)
            edit = typer.confirm(f"""Are you sure you want to delete:
            {task}""")
            if not edit:
                typer.secho("Not deleting",
                            fg=typer.colors.RED)
                raise typer.Abort()
            typer.secho("Deleting it!",
                        fg=typer.colors.RED)
            session.commit()
    except UnmappedInstanceError:
        typer.secho(f'\nInvalid task id\n',
                    fg=typer.colors.RED)
        raise typer.Exit(code=1)


@app.command()
def del_project(project: str):
    """Delete all tasks from a project"""
    with Session(engine) as session:
        tasks = session.exec(select(ToDo).where(
            ToDo.project == project)).all()
        if len(tasks) > 0:
            for task in tasks:
                timers = session.exec(select(Timer).where(
                    Timer.id_todo == task.id)).all()
                for timer in timers:
                    session.delete(timer)
                session.delete(task)
                session.delete(task)
            edit = typer.confirm(f"""Are you sure you want to delete:
            {tasks}""")
            if not edit:
                typer.secho("Not deleting",
                            fg=typer.colors.RED)
                raise typer.Abort()
            typer.secho("deleting it!",
                        fg=typer.colors.RED)
            session.commit()
        else:
            typer.secho(f'\nInvalid project\n',
                        fg=typer.colors.RED)
            raise typer.Exit(code=1)


@app.command()
def timer(id: int,
          end: datetime = typer.Option('', formats=['%Y-%m-%d %H:%M:%S'])):
    """Edit record from Timer"""
    with Session(engine) as session:
        try:
            query = session.get(Timer, id)
            if end <= query.start:
                typer.secho(
                    f'\nEnd must be >= {query.start}\n',
                    fg=typer.colors.RED)
                raise typer.Exit(code=1)
            if end >= datetime.now():
                typer.secho(
                    f'\nEnd must be < {datetime.now()}'
                )
                raise typer.Exit(code=1)

            query.end = end
            session.add(query)
            edit = typer.confirm(f"""Are you sure you want to edit:
                        {query}""")
            if not edit:
                typer.secho("Not editing",
                            fg=typer.colors.RED)
                raise typer.Abort()
            typer.secho("Editing it!",
                        fg=typer.colors.RED)
            session.commit()
        except AttributeError:
            typer.secho(f'\nInvalid timer id\n',
                        fg=typer.colors.RED)


@app.command()
def del_timer(id: int):
    """Delete record from Timer"""
    with Session(engine) as session:
        try:
            query = session.get(Timer, id)
            session.delete(query)
            edit = typer.confirm(f"""Are you sure you want to delete:
            {query}""")
            if not edit:
                typer.secho("Not deleting",
                            fg=typer.colors.RED)
                raise typer.Abort()
            typer.secho("deleting it!",
                        fg=typer.colors.RED)
            session.commit()

        except AttributeError:
            typer.secho(f'\nInvalid timer id\n',
                        fg=typer.colors.RED)
typer.secho typer.Exit datetime.datetime.now typer.Abort sqlmodel.Session typer.confirm typer.Option datetime.datetime.today sqlmodel.select typer.Typer
[((265, 278), 'typer.Typer', 'typer.Typer', ([], {}), '()\n', (276, 278), False, 'import typer\n'), ((368, 386), 'typer.Option', 'typer.Option', (['None'], {}), '(None)\n', (380, 386), False, 'import typer\n'), ((486, 526), 'typer.Option', 'typer.Option', (['None'], {'formats': "['%Y-%m-%d']"}), "(None, formats=['%Y-%m-%d'])\n", (498, 526), False, 'import typer\n'), ((558, 598), 'typer.Option', 'typer.Option', (['None'], {'formats': "['%Y-%m-%d']"}), "(None, formats=['%Y-%m-%d'])\n", (570, 598), False, 'import typer\n'), ((7039, 7086), 'typer.Option', 'typer.Option', (['""""""'], {'formats': "['%Y-%m-%d %H:%M:%S']"}), "('', formats=['%Y-%m-%d %H:%M:%S'])\n", (7051, 7086), False, 'import typer\n'), ((648, 663), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (655, 663), False, 'from sqlmodel import Session, select\n'), ((4296, 4311), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (4303, 4311), False, 'from sqlmodel import Session, select\n'), ((6027, 6042), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (6034, 6042), False, 'from sqlmodel import Session, select\n'), ((7131, 7146), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (7138, 7146), False, 'from sqlmodel import Session, select\n'), ((8240, 8255), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (8247, 8255), False, 'from sqlmodel import Session, select\n'), ((1880, 1896), 'datetime.datetime.today', 'datetime.today', ([], {}), '()\n', (1894, 1896), False, 'from datetime import datetime\n'), ((3516, 3592), 'typer.confirm', 'typer.confirm', (['f"""Are you sure you want to edit:\n                {query}"""'], {}), '(f"""Are you sure you want to edit:\n                {query}""")\n', (3529, 3592), False, 'import typer\n'), ((3758, 3805), 'typer.secho', 'typer.secho', (['"""Editing it!"""'], {'fg': 'typer.colors.RED'}), "('Editing it!', fg=typer.colors.RED)\n", (3769, 3805), False, 'import typer\n'), ((4571, 4643), 'typer.confirm', 'typer.confirm', (['f"""Are you sure you want to edit:\n            {tasks}"""'], {}), '(f"""Are you sure you want to edit:\n            {tasks}""")\n', (4584, 4643), False, 'import typer\n'), ((4809, 4856), 'typer.secho', 'typer.secho', (['"""Editing it!"""'], {'fg': 'typer.colors.RED'}), "('Editing it!', fg=typer.colors.RED)\n", (4820, 4856), False, 'import typer\n'), ((4936, 4994), 'typer.secho', 'typer.secho', (['f"""\nInvalid project\n"""'], {'fg': 'typer.colors.RED'}), '(f"""\nInvalid project\n""", fg=typer.colors.RED)\n', (4947, 4994), False, 'import typer\n'), ((5035, 5053), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (5045, 5053), False, 'import typer\n'), ((5138, 5153), 'sqlmodel.Session', 'Session', (['engine'], {}), '(engine)\n', (5145, 5153), False, 'from sqlmodel import Session, select\n'), ((5434, 5507), 'typer.confirm', 'typer.confirm', (['f"""Are you sure you want to delete:\n            {task}"""'], {}), '(f"""Are you sure you want to delete:\n            {task}""")\n', (5447, 5507), False, 'import typer\n'), ((5674, 5722), 'typer.secho', 'typer.secho', (['"""Deleting it!"""'], {'fg': 'typer.colors.RED'}), "('Deleting it!', fg=typer.colors.RED)\n", (5685, 5722), False, 'import typer\n'), ((5818, 5876), 'typer.secho', 'typer.secho', (['f"""\nInvalid task id\n"""'], {'fg': 'typer.colors.RED'}), '(f"""\nInvalid task id\n""", fg=typer.colors.RED)\n', (5829, 5876), False, 'import typer\n'), ((5909, 5927), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (5919, 5927), False, 'import typer\n'), ((6490, 6564), 'typer.confirm', 'typer.confirm', (['f"""Are you sure you want to delete:\n            {tasks}"""'], {}), '(f"""Are you sure you want to delete:\n            {tasks}""")\n', (6503, 6564), False, 'import typer\n'), ((6731, 6779), 'typer.secho', 'typer.secho', (['"""deleting it!"""'], {'fg': 'typer.colors.RED'}), "('deleting it!', fg=typer.colors.RED)\n", (6742, 6779), False, 'import typer\n'), ((6859, 6917), 'typer.secho', 'typer.secho', (['f"""\nInvalid project\n"""'], {'fg': 'typer.colors.RED'}), '(f"""\nInvalid project\n""", fg=typer.colors.RED)\n', (6870, 6917), False, 'import typer\n'), ((6958, 6976), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (6968, 6976), False, 'import typer\n'), ((7679, 7768), 'typer.confirm', 'typer.confirm', (['f"""Are you sure you want to edit:\n                        {query}"""'], {}), '(\n    f"""Are you sure you want to edit:\n                        {query}""")\n', (7692, 7768), False, 'import typer\n'), ((7929, 7976), 'typer.secho', 'typer.secho', (['"""Editing it!"""'], {'fg': 'typer.colors.RED'}), "('Editing it!', fg=typer.colors.RED)\n", (7940, 7976), False, 'import typer\n'), ((8377, 8451), 'typer.confirm', 'typer.confirm', (['f"""Are you sure you want to delete:\n            {query}"""'], {}), '(f"""Are you sure you want to delete:\n            {query}""")\n', (8390, 8451), False, 'import typer\n'), ((8618, 8666), 'typer.secho', 'typer.secho', (['"""deleting it!"""'], {'fg': 'typer.colors.RED'}), "('deleting it!', fg=typer.colors.RED)\n", (8629, 8666), False, 'import typer\n'), ((2174, 2192), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (2184, 2192), False, 'import typer\n'), ((3634, 3681), 'typer.secho', 'typer.secho', (['"""Not editing"""'], {'fg': 'typer.colors.RED'}), "('Not editing', fg=typer.colors.RED)\n", (3645, 3681), False, 'import typer\n'), ((3732, 3745), 'typer.Abort', 'typer.Abort', ([], {}), '()\n', (3743, 3745), False, 'import typer\n'), ((3902, 3960), 'typer.secho', 'typer.secho', (['f"""\nInvalid task id\n"""'], {'fg': 'typer.colors.RED'}), '(f"""\nInvalid task id\n""", fg=typer.colors.RED)\n', (3913, 3960), False, 'import typer\n'), ((4001, 4019), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (4011, 4019), False, 'import typer\n'), ((4070, 4128), 'typer.secho', 'typer.secho', (['f"""\nInvalid task id\n"""'], {'fg': 'typer.colors.RED'}), '(f"""\nInvalid task id\n""", fg=typer.colors.RED)\n', (4081, 4128), False, 'import typer\n'), ((4169, 4187), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (4179, 4187), False, 'import typer\n'), ((4685, 4732), 'typer.secho', 'typer.secho', (['"""Not editing"""'], {'fg': 'typer.colors.RED'}), "('Not editing', fg=typer.colors.RED)\n", (4696, 4732), False, 'import typer\n'), ((4783, 4796), 'typer.Abort', 'typer.Abort', ([], {}), '()\n', (4794, 4796), False, 'import typer\n'), ((5549, 5597), 'typer.secho', 'typer.secho', (['"""Not deleting"""'], {'fg': 'typer.colors.RED'}), "('Not deleting', fg=typer.colors.RED)\n", (5560, 5597), False, 'import typer\n'), ((5648, 5661), 'typer.Abort', 'typer.Abort', ([], {}), '()\n', (5659, 5661), False, 'import typer\n'), ((6606, 6654), 'typer.secho', 'typer.secho', (['"""Not deleting"""'], {'fg': 'typer.colors.RED'}), "('Not deleting', fg=typer.colors.RED)\n", (6617, 6654), False, 'import typer\n'), ((6705, 6718), 'typer.Abort', 'typer.Abort', ([], {}), '()\n', (6716, 6718), False, 'import typer\n'), ((7266, 7337), 'typer.secho', 'typer.secho', (['f"""\nEnd must be >= {query.start}\n"""'], {'fg': 'typer.colors.RED'}), '(f"""\nEnd must be >= {query.start}\n""", fg=typer.colors.RED)\n', (7277, 7337), False, 'import typer\n'), ((7399, 7417), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (7409, 7417), False, 'import typer\n'), ((7440, 7454), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (7452, 7454), False, 'from datetime import datetime\n'), ((7581, 7599), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (7591, 7599), False, 'import typer\n'), ((7805, 7852), 'typer.secho', 'typer.secho', (['"""Not editing"""'], {'fg': 'typer.colors.RED'}), "('Not editing', fg=typer.colors.RED)\n", (7816, 7852), False, 'import typer\n'), ((7903, 7916), 'typer.Abort', 'typer.Abort', ([], {}), '()\n', (7914, 7916), False, 'import typer\n'), ((8073, 8132), 'typer.secho', 'typer.secho', (['f"""\nInvalid timer id\n"""'], {'fg': 'typer.colors.RED'}), '(f"""\nInvalid timer id\n""", fg=typer.colors.RED)\n', (8084, 8132), False, 'import typer\n'), ((8493, 8541), 'typer.secho', 'typer.secho', (['"""Not deleting"""'], {'fg': 'typer.colors.RED'}), "('Not deleting', fg=typer.colors.RED)\n", (8504, 8541), False, 'import typer\n'), ((8592, 8605), 'typer.Abort', 'typer.Abort', ([], {}), '()\n', (8603, 8605), False, 'import typer\n'), ((8764, 8823), 'typer.secho', 'typer.secho', (['f"""\nInvalid timer id\n"""'], {'fg': 'typer.colors.RED'}), '(f"""\nInvalid timer id\n""", fg=typer.colors.RED)\n', (8775, 8823), False, 'import typer\n'), ((2406, 2424), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (2416, 2424), False, 'import typer\n'), ((2651, 2669), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (2661, 2669), False, 'import typer\n'), ((1200, 1214), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (1212, 1214), False, 'from datetime import datetime\n'), ((2966, 2984), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (2976, 2984), False, 'import typer\n'), ((4353, 4365), 'sqlmodel.select', 'select', (['ToDo'], {}), '(ToDo)\n', (4359, 4365), False, 'from sqlmodel import Session, select\n'), ((6084, 6096), 'sqlmodel.select', 'select', (['ToDo'], {}), '(ToDo)\n', (6090, 6096), False, 'from sqlmodel import Session, select\n'), ((7524, 7538), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (7536, 7538), False, 'from datetime import datetime\n'), ((1558, 1621), 'typer.secho', 'typer.secho', (['f"""\nTask already started\n"""'], {'fg': 'typer.colors.RED'}), '(f"""\nTask already started\n""", fg=typer.colors.RED)\n', (1569, 1621), False, 'import typer\n'), ((1678, 1696), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (1688, 1696), False, 'import typer\n'), ((3283, 3301), 'typer.Exit', 'typer.Exit', ([], {'code': '(1)'}), '(code=1)\n', (3293, 3301), False, 'import typer\n'), ((5241, 5254), 'sqlmodel.select', 'select', (['Timer'], {}), '(Timer)\n', (5247, 5254), False, 'from sqlmodel import Session, select\n'), ((6244, 6257), 'sqlmodel.select', 'select', (['Timer'], {}), '(Timer)\n', (6250, 6257), False, 'from sqlmodel import Session, select\n'), ((1434, 1447), 'sqlmodel.select', 'select', (['Timer'], {}), '(Timer)\n', (1440, 1447), False, 'from sqlmodel import Session, select\n')]