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.Email;

namespace KarleyUpdate
{
    internal static class BundlePrüfung
    {
        public static async Task RunAsync(ILogger logger)
        {
            using FbController2 fbController = new FbController2();
            //Korrektur der Stücklisten wo ggf. Menge = 0 steht, denn wenn es Teil einer Stückliste sollte mindestens 1 Stück drin sein ... Vermutlich Userfehler, den wir hier korrigieren
            await fbController.QueryAsync("UPDATE BUNDLES SET BUNDLE_N_MENGE = 1 WHERE BUNDLE_N_MENGE = 0");

            bool emailSenden = false;



            // Alle Stücklisten Artikel, die Inaktiv sind, oder nicht mehr existieren
            DataTable data = await GetInaktiveArtikelInBundleAsync(fbController);

            StringBuilder mailBuilder = new StringBuilder();
            mailBuilder.Append("1x monatlich werden unsere Bundles untersucht damit wir keine Bundles anbieten bei denen Artikel nicht mehr vorhanden sind.");
            mailBuilder.Append(" Das Bundle muss in der WK5 geprüft werden.");
            mailBuilder.Append(" Dort sind vermutlich Produkte die es ggf. nicht mehr gibt. Je nachdem müssen wir dann den Artikel gegen ");
            mailBuilder.Append(" einen neuen Austauschen und selbiges natürlich auch in der Produktbeschreibung online im Shop, sowie der WK5. Auch beachten das die ");
            mailBuilder.Append(" Preise dann ggf. steigen oder sinken. Wenn eventuell ein Produkt keinen Sinn mehr macht, muss es auch online gelöscht werden.<br /> <br />");

            // Verarbeite alle inaktiven und gelöschten Artikel aus Stücklisten in den Text der E-Mail
            if (data.Rows.Count > 0)
            {
                emailSenden = true;

                mailBuilder.Append("Folgende Bundles enthalten Artikel, die entweder inaktiv sind, oder nicht mehr existieren:<br />");

                string? tempStuecklisteNr = null;
                foreach (DataRow StueckArtikel in data.Rows)
                {
                    if (string.IsNullOrEmpty(tempStuecklisteNr) || tempStuecklisteNr != StueckArtikel["ARST_A_Hauptarti"].ToString())
                    {
                        tempStuecklisteNr = StueckArtikel["BUNDLE_A_ARTINR"].ToString();
                        mailBuilder.Append($"Bundle: {tempStuecklisteNr}<br />");
                    }
                    mailBuilder.Append($"\tPosition: {StueckArtikel["BUNDLE_N_SORT"]}  Artikel: {StueckArtikel["BUNDLE_A_UNTERARTINR"]}  (Menge: {StueckArtikel["BUNDLE_N_MENGE"]} , Bestand: {StueckArtikel["ARWE_N_BESTAND"]})<br />");
                }
                mailBuilder.Append($"<br />Gesamt: {data.Rows.Count} Artikel<br />");
            }

            // DataTable Reset
            data.Clear();
            data = await PruefeAufAktiveArtikelOhneBestand(fbController);


            // Verarbeite alle aktiven Artikel aus Stücklisten, welche über einen zu geringen Bestand verfügen in den Text der E-Mail
            if (data.Rows.Count > 0)
            {
                emailSenden = true;
                mailBuilder.Append("<br />xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
                mailBuilder.Append("<br />Folgende Bundles haben aktive Artikel ohne ausreichenden Bestand:");
                mailBuilder.Append("<br />xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
                mailBuilder.Append("<br />Bitte überprüfen, ob es Sinn macht ggf. einzelne Positionen in den folgenden Bundles durch andere Artikel zu ersetzen.<br />");
                string? tempStuecklisteNr = null;
                foreach (DataRow row in data.Rows)
                {
                    if (string.IsNullOrEmpty(tempStuecklisteNr) || tempStuecklisteNr != row["BUNDLE_A_ARTINR"].ToString())
                    {
                        tempStuecklisteNr = row["BUNDLE_A_ARTINR"].ToString();
                        mailBuilder.Append($"<br />Bundle: {tempStuecklisteNr}<br />");
                    }
                    mailBuilder.Append($"\tPosition: {row["BUNDLE_N_SORT"]} Artikel: {row["BUNDLE_A_UNTERARTINR"]} (Menge: {row["BUNDLE_N_MENGE"]} , Bestand: {row["GESAMT_BESTAND"]})<br />");

                }

                mailBuilder.Append($"<br />Gesamt: {data.Rows.Count} Artikel<br />");

            }

            // Sende E-Mail
            if (emailSenden)
            {
                EmailController emailController = new EmailController();
                await emailController.SendenAsync(GlobalConfig.EmailShopverwalter, "Bundles ohne Artikel gefunden", mailBuilder.ToString());
            }
        }
        /// <summary>
        /// Prüft alle Stuecklisten auf inaktive oder gelöschte Artikel
        /// </summary>
        /// <returns>Alle inaktiven oder gelöschten Artikel als DataTable</returns>
        private static Task<DataTable> GetInaktiveArtikelInBundleAsync(FbController2 fbController)
        {
            return fbController.SelectDataAsync(@"SELECT 
BUNDLE_A_ARTINR,BUNDLE_A_UNTERARTINR,BUNDLE_N_SORT,ARWE_N_BESTAND,BUNDLE_N_MENGE 
FROM BUNDLES AS BL 
LEFT JOIN ARTIKELWERTE AS AW ON BL.BUNDLE_A_UNTERARTINR = AW.ARWE_A_NR
LEFT JOIN ARTIKEL AS A ON A.ARTI_A_NR = AW.ARWE_A_NR 
WHERE ARWE_N_BESTAND < BUNDLE_N_MENGE 
AND (A.ARTI_L_INAKTIV = 'Y' OR (SELECT FIRST 1 CASE WHEN EXISTS(SELECT * FROM ARTIKEL WHERE ARTI_A_NR = A.ARTI_A_NR) THEN 1 ELSE 0 END AS ARTIKEL_EXISTIERT
FROM ARTIKEL A) != 1)
AND (SELECT ARTI_L_INAKTIV FROM ARTIKEL WHERE ARTI_A_NR = BL.BUNDLE_A_ARTINR) = 'N'
ORDER BY BUNDLE_A_ARTINR");
        }


        /// <summary>
        /// Prüft alle aktiven Artikel in allen Stücklisten, ob diese noch über ausreichenden Bestand verfügen
        /// </summary>
        /// <returns>Alle gefundenen Artikel ohne ausreichenden Bestand als DataTable</returns>
        private static Task<DataTable> PruefeAufAktiveArtikelOhneBestand(FbController2 fbController)
        {


            string SQL = @"SELECT * FROM 
    (SELECT 
        BUNDLE_A_ARTINR, 
        BUNDLE_A_UNTERARTINR,
        MAX(BUNDLE_N_SORT) AS BUNDLE_N_SORT, 
        (MAX(ARWE_N_BESTAND) + SUM(CAST(LIEFERANTEN_MENGE AS INTEGER))) AS GESAMT_BESTAND,
        MAX(BUNDLE_N_MENGE) AS BUNDLE_N_MENGE,
        MAX(VIRTUELLES_LAGER) AS VIRTUELLES_LAGER
    FROM
        (SELECT 
            BUNDLE_A_ARTINR,
            BUNDLE_A_UNTERARTINR,
            BUNDLE_N_SORT,
            ARWE_N_BESTAND,
            BUNDLE_N_MENGE,
            COALESCE(A.WK5_ARTI_N_VIRT_LAGER,0) AS VIRTUELLES_LAGER,     
            COALESCE(WK5_ARLI_N_LIEFBESTAND,0) AS LIEFERANTEN_MENGE
        FROM BUNDLES AS BL 
            LEFT JOIN ARTIKELWERTE AS AW ON BL.BUNDLE_A_UNTERARTINR = AW.ARWE_A_NR
            LEFT JOIN ARTIKEL AS A ON A.ARTI_A_NR = AW.ARWE_A_NR 
            LEFT JOIN LIEFERANTENARTIKEL AS LFA ON A.ARTI_A_NR = LFA.ARLI_A_ARTIKELNR 
        WHERE ARWE_N_BESTAND < BUNDLE_N_MENGE 
            AND A.ARTI_L_INAKTIV = 'N'
            AND A.ARTI_L_DIENSTLEIST = 'N'
            AND (SELECT ARTI_L_INAKTIV FROM ARTIKEL WHERE ARTI_A_NR = BL.BUNDLE_A_ARTINR) = 'N'
        ORDER BY BUNDLE_A_ARTINR) AS GEFUNDENE_ARTIKEL
    WHERE ARWE_N_BESTAND < BUNDLE_N_MENGE AND CAST(VIRTUELLES_LAGER AS INTEGER) = 0   
    GROUP BY BUNDLE_A_ARTINR, BUNDLE_A_UNTERARTINR)
WHERE GESAMT_BESTAND < BUNDLE_N_MENGE
";


            return fbController.SelectDataAsync(SQL);
        }

        /// <summary>
        /// Die Funktion prüft ob es sich bei einem Artikel um eine Stückliste handelt.
        /// </summary>
        /// <param name="ARTIKELNUMMER">Zu überprüfende Artikelnummer</param>
        /// <returns>True wenn es eine Stückliste ist, False wenn es keine ist.</returns>
        public static async Task<bool> IstBundle(string ARTIKELNUMMER, FbController2 fbController)
        {
            string SQL = @"SELECT 1 FROM ARTIKEL AS A
LEFT JOIN BUNDLES AS BL ON BL.BUNDLE_A_ARTINR = A.ARTI_A_NR
WHERE A.ARTI_A_NR = @ARTIKELNUMMER";
            fbController.AddParameter("@ARTIKELNUMMER", ARTIKELNUMMER);
            DataRow? row = await fbController.SelectRowAsync(SQL);

            return row is not null;
        }
    }
}
