using KarleyLibrary.Erweiterungen;
using MbeSoap;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Toolbelt.Blazor.HotKeys;
using WK5.Core;
using WK5.Core.Basis;
using WK5.Core.Basis.Erweiterungen;
using WK5.Core.Basis.Filter;
using WK5.Core.Drucken.Bestellungen;
using WK5.Core.Drucken.Warenbegleitscheine;
using WK5.Core.Email;
using WK5.Core.Models;
using WK5.Core.PageModels.Einkauf.Bestellungen;
using WK5.Core.Validators.Bestellungen;

namespace WK5_Blazor.Pages.Bestellungen
{
    public partial class BestellungForm : IEditPage, IPipeline<Bestellung>, ITabPage<BestellungenTabs>
    {
        [Parameter] public int Bestellnummer { get; set; }
#nullable disable
        [CascadingParameter] public AppMitarbeiter Mitarbeiter { get; set; }
#nullable enable

        public Bestellposition? SelectedPosition { get; set; }
        private Lieferant? Lieferant { get; set; }
        public Bestellung Input { get; set; } = new Bestellung();
        public Bestellung StartCopy { get; set; } = new Bestellung();
        public BestellungenTabs ActiveTab { get; set; } = BestellungenTabs.Bestelldaten;
        public List<int> OffenerBedarf { get; set; } = new List<int>();
        public LieferantenFilter FilterLieferanten { get; set; } = new LieferantenFilter();
        public ArtikelFilter FilterArtikel { get; set; } = new ArtikelFilter()
        {
            NurArtikelVomLieferantenAnzeigen = true,
            NurArtikelMitLagerführung = true,
            ZeigeBundles = true
        };
        public BelegFilter FilterBelege { get; set; } = new BelegFilter()
        {
            BelegTyp = BelegTyp.Auftrag
        };

        /// <summary>
        /// Ruft die Funktion ab, die von der BelegSuche ausgeführt werden soll,
        /// </summary>
        public Func<Beleg, Task>? BelegSucheFunc { get; set; }


        private EditForm? _form;
        private bool _lädtHistorie;
        private bool _lädtAbrufe;
        private bool _isDownloading;
        private bool _showErledigenModal;
        private bool _showArtikelnummerSuchenModal;
        private bool _showLieferantenSucheModal;
        private bool _showBelegSucheModal;
        private bool _showPositionLieferterminÄndernModal;
        private bool _showMindestbestellwertUnterschrittenWarnung;
        private bool _mindermengenzuschlagConfirmed;
        private bool _showLieferantenInfoModal;
        private bool _showSonderartikelConfirmModal;
        private Artikelwerte? _artikelwerte;
        private Kunde? _kunde;
        private RecipientType? _lieferanschrift;
        private AnsprechpartnerLieferant[] _ansprechpartnerLieferant = Array.Empty<AnsprechpartnerLieferant>();
        private List<BelegChangeAnsicht> _historie = new List<BelegChangeAnsicht>();
        private DateTime _oldLiefertermin;
        private BestellungErledigtInput _erledigtInput = new BestellungErledigtInput();
        private BestellungErledigtInputValidator _erledigtValidator = new BestellungErledigtInputValidator();
        private BestellpositionValidator _posValidator = new BestellpositionValidator();
        private int _zähler = 0;
        private List<int> _zugangsnummern = new List<int>();
        private List<BestellungAbruf> _abrufe = new List<BestellungAbruf>();
        private BestellungAbruf? _neuerAbruf;
        private BestellungAbruf? _selectedAbruf;
        private BestellungAbrufPos? _selectedAbrufPos;
        private BestellungAbrufValidator _abrufValidator = new BestellungAbrufValidator();
        private EditForm? _abrufForm;
        private bool _abrufIsSaving;
        public BestellungForm()
        {
            _abrufValidator.Input = Input;
        }
        protected override async Task OnParametersSetAsync()
        {
            if (Bestellnummer > 0)
            {
                await LadeEditModeAsync();
            }

            if (Lieferant is null)
            {
                _showLieferantenSucheModal = true;
            }



            await SetAlerts();
            await SetupPipelineAsync();

            StartCopy = Input.DeepCopy();
        }

