import datetime
from sqlalchemy.sql.expression import func

from pyramid.view import view_config

from brewman.models import DBSession
from brewman.models.master import Product, CostCenter

from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory
from brewman.views.services.session import session_period_start, session_period_finish


@view_config(request_method='GET', route_name='stock_movement', renderer='brewman:templates/angular_base.mako',
             permission='Stock Movement')
def html(request):
    return {}


@view_config(request_method='GET', route_name='api_stock_movement', renderer='json', permission='Stock Movement')
def get_stock_movement(request):
    start_date = request.GET.get('StartDate', None)
    finish_date = request.GET.get('FinishDate', None)
    if start_date and finish_date:
        report = {'StartDate': start_date, 'FinishDate': finish_date}
        start_date = datetime.datetime.strptime(start_date, '%d-%b-%Y')
        finish_date = datetime.datetime.strptime(finish_date, '%d-%b-%Y')
        report['Body'] = build_stock_movement(start_date, finish_date)
        return report
    else:
        return {'StartDate': session_period_start(request),
                'FinishDate': session_period_finish(request), 'Body': []}


def build_stock_movement(start_date, finish_date):
    dict = {}
    quantity_sum = func.sum(Journal.debit * Inventory.quantity).label('Quantity')
    openings = DBSession.query(Product, quantity_sum) \
        .join(Product.inventories).join(Inventory.voucher).join(Voucher.journals) \
        .filter(Voucher.date < start_date) \
        .filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \
        .group_by(Product).all()
    for product, quantity in openings:
        dict[product.id] = {'ProductID': product.id, 'Name': product.full_name, 'Group': product.product_group.name,
                            'Opening': quantity}
    purchases = DBSession.query(Product, quantity_sum) \
        .join(Product.inventories).join(Inventory.voucher).join(Voucher.journals) \
        .filter(Voucher.date >= start_date) \
        .filter(Voucher.date <= finish_date) \
        .filter(Voucher.type != VoucherType.by_name('Issue').id) \
        .filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \
        .group_by(Product).all()
    for product, quantity in purchases:
        if product.id in dict:
            dict[product.id]['Purchase'] = quantity
        else:
            dict[product.id] = {'ProductID': product.id, 'Name': product.full_name, 'Group': product.product_group.name,
                                'Purchase': quantity}
    issues = DBSession.query(Product, quantity_sum) \
        .join(Product.inventories).join(Inventory.voucher).join(Voucher.journals) \
        .filter(Voucher.date >= start_date) \
        .filter(Voucher.date <= finish_date) \
        .filter(Voucher.type == VoucherType.by_name('Issue').id) \
        .filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \
        .group_by(Product).all()
    for product, quantity in issues:
        if product.id in dict:
            dict[product.id]['Issue'] = quantity * -1
        else:
            dict[product.id] = {'ProductID': product.id, 'Name': product.full_name, 'Group': product.product_group.name,
                                'Issue': quantity * -1}

    list = [value for key, value in dict.items()]
    list = sorted(list, key=lambda x: x['Name'].lower())
    list = sorted(list, key=lambda x: x['Group'].lower())
    for i in range(len(list), 0, -1):
        item = list[i - 1]
        opening = item['Opening'] if 'Opening' in item else 0
        purchase = item['Purchase'] if 'Purchase' in item else 0
        issue = item['Issue'] if 'Issue' in item else 0
        closing = opening + purchase - issue
        if opening == 0 and purchase == 0 and issue == 0:
            list.remove(item)
        else:
            item['Closing'] = closing
    return list