using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WK5.Core;
using System.Linq;
using KarleyLibrary.Attributes;

namespace WK5.Core.Models
{
    public class Verbrauchsdaten
    {
        [CompareField("VERB_A_ARTIKELNR")]
        public string Artikelnummer { get; set; }
        [CompareField("VERB_N_JAHR")]
        public int Jahr { get; set; }
        [CompareField("VERB_N_MONAT")]
        public int Monat { get; set; }
        [CompareField("VERB_N_MENGE")]
        public decimal Menge { get; set; }
        [CompareField("VERB_N_UMSATZ")]
        public decimal Umsatz { get; set; }
        [CompareField("VERB_N_GEWINN")]
        public decimal Gewinn { get; set; }

        public static string DatenSql = @"SELECT
COALESCE(EXTRACT(MONTH FROM BELE_D_DATE),0) as monat,
COALESCE(EXTRACT(YEAR FROM BELE_D_DATE),0) as jahr,
COALESCE(SUM(BPOS_N_MENGE),0) as menge, 
COALESCE(SUM((COALESCE(BPOS_N_PREIS,0) * (1-COALESCE(BPOS_N_RABATTPROZ,0)/100) * (1-COALESCE(BPOS_N_RABATTPROZ2,0)/100))*BPOS_N_MENGE - (SELECT SUM(CHAR_N_EKPREIS * BCHA_N_MENGE) as posek FROM BELEGCHARGEN
LEFT JOIN CHARGEN ON BCHA_N_CHARGE = CHAR_N_NR
WHERE BCHA_N_POSID = BPOS_N_POSID)),0) as gewinn,
COALESCE(SUM((COALESCE(BPOS_N_PREIS,0) * (1-COALESCE(BPOS_N_RABATTPROZ,0)/100) * (1-COALESCE(BPOS_N_RABATTPROZ2,0)/100))*BPOS_N_MENGE),0) as umsatz
FROM BELEGPOS
LEFT JOIN BELEGE ON BELE_A_TYP = BPOS_A_TYP AND BELE_N_NR = BPOS_N_NR WHERE 1=1";

        public static string FilterSql = @" AND BPOS_A_TYP = @BELEGTYP
AND BPOS_A_ARTIKELNR = @ARTIKEL
GROUP BY monat, jahr
HAVING (SUM(BPOS_N_MENGE) > 0 OR SUM(BPOS_N_NETTO) > 0)
ORDER BY jahr, monat";
        public static async IAsyncEnumerable<Verbrauchsdaten> GetCache(string artikelnummer)
        {
            using FbController2 fbController = new FbController2();
            string datenSql = DatenSql + FilterSql;

            fbController.AddParameter("@ARTIKEL", artikelnummer);
            fbController.AddParameter("@BELEGTYP", "RE");
            DataTable rechnungsDataTable = await fbController.SelectDataAsync(datenSql);

            fbController.AddParameter("@ARTIKEL", artikelnummer);
            fbController.AddParameter("@BELEGTYP", "GU");
            DataTable gutschriftDataTable = await fbController.SelectDataAsync(datenSql);

            var rechnungData = rechnungsDataTable.Rows.Cast<DataRow>();
            var gutschriftData = gutschriftDataTable.Rows.Cast<DataRow>();
            if (rechnungData.Any() || gutschriftData.Any())
            {
                int oldest = rechnungData.Min(x => x.Field<int>("jahr"));
                if (gutschriftData.Count() > 0)
                {
                    int oldestGutschrift = gutschriftData.Min(x => x.Field<int>("jahr"));
                    if(oldestGutschrift < oldest)
                    {
                        oldest = oldestGutschrift;
                    }
                }                

                for (int jahr = oldest; jahr <= DateTime.Now.Year; jahr++)
                {
                    for (int monat = 1; monat <= 12; monat++)
                    {
                        var rechnungEntries = rechnungData.Where(x => x.Field<int>("monat") == monat && x.Field<int>("jahr") == jahr);
                        var gutschriftEntries = gutschriftData.Where(x => x.Field<int>("monat") == monat && x.Field<int>("jahr") == jahr);
                        if (rechnungEntries.Any() || gutschriftEntries.Any())
                        {
                            var cache = new Verbrauchsdaten()
                            {
                                Artikelnummer = artikelnummer,
                                Jahr = jahr,
                                Monat = monat,
                                Menge = rechnungEntries.Sum(x => x.Field<decimal>("menge")) - gutschriftEntries.Sum(x => x.Field<decimal>("menge")),
                                Gewinn = rechnungEntries.Sum(x => x.Field<decimal>("gewinn")) - gutschriftEntries.Sum(x => x.Field<decimal>("gewinn")),
                                Umsatz = rechnungEntries.Sum(x => x.Field<decimal>("umsatz")) - gutschriftEntries.Sum(x => x.Field<decimal>("umsatz"))
                            };

                            yield return cache;
                        }
                    }
                }

            }
        }
        