        #region Download & Mail
        private async Task DownloadBestellung()
        {
            _isDownloading = true;
            StateHasChanged(); // Wird für den Shortcut benötigt
            using FbController2 fbController = new FbController2();
            Bestellung? bestellung = await Bestellung.GetBestellungAsync(Bestellnummer, fbController);
            if (bestellung is not null)
            {
                PrintBestellung printBestellung = await PrintBestellung.CreateAsync(fbController, bestellung, Mitarbeiter.DisplayName);
                string filenameBestellung = printBestellung.Print(GlobalConfig.Configuration.OutputPfad);
                await downloadService.DownloadFile($"BE_{Bestellnummer}.pdf", await File.ReadAllBytesAsync(filenameBestellung), "application/pdf");
                if (bestellung.BEST_N_AB_NR > 0 && bestellung.Direktlieferung)
                {
                    Auftrag? auftrag = await Auftrag.GetAuftragAsync(bestellung.BEST_N_AB_NR, fbController);

                    if (auftrag is not null)
                    {
                        PrintWarenbegleitschein warenbegleitschein = await PrintWarenbegleitschein.CreateAsync(bestellung, null, fbController);
                        string filenameWarenbegleitschein = warenbegleitschein.Print(GlobalConfig.Configuration.OutputPfad);
                        await downloadService.DownloadFile($"WBS_{auftrag.Belegnummer}.pdf", await File.ReadAllBytesAsync(filenameWarenbegleitschein), "application/pdf");
                    }
                }

                await downloadService.ClearBuffers();
            }
            _isDownloading = false;
        }
        private async Task ÖffneMail()
        {
            if (Lieferant is null)
            {
                return;
            }

            using FbController2 fbController = new FbController2();
            var bestellung = await Bestellung.GetBestellungAsync(Bestellnummer, fbController);

            if (bestellung is not null)
            {
                var printBestellung = await PrintBestellung.CreateAsync(fbController, bestellung, Mitarbeiter.DisplayName);
                string filenameBestellung = printBestellung.Print(GlobalConfig.Configuration.OutputPfad);

                string empfängerEmail = String.Empty;
                var ansprechpartner = await AnsprechpartnerLieferant.GetAnsprechpartnerByNameAsync(bestellung.LieferantenId, bestellung.BEST_A_PARTNER);

                if (ansprechpartner is not null)
                {
                    if (!String.IsNullOrWhiteSpace(ansprechpartner.LIEP_A_EMAIL))
                    {
                        empfängerEmail = ansprechpartner.LIEP_A_EMAIL;
                    }
                }

                if (empfängerEmail == String.Empty)
                {
                    empfängerEmail = Lieferant.LIEF_A_EMAIL ?? String.Empty;
                }

                KarleyBrowserInterfaceEmail email = new KarleyBrowserInterfaceEmail
                {
                    Absender = GlobalConfig.EmailInfoEU,
                    Empfänger = empfängerEmail,
                    Content = await bestellung.GetEmailTextAsync(Mitarbeiter.DisplayName),
                    Betreff = $"Bestellung {Bestellnummer}"
                };

                email.Anhänge.Add(filenameBestellung);

                if (bestellung.BEST_N_AB_NR > 0 && bestellung.Direktlieferung && !bestellung.IstAbrufbestellung)
                {
                    Auftrag? auftrag = await Auftrag.GetAuftragAsync(bestellung.BEST_N_AB_NR, fbController);
                    if (auftrag is not null)
                    {
                        PrintWarenbegleitschein warenbegleitschein = await PrintWarenbegleitschein.CreateAsync(bestellung, null, fbController);
                        string filenameWarenbegleitschein = warenbegleitschein.Print(GlobalConfig.Configuration.OutputPfad);

                        email.Anhänge.Add(filenameWarenbegleitschein);
                    }
                }

                var (success, data, _) = KarleyLibrary.Serialization.XMLWriter.Serialize(email);
                if (success)
                {
                    string xmlFilename = $"{email.GetHashCode()}.xml";
                    await File.WriteAllTextAsync(Path.Combine(GlobalConfig.Configuration.OutputPfad, xmlFilename), data);
                    await jsRuntime.OpenNewTab($"karley:davidMail;{xmlFilename}");
                }


            }
        }
        private async Task ÖffneAbrufMailAsync(BestellungAbruf abruf)
        {
            if (Lieferant is null)
            {
                return;
            }

            using FbController2 fbController = new FbController2();
            var bestellung = await Bestellung.GetBestellungAsync(Bestellnummer, fbController);

            if (bestellung is not null)
            {
                if (string.IsNullOrWhiteSpace(bestellung.BEST_A_BESTAET_NR_LIEF))
                {
                    await jsRuntime.ShowToast(ToastType.error, "Es kann erst ein Abruf angefragt werden, wenn die Betsellung durch den Lieferant bestätigt worden ist.");
                    return;
                }




                string empfängerEmail = String.Empty;
                var ansprechpartner = await AnsprechpartnerLieferant.GetAnsprechpartnerByNameAsync(bestellung.LieferantenId, bestellung.BEST_A_PARTNER);

                if (ansprechpartner is not null)
                {
                    if (!String.IsNullOrWhiteSpace(ansprechpartner.LIEP_A_EMAIL))
                    {
                        empfängerEmail = ansprechpartner.LIEP_A_EMAIL;
                    }
                }

                if (empfängerEmail == String.Empty)
                {
                    empfängerEmail = Lieferant.LIEF_A_EMAIL ?? String.Empty;
                }

                KarleyBrowserInterfaceEmail email = new KarleyBrowserInterfaceEmail
                {
                    Absender = GlobalConfig.EmailInfoEU,
                    Empfänger = empfängerEmail,
                    Content = await bestellung.GetEmailTextFürAbrufAsync(Mitarbeiter.DisplayName, abruf, bestellung),
                    Betreff = $"Abruf für Bestellung {Bestellnummer}",
                };

                if (bestellung.Direktlieferung)
                {
                    PrintWarenbegleitschein printWarenbegleitschein = await PrintWarenbegleitschein.CreateAsync(bestellung, abruf, fbController);
                    string filenameWbs = printWarenbegleitschein.Print(GlobalConfig.Configuration.OutputPfad);
                    email.Anhänge.Add(filenameWbs);
                }

                var (success, data, _) = KarleyLibrary.Serialization.XMLWriter.Serialize(email);
                if (success)
                {
                    string xmlFilename = $"{email.GetHashCode()}.xml";
                    await File.WriteAllTextAsync(Path.Combine(GlobalConfig.Configuration.OutputPfad, xmlFilename), data);
                    await jsRuntime.OpenNewTab($"karley:davidMail;{xmlFilename}");
                }


            }
        }
        #endregion

        #region Speichern & Laden 

