#!/usr/bin/env python3

__version__ = '0.0.15'

import yaml
import importlib
import time

from collections import OrderedDict
from datetime import datetime

import rapidtables
import argparse

from neotermcolor import cprint

from types import SimpleNamespace

exitcode = 0

from bakauditor.tools import bytes_to_iso

try:
    yaml.warnings({'YAMLLoadWarning': False})
except:
    pass

table = []
result = []


def date_to_ts(d):
    d = str(d).upper()
    if d.endswith('S'):
        return float(d[:-1])
    elif d.endswith('M'):
        return float(d[:-1]) * 60
    elif d.endswith('H'):
        return float(d[:-1]) * 3600
    elif d.endswith('D'):
        return float(d[:-1]) * 86400
    elif d.endswith('W'):
        return float(d[:-1]) * 86400 * 7
    return float(d)


ap = argparse.ArgumentParser()

ap.add_argument('--version', help='Print version and exit', action='store_true')

ap.add_argument('-f',
                '--config',
                help='Configuration file',
                metavar='FILE',
                default='/usr/local/etc/bakauditor.yml')

ap.add_argument('-x',
                dest='failed_only',
                help='Print failed only',
                action='store_true')

ap.add_argument('backup_id', help='Backup ID', metavar='ID', nargs='?')

a = ap.parse_args()

if a.version:
    print(__version__)
    exit()

with open(a.config) as fh:
    config = yaml.load(fh)

defaults = config.get('default')
if not defaults: defaults = {}

checked = 0
failed = 0

if a.backup_id is not None:
    try:
        config = {a.backup_id: config[a.backup_id]}
    except KeyError:
        cprint('No such backup: {}'.format(a.backup_id), 'red', attrs='bold')
        exit(2)

for k, v in config.items():
    if k != 'default':
        for dk in defaults:
            if v.get(dk) is None:
                v[dk] = defaults[dk]
        checker = importlib.import_module('bakauditor.plugins.{}'.format(
            v['type']))
        try:
            r = checker.check(**v)
        except Exception as e:
            r = SimpleNamespace(ok=False, time=0, size=None, err=str(e))
        checked += 1
        if r.time > 0:
            if time.time() - date_to_ts(v['time']) > r.time:
                r.ok = False
                r.err = 'Outdated'
        d = OrderedDict()
        d['backup'] = k
        d['date'] = datetime.fromtimestamp(
            r.time).strftime('%Y-%m-%d %H:%M:%S') if r.time > 0 else '-'
        d['size'] = bytes_to_iso(r.size) if r.size is not None else '-'
        d['status'] = 'OK' if r.ok else (r.err if r.err else 'Failed')
        if not r.ok:
            exitcode = 1
            failed += 1
        if not r.ok or not a.failed_only:
            table.append(d)
            result.append({'backup': k, 'r': r})

print('Checked: ', end='')
cprint(checked, attrs='bold', end='')
print(', failed: ', end='')
cprint(str(failed), 'red' if failed else None, attrs='bold' if failed else None)
print()

if not result:
    if a.failed_only:
        cprint('All backups are fine', 'green')
    exit(exitcode)

table = sorted(table, key=lambda k: k['backup'])
result = sorted(result, key=lambda k: k['backup'])

h, vals = rapidtables.format_table(table, fmt=rapidtables.FORMAT_GENERATOR)

cprint(h, 'blue')
cprint('-' * len(h), 'grey')
for v, r in zip(vals, result):
    cprint(v, 'red' if not r['r'].ok else None)
exit(exitcode)
