using CySoft.Unimatrix;
using EPS.Toukass.Reporting.Reports.Helpers;
using EpsBO.AddIn.Reporting.Reports.Models;
using EpsBO.Kasse.Common.ViewModels;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace EpsBO.AddIn.Reporting.Reports
{
    public class AdrInvoiceByCouponNrReportManager : ReportManager
    {
        public AdrInvoiceByCouponNrReportManager(Report report, DbContext toukassDB, string licensee)
        : base(report, toukassDB, licensee)
        {
        }

        public const string ReportName = "rptAdrInvoiceByCouponNr";

        public override IEnumerable PrepareReportData(ReportManagerHost host, DbContext configDB)
        {
            IEnumerable<ReportFilterTerm> filterTerms = _report.GetFilterTerms(configDB);

            var filter = new Expression<Func<JournalBase, bool>>[] { j => j.CustomerNr != null };
            var journalEntries = ExecuteJournalQuery(filterTerms, _report.JournalSource, filter, onlyNullReceipts: true);
            var totals =
                (from j in journalEntries
                 orderby j.CustomerNr, j.DateTime, j.Id
                 group j by new {
                     j.DateTime.Date,
                     j.CustomerNr,
                     j.CouponNr,
                     j.ArticleNr,
                     j.Text,
                     j.SinglePrice,
                     j.TaxNr,
                     IsWeighted = j.Weight > 0,
                     Weight = j.Weight ?? 0
                 } into g
                 select new {
                     g.Key.Date,
                     g.Key.CustomerNr,
                     g.Key.CouponNr,
                     g.Key.ArticleNr,
                     g.Key.Text,
                     g.Key.IsWeighted,
                     g.Key.Weight,
                     g.Key.SinglePrice,
                     g.Key.TaxNr,
                     MinDate = g.Min(x => x.DateTime),
                     MaxDate = g.Max(x => x.DateTime),
                     AmountTotal = g.Sum(x => x.Amount ?? 0.0m),
                     QuantityTotal = g.Sum(x => x.Quantity ?? 0)
                 })
                .ToList();

            Dictionary<string, VW_CustomerAdr> customers = totals
                .Select(t => t.CustomerNr ?? "")
                .CustomersWithDummiesToDictByNr(_epsKasseDB);

            var taxBlocks = TaxBlockDictionary.FromEntries(totals,
                j => new TaxBlockDictionary.TaxData(j.TaxNr, j.CustomerNr, j.AmountTotal));

            IEnumerable<JournalTotals> journalTotals =
                from t in totals
                let c = customers[t.CustomerNr ?? ""]
                let taxBlock = taxBlocks[t.CustomerNr ?? ""]
                select new JournalTotals {
                    Date = t.Date,
                    CustomerNr = c.CustomerNr,
                    AddressMultiline = customers[c.CustomerNr].GetAddressMultiLine(),
                    Section = t.Coupon ?? 0, // Section as Coupon
                    Product = t.Product ?? 0,
                    Text = t.Text + WeightText(t.IsWeighted, t.Weight, t.SinglePrice, t.QuantityTotal, t.AmountTotal),
                    QuantityTotal = t.QuantityTotal,
                    AmountTotal = t.AmountTotal,
                    SinglePrice = t.SinglePrice,
                    Weight = t.Weight,
                    Date1 = t.MinDate,
                    Date2 = t.MaxDate,
                    Info = t.Taxe.HasValue ? t.Taxe + ")" : "", // Info as tax code
                    s1 = taxBlock.TaxIDColumn,
                    s2 = taxBlock.TextColumn,
                    s3 = taxBlock.NetColumn,
                    s4 = taxBlock.TaxColumn,
                    s5 = taxBlock.GrossColumn,
                };

            host.JournalTotalsBindingSource.DataSource = journalTotals.DefaultIfEmpty(new JournalTotals {
                Date1 = DateTime.Today,
                Date2 = DateTime.Today
            });
            return journalTotals;
        }

        private string WeightText(bool isWeighted, float weight, double? singlePrice, int quantityTotal, double amountTotal)
        {
            if (isWeighted && (singlePrice ?? 0.0) * quantityTotal != amountTotal) {
                return $" {weight} kg à";
            }
            return string.Empty;
        }

        public override ReportSlot GetReportSlot(ReportManagerHost host) => host.AdrInvoiceByCouponNrReportSlot;

    }
}