        private async Task SubmitAsync()
        {
            if ((Input.BEST_L_ERLEDIGT && !Mitarbeiter.IsAdmin) || SperreDurchAnderenUser || !Input.HasBeenModified(StartCopy))
            {
                return;
            }


            if (_form?.EditContext is not null)
            {
                if (_form.EditContext.Validate())
                {
                    Pipeline.Reset();
                    await Pipeline.RunUntilFailureAsync(Input);
                }
            }
        }
        private async Task SaveAsync()
        {
            if (Input.BEST_L_ERLEDIGT && !Mitarbeiter.IsAdmin)
            {
                return;
            }

            if (Lieferant is null)
            {
                return;
            }

            if (_form is null || _form.EditContext is null)
            {
                return;
            }

            if (_form.EditContext.Validate())
            {

                string message = String.Empty;
                using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
                await fbController.StartTransactionAsync();
                try
                {
                    if (Modus is EditMode.Anlage)
                    {
                        Bestellnummer = await bestellService.CreateBestellungAsync(Input, Mitarbeiter.PersonalNummer, fbController);
                        message = $"Bestellung {Bestellnummer} wurde angelegt.";
                    }
                    else
                    {
                        await bestellService.UpdateBestellungAsync(Input, Lieferant, Mitarbeiter.PersonalNummer, fbController, null);
                        message = $"Bestellung {Bestellnummer} wurde aktualisiert.";
                    }

                    if (_mindermengenzuschlagConfirmed)
                    {
                        await BelegChange.InsertBelegChangeAsync(fbController, new BelegChange
                        {
                            BCNG_A_BELEGTYP = "BE",
                            BCNG_N_BELEGNR = Bestellnummer.ToString(),
                            BCNG_N_ART = 130,
                            BCNG_A_WERTALT = "Bestätigt durch:",
                            BCNG_A_WERTNEU = Mitarbeiter.Username
                        });

                        _mindermengenzuschlagConfirmed = false;
                    }

                    await fbController.CommitChangesAsync();

                }
                catch (Exception)
                {
                    await fbController.RollbackChangesAsync();
                    throw;
                }




                await AddAlertAsync(new AlertBox
                {
                    AlertType = AlertType.Success,
                    Message = message,
                    DecayTime = 10
                });

                if(Modus is EditMode.Anlage)
                {
                    navigationManager.NavigateTo($"Bestellungen/{Bestellnummer}");
                }
                else
                {
                    await OnParametersSetAsync();
                }
            }
        }

        private async Task BestellungErledigenAsync()
        {
            if (Modus is not EditMode.Bearbeiten)
            {
                return;
            }

            using FbController2 fbController = new FbController2();

            foreach (var pos in Input.Positionen)
            {
                pos.BEPO_L_ERLEDIGT = true;
            }

            await SubmitAsync();
        }

