import datetime
from sqlalchemy.sql.expression import func, desc

from pyramid.view import view_config

from brewman.models import DBSession
from brewman.models.master import LedgerType, LedgerBase

from brewman.models.voucher import Voucher, Journal, VoucherType
from brewman.views.reports.closing_stock import get_closing_stock
from brewman.views.reports.profit_loss import get_accumulated_profit
from brewman.views.services.session import session_period_finish


@view_config(request_method='GET', route_name='balance_sheet', renderer='brewman:templates/angular_base.mako',
             permission='Balance Sheet')
@view_config(request_method='GET', route_name='balance_sheet_date', renderer='brewman:templates/angular_base.mako',
             permission='Balance Sheet')
def html(request):
    return {}


@view_config(request_method='GET', route_name='api_balance_sheet', renderer='json', permission='Balance Sheet')
def report_blank(request):
    return {'Date': session_period_finish(request), 'Body': [], 'Footer': []}


@view_config(request_method='GET', route_name='api_balance_sheet_date', renderer='json', permission='Balance Sheet')
def report_data(request):
    date = request.matchdict.get('date', None)
    body, footer = build_balance_sheet(date)
    return {'Date': date, 'Body': body, 'Footer': footer}


def build_balance_sheet(finish_date):
    if not isinstance(finish_date, datetime.datetime):
        finish_date = datetime.datetime.strptime(finish_date, '%d-%b-%Y')
    type_list = [i.id for i in LedgerType.list() if i.balance_sheet == True]
    report = []
    groups = dict()
    # Add Net Profit / Loss
    closing_stock = get_closing_stock(finish_date)
    net_profit = get_accumulated_profit(finish_date) - closing_stock
    total_amount = net_profit
    report.append({'Name': 'Net Loss' if net_profit >= 0 else 'Net Profit', 'SubAmount': net_profit, 'Order': 79})

    capital_group = LedgerType.by_id(5)
    groups[capital_group.id] = {'Group': capital_group.name, 'Amount': total_amount, 'Order': capital_group.order}

    total_amount += closing_stock
    report.append({'Name': 'Closing Stock', 'SubAmount': closing_stock, 'Order': 20.001})

    asset_group = LedgerType.by_id(4)
    groups[asset_group.id] = {'Group': asset_group.name, 'Amount': closing_stock, 'Order': asset_group.order}

    amount_sum = func.sum(Journal.amount * Journal.debit)
    query = DBSession.query(LedgerBase, amount_sum) \
        .join(Journal.voucher).join(Journal.ledger) \
        .filter(Voucher.date <= finish_date) \
        .filter(Voucher.type != VoucherType.by_name('Issue').id) \
        .filter(LedgerBase.type.in_(type_list)) \
        .group_by(LedgerBase).order_by(LedgerBase.type).order_by(desc(func.abs(amount_sum))).all()

    counter = 0
    sss = 0
    for ledger, amount in query:
        # Add Items
        ledger_type = LedgerType.by_id(ledger.type)
        sss += amount
        total_amount += amount
        if amount != 0:
            counter += .001
            report.append(
                {'Name': ledger.name, 'SubAmount': amount, 'Order': ledger_type.order + counter})
            if ledger_type.id in groups:
                groups[ledger_type.id]['Amount'] += amount
            else:
                groups[ledger_type.id] = {'Group': ledger_type.name, 'Amount': amount, 'Order': ledger_type.order}

    # Add Subtotals
    for item in groups.values():
        report.append(item)

    footer = [{'Name': 'Total', 'Amount': total_amount, 'Order': 100}]
    return sorted(report, key=lambda d: d['Order']), footer
