using Serilog;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WK5.Core;
using WK5.Core.Basis.Filter;
using WK5.Core.Models;
using WK5.Core.Services;

namespace KarleyUpdate
{
    internal static class Statistik
    {
        public static async Task RunAsync(ILogger logger)
        {
            using FbController2 fbController = new FbController2();
            await SelektionsStatistikAsync(fbController);
        }

        private static async Task SelektionsStatistikAsync(FbController2 fbController)
        {
            await fbController.QueryAsync("DELETE FROM WK5_SELEKTIONSSTATISTIK");


            // Alle möglichen Selektionsmerkmale laden
            List<Selektionsmerkmal> selektionsmerkmale = await Selektionsmerkmal.GetSelektionsmerkmaleAsync(SelektionsMerkmalTyp.Kunde, fbController).ToListAsync();
            foreach (var merkmal in selektionsmerkmale)
            {

                // Wir brauchen als erstes Alle Kunden, bei denen mindestens eines der Selektionsmerkmale entspricht
                List<string> kundennummern = await fbController.SelectDataAsync<string>(@"SELECT DISTINCT KUND_A_NR FROM KUNDEN WHERE
   COALESCE(KUND_A_SELEKTION1, '') = @MERKMAL
OR COALESCE(KUND_A_SELEKTION2, '') = @MERKMAL
OR COALESCE(KUND_A_SELEKTION3, '') = @MERKMAL
OR COALESCE(KUND_A_SELEKTION4, '') = @MERKMAL
OR COALESCE(KUND_A_SELEKTION5, '') = @MERKMAL
OR COALESCE(KUND_A_SELEKTION6, '') = @MERKMAL", new
                {
                    MERKMAL = merkmal.SELE_A_ID
                });


                List<int> belegnummernRechnungen = new List<int>();
                List<int> belegnummernGutschriften = new List<int>();

                // Im nächsten Schritt werden alle Rechnungen der Kunden geholt
                foreach (string kundennummer in kundennummern)
                {
                    fbController.AddParameter("@KUNDENNUMMER", kundennummer);
                    DataTable belege = await fbController.SelectDataAsync("SELECT BELE_N_NR, BELE_A_TYP FROM BELEGE WHERE BELE_A_KUNDENNR = @KUNDENNUMMER AND BELE_A_TYP IN ('RE', 'GU')");

                    foreach (DataRow row in belege.Rows)
                    {
                        int belegnummer = row.Field<int>("BELE_N_NR");
                        string belegtyp = row.Field<string>("BELE_A_TYP") ?? String.Empty;

                        if (belegtyp is "RE")
                        {
                            belegnummernRechnungen.Add(belegnummer);
                        }
                        else if (belegtyp is "GU")
                        {
                            belegnummernGutschriften.Add(belegnummer);
                        }
                    }
                }



                // Als nächstes müssen die Erlöse für die Belege bestimmt werden

                decimal wert_bestellungen = 0;
                decimal rohertrag = 0;

                foreach (int belegnummer in belegnummernRechnungen)
                {
                    decimal ek = await GetPositionenEkAsync(belegnummer, "RE", fbController);
                    decimal vk = await GetPositionenVkAsync(belegnummer, "RE", fbController);

                    wert_bestellungen += vk;
                    rohertrag += vk - ek;
                }

                foreach (int belegnummer in belegnummernGutschriften)
                {
                    decimal ek = await GetPositionenEkAsync(belegnummer, "GU", fbController);
                    decimal vk = await GetPositionenVkAsync(belegnummer, "GU", fbController);

                    wert_bestellungen -= vk;
                    rohertrag -= vk - ek;
                }

                // Jetzt haben wir alle Daten die wir brauchen, rein in die Datenbank damit
                fbController.AddParameter("@SS_A_MERKMAL", merkmal.SELE_A_ID);
                fbController.AddParameter("@SS_N_ANZAHL_KUNDEN", kundennummern.Count);
                fbController.AddParameter("@SS_N_ANZAHL_BESTELLUNGEN", belegnummernRechnungen.Count);
                fbController.AddParameter("@SS_N_WERT_BESTELLUNGEN", wert_bestellungen);
                fbController.AddParameter("@SS_N_ROHERTRAG", rohertrag);
                await fbController.QueryAsync(@"INSERT INTO WK5_SELEKTIONSSTATISTIK
(
SS_A_MERKMAL, 
SS_N_ANZAHL_KUNDEN, 
SS_N_ANZAHL_BESTELLUNGEN, 
SS_N_WERT_BESTELLUNGEN, 
SS_N_ROHERTRAG
)
VALUES
(
@SS_A_MERKMAL, 
@SS_N_ANZAHL_KUNDEN, 
@SS_N_ANZAHL_BESTELLUNGEN, 
@SS_N_WERT_BESTELLUNGEN, 
@SS_N_ROHERTRAG
)");

                Console.WriteLine($"{merkmal.SELE_A_ID};{kundennummern.Count};{belegnummernRechnungen.Count} (RE);{belegnummernGutschriften.Count} (GU);{wert_bestellungen};{rohertrag}");

            }
        }


        private static async Task<decimal> GetPositionenEkAsync(int belegnummer, string belegtyp, FbController2 fbController)
        {
            fbController.AddParameter("@BELEGTYP", belegtyp);
            fbController.AddParameter("@BELEGNUMMER", belegnummer);
            DataRow? row = await fbController.SelectRowAsync("EXECUTE PROCEDURE WK5_PROZ_BELEG_EK(@BELEGTYP, @BELEGNUMMER)");

            if (row is null)
            {
                return 0;
            }

            return row.Field<decimal?>("EK_GESAMT") ?? 0;
        }

        private static async Task<decimal> GetPositionenVkAsync(int belegnummer, string belegtyp, FbController2 fbController)
        {
            fbController.AddParameter("@BELEGTYP", belegtyp);
            fbController.AddParameter("@BELEGNUMMER", belegnummer);
            DataRow? row = await fbController.SelectRowAsync("SELECT BPOS_N_NETTO AS VK FROM BELEGPOS WHERE BPOS_A_TYP = @BELEGTYP AND BPOS_N_NR = @BELEGNUMMER");

            if(row is null)
            {
                return 0;
            }

            return row.Field<decimal?>("VK") ?? 0;
        }

    }


}