        public static async IAsyncEnumerable<Verbrauchsdaten> GetCurrentMonthCache(string artikelnummer)
        {
            using FbController2 fbController = new FbController2();

            string datenSql = DatenSql;
            datenSql += @" AND COALESCE(EXTRACT(MONTH FROM BELE_D_DATE),0) = @MONAT
AND COALESCE(EXTRACT(YEAR FROM BELE_D_DATE),0) = @JAHR";
            datenSql += FilterSql;            

            fbController.AddParameter("@ARTIKEL", artikelnummer);
            fbController.AddParameter("@BELEGTYP", "RE");
            fbController.AddParameter("@MONAT", DateTime.Now.Month);
            fbController.AddParameter("@JAHR", DateTime.Now.Year);
            DataTable rechnungsDataTable = await fbController.SelectDataAsync(datenSql);

            fbController.AddParameter("@ARTIKEL", artikelnummer);
            fbController.AddParameter("@BELEGTYP", "GU");
            fbController.AddParameter("@MONAT", DateTime.Now.Month);
            fbController.AddParameter("@JAHR", DateTime.Now.Year);
            DataTable gutschriftDataTable = await fbController.SelectDataAsync(datenSql);

            var rechnungData = rechnungsDataTable.Rows.Cast<DataRow>();
            var gutschriftData = gutschriftDataTable.Rows.Cast<DataRow>();
            if (rechnungData.Any() || gutschriftData.Any())
            {
                int oldest = rechnungData.Min(x => x.Field<int>("jahr"));
                if (gutschriftData.Count() > 0)
                {
                    int oldestGutschrift = gutschriftData.Min(x => x.Field<int>("jahr"));
                    if (oldestGutschrift < oldest)
                    {
                        oldest = oldestGutschrift;
                    }
                }

                for (int jahr = oldest; jahr <= DateTime.Now.Year; jahr++)
                {
                    for (int monat = 1; monat <= 12; monat++)
                    {
                        var rechnungEntries = rechnungData.Where(x => x.Field<int>("monat") == monat && x.Field<int>("jahr") == jahr);
                        var gutschriftEntries = gutschriftData.Where(x => x.Field<int>("monat") == monat && x.Field<int>("jahr") == jahr);
                        if (rechnungEntries.Any() || gutschriftEntries.Any())
                        {
                            var cache = new Verbrauchsdaten()
                            {
                                Artikelnummer = artikelnummer,
                                Jahr = jahr,
                                Monat = monat,
                                Menge = rechnungEntries.Sum(x => x.Field<decimal>("menge")) - gutschriftEntries.Sum(x => x.Field<decimal>("menge")),
                                Gewinn = rechnungEntries.Sum(x => x.Field<decimal>("gewinn")) - gutschriftEntries.Sum(x => x.Field<decimal>("gewinn")),
                                Umsatz = rechnungEntries.Sum(x => x.Field<decimal>("umsatz")) - gutschriftEntries.Sum(x => x.Field<decimal>("umsatz"))
                            };

                            yield return cache;
                        }
                    }
                }

            }
        }
        public async Task Save()
        {
            string sql = @"UPDATE OR INSERT INTO VERBRAUCHSDATEN 
(VERB_A_ARTIKELNR,VERB_N_MONAT, VERB_N_JAHR, VERB_N_MENGE,VERB_N_UMSATZ, VERB_N_GEWINN)
VALUES
(@VERB_A_ARTIKELNR,@VERB_N_MONAT, @VERB_N_JAHR, @VERB_N_MENGE,@VERB_N_UMSATZ, @VERB_N_GEWINN)";

            using FbController2 fbController = new FbController2();
            fbController.AddParameter("@VERB_A_ARTIKELNR", Artikelnummer);
            fbController.AddParameter("@VERB_N_MONAT", Monat);
            fbController.AddParameter("@VERB_N_JAHR", Jahr);
            fbController.AddParameter("@VERB_N_MENGE", Menge);
            fbController.AddParameter("@VERB_N_UMSATZ", Umsatz);
            fbController.AddParameter("@VERB_N_GEWINN", Gewinn);

            await fbController.QueryAsync(sql);
        }
    }
}