        private async Task LadeHistorie()
        {
            _historie.Clear();
            _lädtHistorie = true;
            await foreach (var item in BelegChangeAnsicht.GetHistorieAsync("BE", Bestellnummer.ToString()))
            {
                _historie.Add(item);
                StateHasChanged();
            }

            _lädtHistorie = false;
        }
        private async Task LadeAbrufeAsync()
        {
            _lädtAbrufe = true;
            using FbController2 fbController = new FbController2();
            _abrufe = await bestellService.GetAbrufeAsync(Bestellnummer, fbController).ToListAsync();
            _lädtAbrufe = false;
        }
        #endregion
        #region Positionen Management
        private void RemovePosition(Bestellposition pos)
        {
            Input.Positionen.Remove(pos);
            _zähler--;

            for (int i = 0; i < _zähler; i++)
            {
                Input.Positionen[i].BEPO_N_POS = i + 1;
            }
            SelectedPosition = Input.Positionen.FirstOrDefault();
            CheckFrachtfrei();
        }
        private async Task AddPosition(string artikelnummer, decimal menge)
        {
            using FbController2 fbController = new FbController2();
            var artikel = await artikelService.GetAsync(artikelnummer, fbController);
            if (artikel is not null)
            {
                await AddPosition(artikel, menge);
            }
        }
        private async Task AddPosition(Artikel artikel, decimal menge = 0)
        {
            if (Lieferant is null)
            {
                return;
            }

            if (!artikel.ARTI_L_LAGERFUEHR)
            {
                await jsRuntime.ShowToast(ToastType.error, $"Der Artikel {artikel.Artikelnummer} kann nicht bestellt werden, da der Artikel keine Lagerführung hat.", 3000);
                return;
            }

            if (artikel.ARTI_L_INAKTIV)
            {
                await jsRuntime.ShowToast(ToastType.error, $"Der Artikel {artikel.Artikelnummer} kann nicht bestellt werden, da der Artikel inaktiv ist.", 3000);
                return;
            }

            if (artikel.IstBundle)
            {
                foreach (var subArtikel in artikel.BundleArtikel)
                {
                    await AddPosition(subArtikel, subArtikel.BUNDLE_N_MENGE);
                }

                await jsRuntime.ShowToast(ToastType.success, $"Die Artikel des Bundels {artikel.Artikelnummer} wurden erfolgreich in die Bestellung übernommen", 3000);
            }
            else
            {
                using FbController2 fbController = new FbController2();

                var lieferantenArtikel = await Lieferantenartikel.GetLieferantenartikelAsync(artikel.Artikelnummer, Input.LieferantenId, fbController);



                if (lieferantenArtikel is null && !artikel.Artikelnummer.Equals("DIVERS", StringComparison.OrdinalIgnoreCase))
                {
                    await jsRuntime.ShowToast(ToastType.error, $"Der Artikel {artikel.Artikelnummer} kann nicht durch den Lieferanten geliefert werden.", 3000);
                    return;
                }

                var position = new Bestellposition
                {
                    BEPO_N_POS = ++_zähler,
                    BEPO_A_ARTIKELNR = artikel.Artikelnummer
                };

                if (position.BEPO_A_ARTIKELNR.StartsWith("SO-"))
                {
                    // Bei Sonderproduktionen gehen wir von einem Liefertermin ab 4 Wochen aus
                    Input.BEST_D_LIEFTERMIN = DateTime.Now.AddDays(28);
                }

                if (lieferantenArtikel is not null)
                {
                    position.BEPO_A_BEZ1 = artikel.Bezeichnung1;
                    position.BEPO_A_BEZ2 = artikel.Bezeichnung2;
                    position.BEPO_A_BEZ3 = artikel.Bezeichnung3;
                    position.BEPO_A_BEZ4 = artikel.Bezeichnung4;
                    position.BEPO_A_BESTELLNUMMER = lieferantenArtikel.ARLI_A_BESTELLNR;
                    position.BEPO_N_MENGE = menge > 0 ? menge : lieferantenArtikel.ARLI_N_MINDESTABNAHME;
                    position.BEPO_N_PREIS = lieferantenArtikel.ARLI_N_PREIS;
                    position.BEPO_N_RABATTPROZ = lieferantenArtikel.ARLI_N_RABATT;
                    position.BEPO_N_RABATTPROZ2 = lieferantenArtikel.ARLI_N_RABATT2;
                    position.Mindestabnahme = lieferantenArtikel.ARLI_N_MINDESTABNAHME;
                    position.ARLI_L_NURVIELFACHES = lieferantenArtikel.ARLI_L_NURVIELFACHES;
                }
                else
                {
                    position.BEPO_N_MENGE = menge;
                }

                position.BEPO_N_MWSTPROZ = Lieferant.LIEF_L_MWST ? artikel.MWST_N_PROZENT : 0;
                _artikelwerte = await Artikelwerte.GetArtikelwertAsync(position.BEPO_A_ARTIKELNR, fbController);
                OffenerBedarf = await artikelService.GetBelegBedarf(position.BEPO_A_ARTIKELNR).ToListAsync();
                Input.Positionen.Add(position);
                SelectedPosition = position;
                _showArtikelnummerSuchenModal = false;

                CheckFrachtfrei();
            }
        }
        private Task AddTextAsync()
        {
            Bestellposition newPos = new Bestellposition
            {
                BEPO_A_ARTIKELNR = "TEXT",
                BEPO_N_MENGE = 0,
                BEPO_N_POS = ++_zähler,
                BEPO_L_ERLEDIGT = true
            };

            Input.Positionen.Add(newPos);

            return PositionSelected(newPos);
        }
        private Task MovePosition(Bestellposition pos, bool moveUp)
        {
            int posIndex = Input.Positionen.IndexOf(pos);
            int posNr = pos.BEPO_N_POS;
            int neuerPosIndex = -1;

            if (moveUp)
            {
                if (posIndex - 1 != -1)
                {
                    neuerPosIndex = posIndex - 1;
                }
            }
            else
            {
                if (posIndex + 1 != _zähler)
                {
                    neuerPosIndex = posIndex + 1;
                }
            }

            if (neuerPosIndex > -1)
            {
                var tmp = Input.Positionen[neuerPosIndex];
                Input.Positionen[neuerPosIndex] = pos;
                Input.Positionen[posIndex] = tmp;
                pos.BEPO_N_POS = tmp.BEPO_N_POS;
                tmp.BEPO_N_POS = posNr;
            }

            return Task.CompletedTask;
        }
        private async Task PositionSelected(Bestellposition? pos)
        {
            SelectedPosition = pos;

            if (SelectedPosition is not null)
            {
                using FbController2 fbController = new FbController2();
                _artikelwerte = await Artikelwerte.GetArtikelwertAsync(SelectedPosition.BEPO_A_ARTIKELNR, fbController);
                OffenerBedarf = await artikelService.GetBelegBedarf(SelectedPosition.BEPO_A_ARTIKELNR).ToListAsync();
            }
        }
        private async Task CheckForStaffelpreis(Bestellposition pos)
        {
            using FbController2 fbController = new FbController2();
            var lieferantenartikel = await Lieferantenartikel.GetLieferantenartikelAsync(pos.BEPO_A_ARTIKELNR, Input.LieferantenId, fbController);

            if (lieferantenartikel is not null)
            {
                pos.BEPO_N_PREIS = lieferantenartikel.GetPreis(pos.BEPO_N_MENGE);
                var (rabatt1, rabatt2) = lieferantenartikel.GetRabatte(pos.BEPO_N_MENGE);
                pos.BEPO_N_RABATTPROZ = rabatt1;
                pos.BEPO_N_RABATTPROZ2 = rabatt2;
            }

            CheckFrachtfrei();
        }

