using System;
using System.Collections.Generic;
using Winbooks.TORM.OM;
using Winbooks.TORM.OM.Accounting;
using Winbooks.TORM.DAL;
using Winbooks.TORM.DAL.Accounting;
using Winbooks.TORM.OM.Logistics;
using Winbooks.TORM.DAL.Logistics;
using Winbooks.Apis.Services;
using Winbooks.Apis.Services.v2;
using Currency = Winbooks.TORM.OM.Currency;


namespace Winbooks.Apis.Demo
{
    public class PostInvoice
    {
        private static EntitiesServices _folder;
        private static Vat _defaultVat;

        private static Decimal _totalBase6, _totalVat6;
        private static Decimal _totalBase21, _totalVat21;
        private static Decimal _totalBase, _totalVat;

        public static string MainExecute(EntitiesServices folder)
        {
            _folder = folder;
            return ExecutePostInvoice();
        }

        private static string ExecutePostInvoice()
        {

            Tools.Log("Getting the Id of related entities ...");
            BookPeriod bookPeriod = GetEntity.GetBookPeriod(_folder, 2012, 4); if (bookPeriod == null) return "Bookperiod 2012 4 not found";
            Currency currency = GetEntity.GetCurrency(_folder, "EUR"); if (currency == null) return "Currency EUR not found";
            JournalLog journalLog = _folder.GetByCode<JournalLog>("FAC"); if (journalLog == null) return "JournalLog FAC not found";
            Customer customer = _folder.GetByCode<Customer>("BEBOP"); if (customer == null) return "Customer BEBOP not found";
            Address address = GetEntity.GetDefaultAddressInvoicing(_folder, customer.Third_Id);
            Vat vat6 = _folder.GetByCode<Vat>("6"); if (vat6 == null) return "Vat 6 not found";
            Vat vat21 = _folder.GetByCode<Vat>("21"); if (vat21 == null) return "Vat 21 not found";
            PayCode payCode = _folder.GetByCode<PayCode>("30"); if (payCode == null) return "PayCode 30 not found";

            _defaultVat = vat21;
            Tools.Log("OK");

            _totalBase6 = _totalVat6 = 0;
            _totalBase21 = _totalVat21 = 0;

            Tools.Log("Creating DocumentHeader ...");
            DocumentHeader dh = new DocumentHeader();
            dh.JournalLog_Id = journalLog.Id;
            dh.Number = GetNextDocNumber(journalLog.Id);
            dh.Customer_Id = customer.Id;
            dh.BookPeriod_Id = bookPeriod.Id;
            dh.Date = DateTime.Parse("2015-04-15T00:00:00");
            dh.PayCode_Id = payCode.Id;
            dh.DueDate = DateTime.Parse("2015-05-15T00:00:00");
            dh.Currency_Id = currency.Id;
            dh.CurrencyRate = 1;
            dh.ThirdReference = "Test";
            dh.ComputingMethod = 1;
            if (address != null)
            { 
                dh.Addressing = new DocumentAddressing();
                dh.Addressing.InvoicingAddress = address;
            }

            int rowNumber = 1;
            dh.Details.Add(CreateDocumentDetail(rowNumber++, "PCCBO", "", 1, 200, vat6));
            dh.Details.Add(CreateDocumentDetail(rowNumber++, "", "Setup of the system", 1, 100, vat21));

            dh.TotalBase = _totalBase;
            dh.TotalVat = _totalVat;
            dh.TotalToPay = _totalBase + _totalVat;

            string msg = journalLog.Code + " " + dh.Number.ToString();
            Tools.Log("Creating " + msg, true);
            _folder.Insert<DocumentHeader>(dh, 5);
            Tools.Log("Creating " + msg + " : OK");

            return "OK";
        }

        private static DocumentDetail CreateDocumentDetail(int rowNumber, string itemCode, string description, decimal qty, decimal unitprice = 0, Vat vat = null)
        {
            DocumentDetail dd = new DocumentDetail();
            DocumentRow dr = new DocumentRow();

            dd.Row = dr;
            dd.RowNumber = rowNumber;

            // Item
            if (!string.IsNullOrEmpty(itemCode))
            {
                Item item = _folder.GetByCode<Item>(itemCode);
                if (item == null) return null;
                dd.Row.Item_Id = item.Id;
                if (string.IsNullOrEmpty(description))
                    dd.Row.Name = item.Name;
                if (item.VatSale != null)
                    dd.Row.Vat = item.VatSale;
            }

            // Description
            if (!string.IsNullOrEmpty(description))
                dd.Row.Name = description;

            dd.Quantity = qty;
            dd.Row.UnitPrice = unitprice;
            dd.Amount = decimal.Round(qty * unitprice, 2);
            dd.CostAmount = 0;

            if (qty != 0 && unitprice != 0)
            {
                if (vat != null)    // If vat is specified in the parameters, we force to this vat
                    dd.Row.Vat = vat;
                else
                {
                    if (dd.Row.Vat == null)  // Was not specified in the item
                        dd.Row.Vat = _defaultVat;
                }

                // Compute totals / vat
                Decimal vatAmount = 0;
                switch (dd.Row.Vat.Code)
                {
                    case "6":
                        _totalBase6 += dd.Amount;
                        vatAmount = decimal.Round(dd.Amount * 6 / 100, 2);
                        _totalVat6 += vatAmount;
                        break;
                    case "21":
                        _totalBase21 += dd.Amount;
                        vatAmount = decimal.Round(dd.Amount * 21 / 100, 2);
                        _totalVat21 += vatAmount;
                        break;
                }
                _totalBase += dd.Amount;
                _totalVat += vatAmount;
            }

            return dd;
        }

        private static long GetNextDocNumber(Guid journalId)
        {
            //GET LAST GLTRANSHEADER DOCUMENT NUMBER
            Tools.Log("Getting the last Document Number of journal", true);
            var lastHeaderCriteria = new DocumentHeaderDAO().CreateCriteria()
                .Add(Condition.Eq(DocumentHeader.Names.JournalLog_Id, journalId))
                .Order(DocumentHeader.Names.Number, false)
                .SetFirstResult(0).SetMaxResults(1);

            DocumentHeader lastHeader = _folder.GetFilter<DocumentHeader>(lastHeaderCriteria);
            long documentNumber = 1;

            if (lastHeader != null)
            {
                Tools.Log("Getting the last Document Number (" + lastHeader.Number + ") : OK");
                documentNumber = lastHeader.Number + 1;
            }
            else
                Tools.Log("Folder has no document in the journal");
            return documentNumber;
        }


    }
}
