#!python

import os
import sys
import time
import json
import datetime
import yaml
import pwd
from monzo_db import DB

PROVIDER = 'Monzo'

FIELD_MAP = {
    'date': 'created_at'
}

class Monzo:

    def __init__(self):
        homedir = pwd.getpwuid(os.getuid()).pw_dir
        monzo_dir = f"{homedir}/.monzo"

        if not os.path.exists(monzo_dir):
            os.mkdir(monzo_dir, 0o755)

        config_file = f"{monzo_dir}/config.yaml"

        self.config = yaml.safe_load(open(config_file).read())

        self.db = DB(self.config['db'])


    def accounts(self, first=True):
        provider = m.db.one("select * from provider where name = %s", [PROVIDER])
        accounts = m.db.query("select * from account where provider_id = %s", [provider['id']])

        accounts_by_name = {}

        for account in accounts:
            accounts_by_name[account['name']] = account

        count = 0

        if 'account_order' in self.config:
            order = self.config['account_order']
        else:
            order = list(sorted(list(accounts_by_name.keys())))

        for account_name in order:
            acc = accounts_by_name[account_name]

            account = {
                'Account': acc['name']
            }

            if 'sortcode' in acc:
                account['Sort code'] = acc['sortcode']
                account['Account no'] = acc['account_no']
            else:
                account['Sort code'] = ' ' * 8
                account['Account no'] = ' ' * 8

            account['Balance'] = '£%.2f' % (acc['balance'])
            account['Available'] = '£%.2f' % (acc['available'])

            pots = self.db.query("select * from pot where account_id = %s and deleted = 0", [acc['id']])

            keys = ['Account','Sort code','Account no', 'Balance', 'Available']

            for pot in pots:
                account[pot['name']] = '£%.2f' % (pot['balance'])

                keys.append(pot['name'])

            self.display([account], keys, count == 0 or '-t' in sys.argv)

            transactions = False
            n = 10

            for i in range(0, len(sys.argv)):
                if sys.argv[i] == '-t':
                    transactions = True
                    if i+1 < len(sys.argv) and sys.argv[i+1].isdigit():
                        n = int(sys.argv[i+1])

            if transactions:
                sys.stdout.write("\n")

                rows = m.db.query("select transaction.*, account.name as account from transaction join account on account_id = account.id where account_id = %s order by id desc limit %s", [acc['id'], n])

                rows = list(reversed(rows))

                self.display(rows, ['account','date','type','money_in','money_out','pending','description','notes'])

                sys.stdout.write("\n")

            count += 1


    def display(self, data, columns, show_headers=True):
        widths = {}

        for key in columns:
            if key in ['Balance','Available']:
                widths[key] = 8
            else:
                widths[key] = len(key)

        for i in range(0, len(data)):
            for key in columns:
                if key in FIELD_MAP:
                    data[i][key] = data[i][FIELD_MAP[key]]

                if data[i][key] is None:
                    data[i][key] = ''

                if type(data[i][key]) == datetime.datetime:
                    data[i][key] = data[i][key].strftime('%d.%m.%Y %H:%M')

                if len(str(data[i][key])) > widths[key]:
                    widths[key] = len(str(data[i][key]))

        if show_headers:
            for key in columns:
                sys.stdout.write(key.ljust(widths[key]+2))
            sys.stdout.write("\n")

            for key in columns:
                sys.stdout.write('-' * (widths[key]+2))
            sys.stdout.write("\n")

        for i in range(0, len(data)):
            for key in columns:
                sys.stdout.write(str(data[i][key]).ljust(widths[key]+2))

            sys.stdout.write("\n")


m = Monzo()
m.accounts()