        #endregion
        #region Hilfsfunktionen
        #region Feldaktionen
        // Hier sind alle Funktionen drin, die ausgeführt werden, wenn ein Feld des Inputs durch den Benutzer verändert wird
        private Task BestätigtCheckedChangedAsync(bool value)
        {
            Input.BEST_L_BESTAETIGT = value;
            if (value)
            {
                Input.BEST_D_BESTAETIGT = DateTime.Now;

                if (Input.Positionen.Any(x => x.BEPO_A_ARTIKELNR.StartsWith("SO-")))
                {
                    _showSonderartikelConfirmModal = true;
                }
            }

            return Task.CompletedTask;
        }
        private Task VersendetCheckedChangedAsync(bool value)
        {
            Input.BEST_L_VERSENDET = value;
            if (value)
            {
                Input.BEST_D_VERSENDET = DateTime.Now;
            }

            return Task.CompletedTask;
        }
        private Task OnLieferterminFocusIn()
        {
            _oldLiefertermin = Input.BEST_D_LIEFTERMIN;
            return Task.CompletedTask;
        }
        private async Task AuftragsnummerFocusOut()
        {
            await FillKundendaten();
        }
        private Task OnLieferterminFocusOut()
        {
            if (_oldLiefertermin != Input.BEST_D_LIEFTERMIN && Input.Positionen.Count > 0)
            {
                _showPositionLieferterminÄndernModal = true;
            }

            return Task.CompletedTask;
        }
        private async Task DirektlieferungChanged(ChangeEventArgs e)
        {
            if (e.Value is null)
            {
                return;
            }

            if (e.Value is bool isChecked)
            {
                if (isChecked)
                {
                    if (Input.BEST_N_AB_NR <= 0)
                    {
                        BelegSucheFunc = OnAuftragSelected;
                        _showBelegSucheModal = true;
                    }
                    else
                    {
                        await FillKundendaten();
                    }
                }
                else
                {
                    Input.BEST_A_LIEFERKUNDE = String.Empty;
                    Input.BEST_A_LIEFERKUNDELA = 0;
                }
            }




        }
        #endregion
        private async Task LieferterminÜbernehmen()
        {
            foreach (var pos in Input.Positionen)
            {
                pos.BEPO_D_LIEFERDAT = Input.BEST_D_LIEFTERMIN;
            }

            await SubmitAsync();
        }
        private async Task FillKundendaten()
        {
            if (Input.BEST_N_AB_NR > 0)
            {
                using FbController2 fbController = new FbController2();
                Auftrag? auftrag = await Auftrag.GetAuftragAsync(Input.BEST_N_AB_NR, fbController);

                if (auftrag is not null)
                {
                    Input.BEST_A_LIEFERKUNDE = auftrag.Kundennummer;
                    Input.BEST_A_LIEFERKUNDELA = auftrag.LieferanschriftId;
                    _kunde = await Kunde.GetKundeAsync(auftrag.Kundennummer);
                    _lieferanschrift = await auftrag.ToRecipientTypeAsync(fbController);
                }
            }
            else
            {
                Input.BEST_A_LIEFERKUNDE = String.Empty;
                Input.BEST_A_LIEFERKUNDELA = 0;
                _lieferanschrift = null;
                _kunde = null;
            }
        }
        private void LieferantenSucheModalSchließen()
        {
            if (Modus == EditMode.Anlage && Lieferant is null)
            {
                navigationManager.NavigateTo("/Bestellungen");
            }

            _showLieferantenSucheModal = false;
        }
        private Task OnAuftragSelected(Beleg beleg)
        {
            Input.BEST_N_AB_NR = beleg.Belegnummer;
            _showBelegSucheModal = false;
            return Task.CompletedTask;
        }
        private async Task OnBelegSelected(Beleg beleg)
        {
            if (Lieferant is null)
            {
                return;
            }

            foreach (var pos in beleg.GetEndPositionen())
            {
                decimal menge = pos.Menge - pos.BPOS_N_MENGEGELIEF;
                var sucheArtikel = Input.Positionen.Where(x => x.BEPO_A_ARTIKELNR.Equals(pos.Artikelnummer, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                // Divers kann alles mögliche sein, daher können wir hier keine Mengen addieren
                if (sucheArtikel is not null && !pos.Artikelnummer.Equals("DIVERS", StringComparison.OrdinalIgnoreCase))
                {
                    sucheArtikel.BEPO_N_MENGE += menge;
                }
                else
                {
                    await AddPosition(pos.Artikelnummer, menge);
                }
            }


            _showBelegSucheModal = false;
        }
        private async Task SelectLieferant(Lieferant lieferant)
        {
            Lieferant = lieferant;
            FilterArtikel.LieferantenId = lieferant.LIEF_N_NR;
            Input.LieferantenId = lieferant.LIEF_N_NR;
            Input.BEST_N_ZAHLUNG = lieferant.LIEF_N_ZABD;
            Input.LieferbedingungId = lieferant.LIEF_N_LIBD;
            Input.Währung = lieferant.LIEF_A_WAEHRUNG;
            Input.Versicherungskosten = lieferant.LIEF_WK5_N_VERSICHERKOSTEN;
            Input.Verpackungskosten = lieferant.LIEF_WK5_N_VERPACKKOSTEN;
            Input.Versandkosten = lieferant.LIEF_WK5_N_VERSANDKOSTEN;
            _ansprechpartnerLieferant = await AnsprechpartnerLieferant.GetAnsprechpartnerAsync(lieferant.LIEF_N_NR).ToArrayAsync();
            var sucheHauptPartner = _ansprechpartnerLieferant.Where(x => x.LIEP_L_HAUPTPARTNER).FirstOrDefault();
            Input.BEST_A_PARTNER = sucheHauptPartner?.LIEP_A_NAME ?? String.Empty;

            foreach (var pos in Input.Positionen)
            {
                pos.Mindestabnahme = await bestellService.GetMindestbestellmenge(pos.BEPO_A_ARTIKELNR, Input.LieferantenId);
            }

            _showLieferantenSucheModal = false;

            if (!String.IsNullOrWhiteSpace(lieferant.WarnhinweisAsText))
            {
                _showLieferantenInfoModal = true;
            }
        }
        public string GetPositionNavListClass(Bestellposition pos)
        {
            if (!_posValidator.Validate(pos).IsValid)
            {
                return $"{GetSubNavListClass(SelectedPosition == pos)} bg-danger text-light";
            }

            if (pos.BEPO_N_MENGE > pos.BEPO_N_LIEFERMENGE)
            {
                return $"{GetSubNavListClass(SelectedPosition == pos)} bg-secondary text-light";
            }

            return GetSubNavListClass(SelectedPosition == pos);
        }
        private async Task MindestbestellwertUnterschrittenConfirmedAsync()
        {
            _mindermengenzuschlagConfirmed = true;
            await Pipeline.RunUntilFailureAsync(Input);
        }
        private bool CanMoveUp(Bestellposition pos) => Input.Positionen.IndexOf(pos) > 0;
        private bool CanMoveDown(Bestellposition pos) => Input.Positionen.IndexOf(pos) < _zähler - 1;
        private string GetBedarfPopOver()
        {
            string bedarf = "<ul>";
            foreach (int nr in OffenerBedarf)
            {
                bedarf += $"<li><a href='/Auftraege/{nr}' target='_blank'>AU-{nr}</a></li>";
            }

            bedarf += "</ul>";

            return bedarf;
        }
        private void CheckFrachtfrei()
        {
            if (Lieferant is not null && Lieferant.LIEF_N_FRACHTFR_AB > 0)
            {
                Input.BEST_L_FRACHTFREI = Lieferant.LIEF_N_FRACHTFR_AB <= Input.GetNettoBetrag();
            }
        }

        /// <summary>
        /// Prüft ob noch Positionen abgerufen werden können.
        /// </summary>
        /// <returns></returns>
        private bool IstAbrufMöglich()
        {
            // Wir gehen von der StartCopy aus, da im normalen Input noch Positionen hinzugefügt werden können
            var positionenMitMenge = StartCopy.Positionen
                .Where(x => x.BEPO_N_MENGE > 0) // Filtert Hilfspositionen wie z.B. TEXT raus
                .GroupBy(x => x.BEPO_A_ARTIKELNR)
                .Select(x => new { Artikelnummer = x.Key, Menge = x.Sum(pos => pos.BEPO_N_MENGE) })
                .ToDictionary(x => x.Artikelnummer);

            var abrufeMitMengen = _abrufe.SelectMany(x => x.Positionen)
                .GroupBy(x => x.Artikelnummer)
                .Select(x => new { Artikelnummer = x.Key, Menge = x.Sum(pos => pos.Menge) })
                .ToDictionary(x => x.Artikelnummer);

            // Wenn beide Dictionaries identisch sind, dann wurden ausreichend Abrufe aufgegeben, ansonsten können noch welche gemacht werden.
            return !positionenMitMenge.OrderBy(kvp => kvp.Key).SequenceEqual(abrufeMitMengen.OrderBy(kvp => kvp.Key));
        }
        #endregion
        #region Abrufe
        private Task NeuerAbrufAsync()
        {
            _neuerAbruf = new BestellungAbruf
            {
                Bestellnummer = Bestellnummer
            };

            _abrufValidator.Input = Input;

            return Task.CompletedTask;
        }

        private Task NeueAbrufPositionAsync(Bestellposition pos)
        {
            if (_neuerAbruf is not null)
            {
                var newPos = new BestellungAbrufPos
                {
                    Artikelnummer = pos.BEPO_A_ARTIKELNR,
                    PosId = pos.BEPO_N_POSID
                };
                _neuerAbruf.Positionen.Add(newPos);
                _selectedAbrufPos = newPos;
            }
            return Task.CompletedTask;
        }

        private bool AbrufContainsPosition(Bestellposition pos)
        {
            if (_neuerAbruf is null)
            {
                return false;
            }

            return _neuerAbruf.Positionen.Any(x => x.PosId == pos.BEPO_N_POSID);
        }

        private Task EditAbrufbestellungPosAsync(Bestellposition pos)
        {
            if (_neuerAbruf is not null)
            {
                _selectedAbrufPos = _neuerAbruf.Positionen.FirstOrDefault(x => x.PosId.Equals(pos.BEPO_N_POSID));
            }

            return Task.CompletedTask;
        }

        private Task SelectAbrufAsync(BestellungAbruf abruf)
        {
            if (_selectedAbruf == abruf)
            {
                _selectedAbruf = null;
            }
            else
            {
                _selectedAbruf = abruf;
            }

            return Task.CompletedTask;
        }

        private async Task SaveAbrufAsync()
        {
            if (_abrufForm is null || _abrufForm.EditContext is null || _neuerAbruf is null || _abrufIsSaving)
            {
                return;
            }

            _abrufIsSaving = true;

            if (_abrufForm.EditContext.Validate())
            {
                using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
                await bestellService.CreateAbrufAsync(_neuerAbruf, fbController);
                _abrufe.Add(_neuerAbruf);
                await jsRuntime.ShowToast(ToastType.success, "Abruf wurde erfolgreich angelegt");
                _neuerAbruf = null;
            }
            _abrufIsSaving = false;
        }
        #endregion
        #region Schnittstelle IEditPage
        public string ActivePageName => Modus switch
        {
            EditMode.Anlage => "Neue Bestellung",
            EditMode.Bearbeiten => $"BE-{Bestellnummer}",
            _ => "Unbekannt"
        };
        public string FinalBreadcrumbItemName => Modus switch
        {
            EditMode.Anlage => "Neu",
            EditMode.Bearbeiten => $"{Bestellnummer}",
            _ => "Unbekannt"
        };
        public EditMode Modus { get; set; } = EditMode.Anlage;
        public string GetNavListClass(bool active) => active ? "nav-link active" : "nav-link";
        public string GetTabClass(bool active) => active ? "tab-pane fade active show" : "tab-pane fade";
        public string GetSubNavListClass(bool active) => active ? "list-group-item list-group-item-action active" : "list-group-item list-group-item-action";

        public async Task LadeEditModeAsync()
        {
            Modus = EditMode.Bearbeiten;
            using FbController2 fbController = new FbController2();
            var bestellung = await Bestellung.GetBestellungAsync(Bestellnummer, fbController);
            if (bestellung is not null)
            {
                Input = bestellung;
                _zähler = Input.Positionen.Count;
                _ansprechpartnerLieferant = await AnsprechpartnerLieferant.GetAnsprechpartnerAsync(Input.LieferantenId).ToArrayAsync();
                Lieferant = await Lieferant.GetLieferantAsync(Input.LieferantenId);
                if (!String.IsNullOrWhiteSpace(bestellung.BEST_A_LIEFERKUNDE))
                {
                    _kunde = await Kunde.GetKundeAsync(bestellung.BEST_A_LIEFERKUNDE);

                    if (bestellung.BEST_N_AB_NR > 0)
                    {
                        Auftrag? auftrag = await Auftrag.GetAuftragAsync(bestellung.BEST_N_AB_NR, fbController);

                        if (auftrag is not null)
                        {
                            _lieferanschrift = await auftrag.ToRecipientTypeAsync(fbController);
                        }
                    }

                }
                FilterArtikel.LieferantenId = Lieferant?.LIEF_N_NR ?? 0;
                _zugangsnummern = await bestellService.GetZugangsnummernFürBestellungAsync(Bestellnummer, fbController).ToListAsync();
                // Wir laden hier nicht die Zusatzkosten von Lieferanten rein, da die für eine bestehende Bestellung bereits festgelegt sind.
                ActiveTab = BestellungenTabs.Bestelldaten;
                await PositionSelected(Input.Positionen.FirstOrDefault());
            }
            else
            {
                await AddAlertAsync(new AlertBox
                {
                    AlertType = AlertType.Danger,
                    Message = $"Bestellung {Bestellnummer} konnte nicht gefunden werden"
                });

                navigationManager.NavigateTo("/Bestellungen");
            }

            if (!_isDisposed)
            {
                await CheckActivePageAsync();
            }
        }
        #endregion

        #region Schnittstelle IPipeLine
        public Pipeline<Bestellung> Pipeline { get; set; } = new Pipeline<Bestellung>();
        public async Task SetupPipelineAsync()
        {
            Pipeline = new Pipeline<Bestellung>();
            await Pipeline.HardReset();

            Pipeline.Add((input) =>
            {
                decimal mindestbestellwert = Lieferant?.LIEF_N_MIDBESTWERT ?? 0;
                decimal mindermengenzuschlag = Lieferant?.Mindermengenzuschlag ?? 0;
                if (input.GetNettoBetrag() < mindestbestellwert)
                {
                    input.Mindermengenzuschlag = mindermengenzuschlag;
                    _showMindestbestellwertUnterschrittenWarnung = true;
                    return false;
                }

                input.Mindermengenzuschlag = 0;
                return true;
            });

            Pipeline.Add(async (input) =>
            {
                await SaveAsync();
                return true;
            });
        }
        #endregion

        #region Telefonieren
        public string ModalTelefonnummer { get; set; } = String.Empty;
        public bool _showTelefonnummerModal = false;
        public List<BestellungenTabs> EditOnlyTabs { get; set; } = new List<BestellungenTabs>
        {
            BestellungenTabs.Abrufe,
            BestellungenTabs.Historie
        };
        public List<BestellungenTabs> AdminOnlyTabs { get; set; } = new List<BestellungenTabs>();

        public Task Call(string? number)
        {
            if (number is not null)
            {
                ModalTelefonnummer = number;
                _showTelefonnummerModal = true;
                StateHasChanged();
            }

            return Task.CompletedTask;
        }


        #endregion

        public override async Task CheckActivePageAsync()
        {
            var (success, page) = ActivePages.AddActivePage(new ActivePage(PageType.Bestellung, Bestellnummer.ToString(), Mitarbeiter.PersonalNummer));

            if (success)
            {
                Page = page;
            }
            else
            {
                await AddAlertAsync(new AlertBox
                {
                    AlertType = AlertType.Danger,
                    Message = $"Die Bestellung wird zurzeit durch {Program.AppDaten.GetMitarbeiterName(page.UserId)} bearbeitet."
                });

                SperreDurchAnderenUser = true;
            }
        }

        public async Task OnTabChange(BestellungenTabs newActiveTab)
        {
            if (newActiveTab is BestellungenTabs.Historie)
            {
                await LadeHistorie();
            }
            else if (newActiveTab is BestellungenTabs.Abrufe)
            {
                await LadeAbrufeAsync();
            }
        }

        #region Hotkeys
        public override void AddHotKeys(HotKeysContext context)
        {
            context
                .Add(ModKeys.Alt, Keys.Insert, HandleCtrlPlus, "Alias für das Plus Symbol", Exclude.Default)
                .Add(ModKeys.Alt, Keys.S, SubmitAsync, "Speichert die Bestellung", Exclude.Default)
                .Add(ModKeys.Alt, Keys.Right, NextTab, "Wechselt zum nächsten Tab", Exclude.Default)
                .Add(ModKeys.Alt, Keys.Left, PrevTab, "Wechselt zum vorherigen Tab", Exclude.Default)
                .Add(ModKeys.Alt, Keys.E, async () =>
                {
                    if (Modus is EditMode.Bearbeiten)
                    {
                        await ÖffneMail();
                    }

                }, "Öffnet die Bestellung als Email", Exclude.Default)
                .Add(ModKeys.Alt, Keys.D, async () =>
                {
                    if (Modus is EditMode.Bearbeiten)
                    {
                        await DownloadBestellung();
                        StateHasChanged();
                    }

                }, "Lädt die Bestellung herunter", Exclude.Default)
                .Add(ModKeys.Alt, Keys.T, async () =>
                {
                    if (ActiveTab is BestellungenTabs.Positionen)
                    {
                        await AddTextAsync();
                        StateHasChanged();
                    }
                }, "Fügt eine Textposition hinzu", Exclude.Default)
                .Add(ModKeys.Alt, Keys.PgUp, async () =>
                {
                    if (ActiveTab is BestellungenTabs.Positionen && !Input.BEST_L_ERLEDIGT)
                    {
                        await Move(true);
                        StateHasChanged();
                    }
                }, "Bewegt die aktuelle Position einen nach oben", Exclude.Default)
                .Add(ModKeys.Alt, Keys.PgDown, async () =>
                {
                    if (ActiveTab is BestellungenTabs.Positionen && !Input.BEST_L_ERLEDIGT)
                    {
                        await Move(false);
                        StateHasChanged();
                    }
                }, "Bewegt die aktuelle Position einen nach unten", Exclude.Default)
                .Add(ModKeys.None, Keys.PgUp, async () =>
                {
                    if (ActiveTab is BestellungenTabs.Positionen)
                    {
                        await Select(true);
                        StateHasChanged();
                    }
                }, "Wählt die nächste Position aus", Exclude.Default)
                .Add(ModKeys.None, Keys.PgDown, async () =>
                {
                    if (ActiveTab is BestellungenTabs.Positionen)
                    {
                        await Select(false);
                        StateHasChanged();
                    }
                }, "Bewegt die aktuelle Position einen nach oben aus", Exclude.Default)
                ;
        }

        public Task NextTab()
        {
            bool found = false;
            int tabIndex = ((int)ActiveTab + 1) % Enum.GetValues(typeof(BestellungenTabs)).Length;
            while (!found)
            {
                BestellungenTabs tab = (BestellungenTabs)tabIndex;
                if (EditOnlyTabs.Contains(tab) && Modus != EditMode.Bearbeiten)
                {
                    tabIndex = (tabIndex + 1) % Enum.GetValues(typeof(BestellungenTabs)).Length;
                    continue;
                }

                if (AdminOnlyTabs.Contains(tab) && !Mitarbeiter.IsAdmin)
                {
                    tabIndex = (tabIndex + 1) % Enum.GetValues(typeof(BestellungenTabs)).Length;
                    continue;
                }

                if (tab is BestellungenTabs.Abrufe && !Input.IstAbrufbestellung)
                {
                    tabIndex = (tabIndex + 1) % Enum.GetValues(typeof(BestellungenTabs)).Length;
                    continue;
                }

                found = true;
            }

            ActiveTab = (BestellungenTabs)tabIndex;
            StateHasChanged();
            return Task.CompletedTask;
        }

        public Task PrevTab()
        {
            bool found = false;
            int tabIndex = (int)ActiveTab - 1 < 0 ? Enum.GetValues(typeof(BestellungenTabs)).Length - 1 : (int)ActiveTab - 1;
            while (!found)
            {
                BestellungenTabs tab = (BestellungenTabs)tabIndex;
                if (EditOnlyTabs.Contains(tab) && Modus != EditMode.Bearbeiten)
                {
                    tabIndex = tabIndex - 1 < 0 ? Enum.GetValues(typeof(BestellungenTabs)).Length - 1 : tabIndex - 1;
                    continue;
                }

                if (AdminOnlyTabs.Contains(tab) && !Mitarbeiter.IsAdmin)
                {
                    tabIndex = tabIndex - 1 < 0 ? Enum.GetValues(typeof(BestellungenTabs)).Length - 1 : tabIndex - 1;
                    continue;
                }

                if (tab is BestellungenTabs.Abrufe && !Input.IstAbrufbestellung)
                {
                    tabIndex = tabIndex - 1 < 0 ? Enum.GetValues(typeof(BestellungenTabs)).Length - 1 : tabIndex - 1;
                    continue;
                }

                found = true;
            }

            ActiveTab = (BestellungenTabs)tabIndex;
            StateHasChanged();
            return Task.CompletedTask;
        }

        public Task HandleCtrlPlus()
        {
            switch (ActiveTab)
            {
                case BestellungenTabs.Positionen:
                    if (!Input.BEST_L_ERLEDIGT)
                    {
                        _showArtikelnummerSuchenModal = true;
                        StateHasChanged();
                    }
                    break;
                default:
                    break;
            }
            return Task.CompletedTask;
        }

        public async Task Move(bool moveUp)
        {
            if (SelectedPosition is not null)
            {
                if (moveUp && CanMoveUp(SelectedPosition))
                {
                    await MovePosition(SelectedPosition, moveUp);
                }
                else if (!moveUp && CanMoveDown(SelectedPosition))
                {
                    await MovePosition(SelectedPosition, moveUp);
                }
            }
        }

        public Task Select(bool moveUp)
        {
            if (SelectedPosition is not null)
            {
                int max = Input.Positionen.Last().BEPO_N_POS;
                int newPos = moveUp ? SelectedPosition.BEPO_N_POS - 1 : SelectedPosition.BEPO_N_POS + 1;
                if (moveUp)
                {

                    if (newPos < 1)
                    {
                        newPos = max;
                    }
                }
                else
                {
                    if (newPos > max)
                    {
                        newPos = 1;
                    }

                }

                var pos = Input.Positionen.FirstOrDefault(x => x.BEPO_N_POS == newPos);

                if (pos is not null)
                {
                    return PositionSelected(pos);
                }
                else
                {
                    return PositionSelected(Input.Positionen.FirstOrDefault());
                }
            }

            return Task.CompletedTask;
        }

        private async Task OpenPreviewWindow()
        {
            await jsRuntime.InvokeAsync<object>("open", new object[] { $"/Bestellung/Vorschau/{Bestellnummer}/{Mitarbeiter.PersonalNummer}", $"popout-{Bestellnummer}", "scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,width=0,height=0,left=-1000,top=-1000" });
        }
        #endregion


    }
}
