from __future__ import unicode_literals, division, absolute_import
from builtins import *  # noqa

import datetime
from datetime import timedelta

from colorclass.toggles import disable_all_colors
from flexget import options
from flexget.event import event
from flexget.manager import Session
from flexget.plugins.operate.status import StatusTask, TaskExecution
from flexget.terminal import TerminalTable, TerminalTableError, table_parser, colorize, console
from sqlalchemy import desc
from sqlalchemy.orm.exc import NoResultFound


def do_cli(manager, options):
    if options.table_type == 'porcelain':
        disable_all_colors()
    if options.task:
        do_cli_task(manager, options)
    else:
        do_cli_summary(manager, options)


def do_cli_task(manager, options):
    header = ['Start', 'Duration', 'Produced', 'Accepted', 'Rejected', 'Failed', 'Abort Reason']
    table_data = [header]
    with Session() as session:
        try:
            task = session.query(StatusTask).filter(StatusTask.name == options.task).one()
        except NoResultFound:
            console('Task name `%s` does not exists or does not have any records' % options.task)
            return
        else:
            query = task.executions.order_by(desc(TaskExecution.start))[:options.limit]
            for ex in reversed(query):
                start = ex.start.strftime('%Y-%m-%d %H:%M')
                start = colorize('green', start) if ex.succeeded else colorize('red', start)

                if ex.end is not None and ex.start is not None:
                    delta = ex.end - ex.start
                    duration = '%1.fs' % delta.total_seconds()
                else:
                    duration = '?'

                table_data.append(
                    [
                        start,
                        duration,
                        ex.produced,
                        ex.accepted,
                        ex.rejected,
                        ex.failed,
                        ex.abort_reason if ex.abort_reason is not None else ''
                    ]
                )

    try:
        table = TerminalTable(options.table_type, table_data)
        console(table.output)
    except TerminalTableError as e:
        console('ERROR: %s' % str(e))


def do_cli_summary(manager, options):
    header = ['Task', 'Last execution', 'Last success', 'Produced', 'Accepted', 'Rejected', 'Failed', 'Duration']
    table_data = [header]

    with Session() as session:
        for task in session.query(StatusTask).all():
            ok = session.query(TaskExecution). \
                filter(TaskExecution.task_id == task.id). \
                filter(TaskExecution.succeeded == True). \
                filter(TaskExecution.produced > 0). \
                order_by(TaskExecution.start.desc()).first()

            if ok is None:
                duration = None
                last_success = '-'
            else:
                duration = ok.end - ok.start
                last_success = ok.start.strftime('%Y-%m-%d %H:%M')

                age = datetime.datetime.utcnow() - ok.start
                if age > timedelta(days=7):
                    last_success = colorize('red', last_success)
                elif age < timedelta(minutes=10):
                    last_success = colorize('green', last_success)

            table_data.append([
                task.name,
                task.last_execution_time.strftime('%Y-%m-%d %H:%M'),
                last_success,
                ok.produced if ok is not None else '-',
                ok.accepted if ok is not None else '-',
                ok.rejected if ok is not None else '-',
                ok.failed if ok is not None else '-',
                '%1.fs' % duration.total_seconds() if duration is not None else '-',
            ]
            )

    table = TerminalTable(options.table_type, table_data)
    try:
        console(table.output)
    except TerminalTableError as e:
        console('ERROR: %s' % str(e))


@event('options.register')
def register_parser_arguments():
    parser = options.register_command('status', do_cli, help='View task health status', parents=[table_parser])
    parser.add_argument('--task', action='store', metavar='TASK', help='Limit to results in specified %(metavar)s')
    parser.add_argument('--limit', action='store', type=int, metavar='NUM', default=50,
                        help='Limit to %(metavar)s results')
