//#define kleinTest
using KarleyLibrary.Erweiterungen;
using Serilog.Core;
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;
using WK5.Core.Models;
using WK5.Core.Services;

namespace KarleyUpdate
{
    internal static class Wartungscheck
    {
        private const string TECHNIK_EMAIL = "supportteam@karley.eu";
        public static async Task RunAsync(Logger logger)
        {
            using FbController2 fbController = new FbController2();

            WartungsService wartungsService = new WartungsService();
            ArtikelService artikelService = new ArtikelService();

            // MK: Alte Belege können keine korrekte zuordnung zur Position haben, durch einen Fehler beim ändern von Artikelnummern. Daher wird zusätzlich geprüft für Seriennummer is not null.
            // Das kleinstmögliche Intervall ist 1 Monat, daher müssen wir den Belegzeitraum Monatsweise abfragen
            // 02.11.2021 - MK: Mit Technik besprochen, die Wartungen laufen permanent bis beendet und nicht nur 2 Jahre.
            // AND BELE_D_DATE BETWEEN DATEADD(-2 year to CURRENT_DATE) AND CURRENT_DATE
            DataTable data = await fbController.SelectDataAsync(@"select 
BELE_N_NR AS RECHNUNGSNUMMER,
B.BELE_A_KUNDENNR AS KUNDENNUMMER,
iif(BSTU_A_UNTERARTI IS NOT NULL, BSTU_A_UNTERARTI, BPOS_A_ARTIKELNR) AS ARTIKELNUMMER,
BSN.BSNR_A_SN AS SERIENNUMMER,
BELE_D_DATE AS RECHNUNGSDATUM
FROM BELEGE B
LEFT JOIN KUNDEN K ON (K.KUND_A_NR = B.BELE_A_KUNDENNR)
LEFT JOIN BELEGPOS BP ON (BPOS_A_TYP = 'RE' AND BPOS_N_NR = BELE_N_NR)
LEFT JOIN BELEGSTUECKLISTE BST ON BST.BSTU_N_BELEPOSID = BPOS_N_POSID
LEFT JOIN BELEGSN BSN ON (BSN.BSNR_N_POSID = BP.BPOS_N_POSID AND BSN.BSNR_N_STLPOSID = coalesce(BST.BSTU_N_POSID, 0))
LEFT JOIN ARTIKEL A ON ARTI_A_NR = iif(coalesce(BSTU_A_UNTERARTI, '') != '', BSTU_A_UNTERARTI, BPOS_A_ARTIKELNR)
WHERE BELE_A_TYP = 'RE'
AND ARTI_N_WARTUNGSINTERVALL > 0 
AND BSNR_A_SN IS NOT NULL
AND KUND_L_KEINE_WARTUNGEN = 'N'
AND DATEADD(ARTI_N_WARTUNGSINTERVALL month to BELE_D_DATE) < CURRENT_DATE
AND NOT EXISTS(SELECT 1 FROM WARTUNGEN WHERE WART_A_KUNDENNR = BELE_A_KUNDENNR AND WART_A_SN = BSNR_A_SN AND WART_L_ERLEDIGT = 'N')
AND (COALESCE((SELECT MAX(CAST(WART_D_ERLEDIGT AS DATE)) FROM WARTUNGEN WHERE WART_A_KUNDENNR = BELE_A_KUNDENNR AND WART_A_SN = BSNR_A_SN), '01.01.0001')) < DATEADD(-ARTI_N_WARTUNGSINTERVALL month to CURRENT_DATE)
AND NOT EXISTS(SELECT 1 FROM STOP_WARTUNG WHERE STWA_A_KUNDENNR = BELE_A_KUNDENNR AND STWA_A_SN = BSNR_A_SN)
UNION ALL
SELECT  
WART_N_NR AS RECHNUNGSNUMMER,
WART_A_KUNDENNR AS KUNDENNUMMER,
WART_A_ARTIKELNR AS ARTIKELNUMMER,
WART_A_SN AS SERIENNUMMER,
WART_D_DATE AS RECHNUNGSDATUM
FROM WARTUNGEN W1
LEFT JOIN KUNDEN K ON K.KUND_A_NR = W1.WART_A_KUNDENNR
LEFT JOIN ARTIKEL A ON A.ARTI_A_NR = W1.WART_A_ARTIKELNR
WHERE W1.WART_L_MANUELL = 'Y'
AND A.ARTI_N_WARTUNGSINTERVALL > 0
AND K.KUND_L_KEINE_WARTUNGEN = 'N'
AND DATEADD(A.ARTI_N_WARTUNGSINTERVALL month to W1.WART_D_DATE) < CURRENT_DATE
AND NOT EXISTS(SELECT 1 FROM WARTUNGEN W2 WHERE W2.WART_A_KUNDENNR = W1.WART_A_KUNDENNR AND W2.WART_A_SN = W1.WART_A_SN AND W2.WART_L_ERLEDIGT = 'N')
AND (COALESCE((SELECT MAX(CAST(W3.WART_D_ERLEDIGT AS DATE)) FROM WARTUNGEN W3 WHERE W3.WART_A_KUNDENNR = W1.WART_A_KUNDENNR AND W3.WART_A_SN = W1.WART_A_SN), '01.01.0001')) < DATEADD(-ARTI_N_WARTUNGSINTERVALL month to CURRENT_DATE)
AND NOT EXISTS(SELECT 1 FROM STOP_WARTUNG WHERE STWA_A_KUNDENNR = WART_A_KUNDENNR AND STWA_A_SN = WART_A_SN)");
            EmailController emailController = new EmailController();
            var absender = new EmailAbsender(GlobalConfig.Configuration.WartungAbsenderName, GlobalConfig.Configuration.WartungsAbsender, GlobalConfig.Configuration.WartungsAbsender);
            foreach (DataRow row in data.Rows)
            {
                var wartung = new Wartung
                {
                    Artikelnummer = row.Field<string>("ARTIKELNUMMER")!,
                    Seriennummer = row.Field<string>("SERIENNUMMER")!,
                    Kundennummer = row.Field<string>("KUNDENNUMMER")!
                };

                Ansprechpartner? ansprechpartner = await Ansprechpartner.GetAnsprechpartnerAsync(wartung.Kundennummer).Where(x => x.PART_N_FUNKTION == 6).FirstOrDefaultAsync();

                if (ansprechpartner is not null)
                {
                    wartung.AnsprechpartnerId = ansprechpartner.PART_N_NR;
                }

                int rechnungsnummer = row.Field<int>("RECHNUNGSNUMMER");
                DateTime rechnungsdatum = row.Field<DateTime>("RECHNUNGSDATUM");

                Artikel? artikel = await artikelService.GetAsync(wartung.Artikelnummer, fbController);
                if (artikel is not null)
                {
                    if (string.IsNullOrWhiteSpace(artikel.WartungsText))
                    {
                        await emailController.SendenAsync(TECHNIK_EMAIL, "Fehler beim anlegen der Wartung", $"Wartung konnte nicht angelegt werden da im Artikel {wartung.Artikelnummer} kein Wartungstext hinterlegt ist. Bitte einen Text hinterlegen, oder das Wartungsintervall im Artikel entfernen!");
                        logger.Error("Wartung konnte nicht angelegt werden da im Artikel {Artikelnummer} kein Wartungstext hinterlegt ist", wartung.Artikelnummer);
                        continue;
                    }

                    await wartungsService.CreateAsync(wartung, fbController);
                    logger.Information("Wartung {ID} wurde angelegt", wartung.WartungsNr);
                    await emailController.SendenAsync(TECHNIK_EMAIL, $"Wartung {wartung.WartungsNr} wurde angelegt", "Neue Wartung");

                    Kunde? kunde = await Kunde.GetKundeAsync(wartung.Kundennummer);
                    if (kunde is not null)
                    {
                        // 28.07.2022 - MK: E-Mails gehen nur noch an den Ansprechpartner. Wenn keiner gefunden wurde, dann gehen die an die Technik
                        string empfänger = String.Empty;

                        if (ansprechpartner is not null && !String.IsNullOrWhiteSpace(ansprechpartner.PART_A_EMAIL) && StringErweiterung.IstEmail(ansprechpartner.PART_A_EMAIL))
                        {
                            empfänger = ansprechpartner.PART_A_EMAIL;
                        }

                        if (String.IsNullOrWhiteSpace(empfänger))
                        {
                            await emailController.SendenAsync
                            (
                                TECHNIK_EMAIL,
                                $"Kunde konnte über anstehende Wartung {wartung.WartungsNr} nicht benachrichtigt werden",
                                $"E-Mail für Wartung {wartung.WartungsNr} konnte nicht gesendet werden, da im Kunden keine E-Mail Adresse hinterlegt ist. Bitte prüfen an wen die Wartung geschickt werden kann und manuell benachrichtigen und ggf. die E-Mailadresse im Kunden hinterlegen."
                            );
                            logger.Warning("E-Mail für Wartung {WartungsNummer} konnte nicht gesendet werden, da im Kunden keine E-Mail Adresse hinterlegt ist", wartung.WartungsNr);
                        }
                        else
                        {
                            string text = artikel.WartungsText
                                .Replace("{{ RECHNUNGSNUMMER }}", rechnungsnummer.ToString())
                                .Replace("{{ RECHNUNGSDATUM }}", rechnungsdatum.ToShortDateString())
                                .Replace("{{ ARTIKELNUMMER }}", wartung.Artikelnummer)
                                .Replace("{{ KUNDENNUMMER }}", wartung.Kundennummer)
                                .Replace("{{ SERIENNUMMER }}", wartung.Seriennummer);

                            text = $"{text}<br /><br />{GlobalConfig.Configuration.FirmenDaten.ImpressumHTML()}";
                            string betreff = $"Wartung {wartung.WartungsNr} (KD: {wartung.Kundennummer}) (SN: {wartung.Seriennummer})";
#if kleinTest
                            betreff = $"Wartung {wartung.WartungsNr} <{empfänger}>";
                            empfänger = TECHNIK_EMAIL;
#endif

                            var response = await emailController.SendenAsync(empfänger, betreff, text, null, absender);
                            if (response.Success)
                            {
                                wartung.Benachrichtigt = true;
                                await wartungsService.UpdateAsync(wartung, fbController);
                            }
                            else
                            {
                                logger.Error("Fehler beim Absenden der E-Mail an {Email}. Fehlermeldung: {Message}", empfänger, response.Message);
                            }

                        }
                    }
                    else
                    {
                        logger.Error("Kunde {Kundennummer} konnte nicht gefunden werden", wartung.Kundennummer);
                    }
                }
                else
                {
                    logger.Error("Artikel {Artikelnummer} konnte nicht gefunden werden", wartung.Artikelnummer);
                }


            }


            // Haben manuelle Wartungen das nächste Intervall erreicht?
        }


    }
}
