import moment from 'moment';


//TODO implement functions for calculating tax items, invoice items and invoices

//a unit containing common functionality for invoices module
export function num(s, places) {
    let n = isNaN(s) ? 0 : s * 1;
    if (places) {
    	n = round(n, places);
    }
    return n * 1;
}

export function round(num, places) { 
	return +(Math.round(num + "e+" + places)  + "e-" + places);
}


export function taxId(name) {
    return name; //FIXME
}

// TODO precise calculation
export function calculateTaxItem(ti, calcTotal) {
    if (!ti) {
        return;
    }

    // calculate tax item
    let base = num(ti.base, 2);
    let tax = ti.flat ? num(ti.taxAmount) : base * num(ti.taxPercent) / 100;
    ti.tax = num(tax, 2);
    ti.base = num(base, 2);

    if (calcTotal) {
        ti.total = num(base + ti.tax, 2);
    }

    return ti;
}


export function calculateInvoice(invoice) {
    if (!invoice) {
        return;
    }

    // calculate invoice
    var amount = 0;
    var payable = 0;

    var taxItems = {};
    var taxItem = null;

    // calculate items first
    if (invoice.items && invoice.items.length) {
        for (var j = 0; j < invoice.items.length; j++) {
        	var i = invoice.items[j];
            calculateInvoiceItem(i, true);

            amount += num(i.amount, 2);
            payable += num(i.amount, 2);

            if (i.taxItems && i.taxItems.length) {
                for (var k = 0; k < i.taxItems.length; k++) {
                    // calculate tax item

                	var ti = calculateTaxItem(i.taxItems[k]);
                    var base = num(amount, 2);
                    var tax = num(ti.tax, 2);
                    payable += tax;

                    // aggregate invoice tax items
                    var key = ti.taxType;

                    taxItem = taxItems[key];
                    if (!taxItem) {
                        taxItem = {};
                        taxItems[key] = taxItem;
                        taxItem.taxType = ti.taxType;
                        taxItem.taxPercent = ti.taxPercent;
                        taxItem.taxAmount = ti.taxAmount;
                        taxItem.flat = ti.flat;

                        taxItem.base = 0;
                        taxItem.tax = 0;
                        taxItem.total = 0;
                    }

                    taxItem.base += base;
                    taxItem.tax += tax;
                    taxItem.total = num(base + tax, 2);
                }
            }
        }
    }

    // convert object into array
    const invoice_tax = [];
    for (var key in taxItems) {
        invoice_tax.push(taxItems[key]);
    }

    invoice.totalAmount = amount;
    invoice.totalPayable = payable;

    invoice.tax = invoice_tax;
    
    return invoice;
}

// TODO precise calculation
export function calculateInvoiceItem(item) {
    if (!item) {
        return;
    }


    if (!isNaN(item.priceUom) && !item.amount) {
        item.amount = num(num(item.priceUom, 2) * num(item.pieces || 1, 3), 2);
    }
    
    return item;
}


//TODO implement
function aggregateTaxItems(invoice) {
    return invoice;
}


export function calculatePaymentStats(payments, currency) {
    let total = 0;
    let paid = 0;
    let pending = 0;
    let overdue = 0;
    let now = moment().format("YYYY-MM-DD");
    let buckets = {};

    if (payments) {
        payments.forEach(p => {
            let amount = p.get("amount");
            let isPaid = p.get("paid");
            let dueDate = p.get("dueDate");
            let year = dueDate.substring(0, 4);
            let bucket = buckets[year];
            if (!bucket) {
                bucket = {
                    total: 0,
                    paid: 0,
                    pending: 0
                };
                buckets[year] = bucket;
            }

            total = round(total + amount, 2);
            bucket.total = round(bucket.total + amount);
            if (isPaid) {
                paid = round(paid + amount, 2);
                bucket.paid = round(bucket.paid + amount, 2);
            } else if (now > dueDate) {
                overdue = round(overdue + amount, 2);
            } else {
                pending = round(pending + amount, 2);
                bucket.pending = round(bucket.pending + amount, 2);
            }
        });
    }

    return {
        stats:{ 
            total, paid, pending, overdue
        },
        buckets
    };
}


export function calculatePaymentSum() {
    //TODO sum payments
    return {

    };
}



export function calculateIncome(income) {
    if (!income) {
        return;
    }

    // calculate invoice
    var amount = 0;
    var payable = income.totalAmount;

    if (income.taxItems && income.taxItems.length) {
        for (var k = 0; k < income.taxItems.length; k++) {
            // calculate tax item
            var ti = calculateTaxItem(income.taxItems[k]);
            var tax = num(ti.tax, 2);
            payable += tax;
        }
    }

    income.totalPayable = payable;

    return income;
}
