using KarleyLibrary.Erweiterungen;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using WK5.Core;
using WK5.Core.Basis;
using WK5.Core.Basis.Erweiterungen;
using WK5.Core.Models;
using WK5.Core.PageModels;
using WK5.Core.PageModels.Stammdaten.Kunden;
using WK5.Core.Validators.Stammdaten.Kunden;
using WK5.Core.Services;
using WK5_Blazor.CoreExtensions;
using WK5.Core.Basis.Filter;
using System.Data;
using System.Diagnostics;
using System.IO;
using WK5.Core.Models.VatChecker;
using Toolbelt.Blazor.HotKeys;

namespace WK5_Blazor.Pages.Stammdaten.Kunden
{
    public partial class KundenForm : IEditPage, ITabView<KundenTabs>, IPipeline<KundeInput>,  IAsyncDisposable, ITabPage<KundenTabs>
    {
#nullable disable
        [CascadingParameter] public AppMitarbeiter Mitarbeiter { get; set; }
        
#nullable enable
        [Parameter] public int Kundennummer { get; set; }
        public KundenTabs ActiveTab { get; set; } = KundenTabs.Allgemein;


        public string ActivePageName => Modus switch
        {
            EditMode.Anlage => "Kundenanlage",
            EditMode.Bearbeiten => $"Kunde {Kundennummer}{(!String.IsNullOrWhiteSpace(Input.Firma) ? $" ({Input.Firma})" : String.Empty)}",
            _ => "Unbekannt"
        };
        public List<KundenrabattInput> Kundenrabatte { get; } = new List<KundenrabattInput>();
        public EditMode Modus { get; set; } = EditMode.Anlage;
        public string FinalBreadcrumbItemName => Modus switch
        {
            EditMode.Anlage => "Neu",
            EditMode.Bearbeiten => $"{Kundennummer}",
            _ => "Unbekannt"
        };

        public ZeitenFilter FilterZeiterfassung { get; set; } = new ZeitenFilter
        {
            Option = ZeitenFilterOption.Kunde
        };

        private async Task UstIdManuellBestätigenAsync()
        {
            if (Input.Land != "DE")
            {
                Input.MwstBerechnen = false;
                bool useCustomAddress = !String.IsNullOrWhiteSpace(Input.UstIdFirma);
                VatRequest vatRequest = new VatRequest
                (
                    Input.UstId ?? String.Empty,
                    useCustomAddress ? Input.UstIdFirma : Input.Firma,
                    useCustomAddress ? Input.UstIdOrt : Input.Ort,
                    useCustomAddress ? Input.UstIdPostleitzahl : Input.Postleitzahl,
                    useCustomAddress ? Input.UstIdStrasse : Input.Strasse,
                    Input.Kundennummer ?? "Keine Kundennummer angegeben",
                    false,
                    VatZuordnung.Kunde,
                    0
                );

                using FbController2 fbController = new FbController2();
                await vatService.UpdateZuordnungAsync(vatRequest, true, fbController);
            }
        }

        private bool IstZahlungsBedingungDisabled(Zahlungsbedingung zahlungsbedingung)
        {
            if (!zahlungsbedingung.ZABD_L_ABBUCHUNG)
            {
                return false;
            }

            if ((String.IsNullOrWhiteSpace(Input.IBAN) || !StringErweiterung.ValidateIBAN(Input.IBAN)) &&
                (String.IsNullOrWhiteSpace(Input.BIC) || !StringErweiterung.ValidateBIC(Input.BIC)) &&
                (Input.MandatsAusstellungsdatum == default))
            {
                return true;
            }

            return false;
        }
        private KundeInput Input { get; set; } = new KundeInput();
        private KundeInput StartCopy { get; set; } = new KundeInput();
        private List<BelegChangeAnsicht> Historie { get; set; } = new List<BelegChangeAnsicht>();
        private CancellationTokenSource _ctsHistorie = new CancellationTokenSource();
        private CancellationTokenSource _ctsGesamtUmsatz = new CancellationTokenSource();
        private bool _lädtHistorie;
        private bool _kundeExists = false;
        private bool _showÄhnlicheKundenModal;
        private VatCheck? _vatResult;
        private bool _showVatModal;
        private List<Kunde> _ähnlicheKunden = new List<Kunde>();
        private Kunde? _kunde;
        private bool _showUstIdManuellBestätigenModal;
        private List<FileInfo> _dokumentenablage = new List<FileInfo>();
        private EditForm? _form;
        public bool _showDeleteMeldung;
        public bool _deleteConfirmMeldung;        
        private bool _showSeriennummernModal;
        private bool _showZeiterfassungModal;
        private bool Gesperrt { get; set; }


        public bool _showKundenrabatteModal { get; set; } = false;


        public KundenBelegeFilter KundenBelegeFilter { get; set; } = new KundenBelegeFilter();

        public Pipeline<KundeInput> DeletePipeline { get; set; } = new Pipeline<KundeInput>();

        public string DeleteMeldungMarkup { get; set; } = String.Empty;
        
        private async Task SetupDeletePipelineAsync()
        {
            await DeletePipeline.HardReset();

            DeletePipeline.Add(async (input) =>
            {
                string sql = "SELECT BELE_A_TYP,BELE_N_NR FROM BELEGE WHERE BELE_A_TYP IN ('AU','LS','RE','GU') AND BELE_A_KUNDENNR = @KUNDNR";

                using FbController2 fbController = new FbController2();
                fbController.AddParameter("@KUNDNR", input.Kundennummer);

                DataTable data = await fbController.SelectDataAsync(sql);


                if (data.Rows.Count > 0)
                {
                    DeleteMeldungMarkup = $"<span>Kunde kann nicht gelöscht werden da er noch in {data.Rows.Count} Belegen vorhanden ist:</span><br/><ul>";
                    foreach (DataRow row in data.Rows)
                    {
                        DeleteMeldungMarkup += $"<li><a href=\"{EnumHelper.GetBelegUrl(row.Field<string>("BELE_A_TYP"), row.Field<int>("BELE_N_NR"))}\" target=\"_blank\">{row.Field<string>("BELE_A_TYP")}-{row.Field<int>("BELE_N_NR")}</a></li>";
                    }
                    DeleteMeldungMarkup += "</ul>";
                    _showDeleteMeldung = true;
                    return false;
                }
                else
                {
                    return true;
                }
            });

            DeletePipeline.Add(async (input) =>
            {
                DateTime olderThan = new DateTime(DateTime.Now.Year - 8, 12, 31);

                string sql = "SELECT BELE_A_TYP, BELE_N_NR FROM BELEGE WHERE BELE_D_DATE > @DATE AND BELE_A_KUNDENNR = @KUNDNR AND BELE_A_TYP = @TYP";

                using FbController2 fbController = new FbController2();
                fbController.AddParameter("@DATE", olderThan);
                fbController.AddParameter("@KUNDNR", input.Kundennummer);
                fbController.AddParameter("@TYP", "AN");

                DataTable data = await fbController.SelectDataAsync(sql);

                if (data.Rows.Count > 0)
                {
                    DeleteMeldungMarkup = "<span>Kunde kann nicht gelöscht werden da es Angebote gibt die jünger als 8 Jahre zum Jahresende sind:</span><br/><ul>";
                    foreach (DataRow row in data.Rows)
                    {
                        DeleteMeldungMarkup += $"<li><a href=\"{EnumHelper.GetBelegUrl(row.Field<string>("BELE_A_TYP"), row.Field<int>("BELE_N_NR"))}\" target=\"_blank\">{row.Field<string>("BELE_A_TYP")}-{row.Field<int>("BELE_N_NR")}</a></li>";
                    }
                    DeleteMeldungMarkup += "</ul>";
                    _showDeleteMeldung = true;
                    return false;
                }
                else
                {
                    return true;
                }
            });
            DeletePipeline.Add((input) =>
            {
                _deleteConfirmMeldung = true;
                return false;
            });
            DeletePipeline.Add(async (input) =>
            {
                using FbController2 fbController = new FbController2();
                await fbController.StartTransactionAsync();

                try
                {
                    await Kunde.DeleteKundeAsync(Input.Kundennummer, fbController);
                    await fbController.CommitChangesAsync();

                    await AddAlertAsync(new AlertBox()
                    {
                        AlertType = AlertType.Success,
                        Message = $"Der Kunde {Input.Kundennummer} wurde erfolgreich gelöscht"
                    });
                    navigationManager.NavigateTo("/Kunden");
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex);
                    await fbController.RollbackChangesAsync();
                    throw;
                }
                return true;
            });
        }

        public override void AddHotKeys(HotKeysContext context)
        {
            context
                .Add(ModKeys.Alt, Keys.S, Submit, "Speichert den Kunden", Exclude.Default)
                .Add(ModKeys.Alt, Keys.B, () => { _showKundenBelegeModal = true; StateHasChanged(); }, "Öffnet die Kundenbelege", Exclude.Default)
                .Add(ModKeys.Alt, Keys.Insert, HandleCtrlPlus, "Alias für das Plus Symbol", 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.H, () => { _showKundenArtikelHistorieModal = true; StateHasChanged(); }, "Öffnet die Kundenartikelhistorie", Exclude.Default)
            ;
        }

        protected override async Task OnParametersSetAsync()
        {
            if (Kundennummer > 0)
            {
                await LadeEditModeAsync();

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

            await SetupPipelineAsync();
            await SetupDeletePipelineAsync();
            await SetAlerts();

            StartCopy = Input.DeepCopy();

#if DEBUG
            // Zum testen der Kundenanlage
            //if (Modus is EditMode.Anlage)
            //{
            //    Input.Firma = "BHM INGENIEURE – Engineering & Consulting GmbH";
            //    Input.Land = "AT";
            //    Input.Postleitzahl = "6800";
            //    Input.Ort = "Feldkirch";
            //    Input.Strasse = "Runastrasse 90";
            //    Input.Telefon1 = "+43 5522 46101 247";
            //    Input.Handy = "+43 664 88692247";
            //    Input.Email = "thomas.nesensohn@bhm-ing.com";
            //    Input.Homepage = "bhm-ing.com";
            //}
#endif
        }

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

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

                SperreDurchAnderenUser = true;
            }
        }

        #region Laden
        public async Task LoadHistorie()
        {
            _ctsHistorie.Cancel();
            _ctsHistorie = new CancellationTokenSource();
            _lädtHistorie = true;
            Historie.Clear();
            await foreach (var item in BelegChangeAnsicht.GetHistorieAsync("KU", Kundennummer.ToString()))
            {
                Historie.Add(item);
                StateHasChanged();
            }
            _lädtHistorie = false;
        }

        public async Task LoadKontakte()
        {
            
        
        }

        #endregion
        #region Speichern
        private async Task SubmitForm()
        {
            switch (Modus)
            {
                case EditMode.Anlage:
                    await CreateKundeAsync();
                    break;
                case EditMode.Bearbeiten:
                    await UpdateKundeAsync();
                    break;
                default:
                    break;
            }
        }
        private async Task UpdateKundeAsync()
        {
            if (String.IsNullOrWhiteSpace(Input.Kundennummer))
            {
                throw new ArgumentException();
            }

            await Kunde.UpdateKundeAsync(Input.ToKunde(Program.AppDaten.Länder), Mitarbeiter.PersonalNummer);

            using FbController2 fbController = new FbController2();


            // Wir löschen erst die Lieferanschrift, die nicht mehr exitieren.
            // Das wurde extra so gelöst, weil die Methode zum löschen der Lieferanschrift noch zusätzlich prüft, ob eine Anschrift gelöscht werden darf oder nicht
            List<int>? nummernVorhanden = await Lieferanschrift.GetLieferanschriftenAsync(Input.Kundennummer).Select(x => x.KULA_N_NR).ToListAsync();
            if (nummernVorhanden != null)
            {
                var nummernNeu = Input.Lieferanschriften.Where(x => x.Nummer > -1).Select(x => x.Nummer).ToList();
                int maxAnschrift = nummernVorhanden.Any() ? nummernVorhanden.Max() : 0;


                foreach (var nummer in nummernNeu.Any() ? HashSetErweiterung.FindeFehlendeNummern(nummernNeu, maxAnschrift) : nummernVorhanden)
                {
                    bool wurdeGelöscht = await Lieferanschrift.DeleteLieferanschriftAsync(Input.Kundennummer, nummer);
                    if (!wurdeGelöscht)
                    {
                        await AddAlertAsync(new AlertBox
                        {
                            AlertType = AlertType.Danger,
                            Message = $"Die Lieferanschrift {nummer} konnte nicht gelöscht werden, da Sie in Belegen vorhanden ist."
                        });
                    }
                }
            }

            // Jetzt können wir Lieferanschriften anlegen
            bool keineHauptLieferanschrift = true;
            foreach (var anschrift in Input.Lieferanschriften)
            {
                var anschriftUpdated = anschrift.Nummer == -1
                    ? await Lieferanschrift.CreateLieferanschriftAsync(anschrift.ToLieferanschrift(), Mitarbeiter.PersonalNummer)
                    : await Lieferanschrift.UpdateLieferanschriftAsync(anschrift.ToLieferanschrift(), Mitarbeiter.PersonalNummer);

                if (anschrift.Hauptanschrift)
                {
                    keineHauptLieferanschrift = false;
                }
            }

            if (keineHauptLieferanschrift)
            {
                await Lieferanschrift.SetHauptanschriftAsync(0, Input.Kundennummer, Mitarbeiter.PersonalNummer);
            }

            // Wir löschen erst die Rechnungsanschrift, die nicht mehr exitieren
            nummernVorhanden = await Rechnungsanschrift.GetRechnungsanschriftenAsync(Input.Kundennummer).Select(x => x.KURE_N_NR).ToListAsync();
            if (nummernVorhanden != null)
            {
                var nummernNeu = Input.Rechnungsanschriften.Where(x => x.Nummer > -1).Select(x => x.Nummer).ToList();
                int maxAnschrift = nummernVorhanden.Any() ? nummernVorhanden.Max() : 0;

                foreach (var nummer in nummernNeu.Any() ? HashSetErweiterung.FindeFehlendeNummern(nummernNeu, maxAnschrift) : nummernVorhanden)
                {
                    bool wurdeGelöscht = await Rechnungsanschrift.DeleteRechnungsanschriftAsync(Input.Kundennummer, nummer, Mitarbeiter.PersonalNummer);
                    if (!wurdeGelöscht)
                    {
                        await AddAlertAsync(new AlertBox { AlertType = AlertType.Danger, Message = $"Die Rechnungsanschrift {nummer} konnte nicht gelöscht werden, da Sie in Belegen vorhanden ist." });
                    }
                }
            }

            // Jetzt können wir Rechnungsanschriften anlegen
            bool keineHauptRechnungsanschrift = true;
            foreach (var anschrift in Input.Rechnungsanschriften)
            {
                var anschriftUpdated = anschrift.Nummer == -1
                    ? await Rechnungsanschrift.CreateRechnungsanschriftAsync(anschrift.ToRechnungsanschrift(), Mitarbeiter.PersonalNummer)
                    : await Rechnungsanschrift.UpdateRechnungsanschriftAsync(anschrift.ToRechnungsanschrift(), Mitarbeiter.PersonalNummer);

                if (anschrift.Hauptanschrift)
                {
                    keineHauptRechnungsanschrift = false;
                }
            }

            if (keineHauptRechnungsanschrift)
            {
                await Rechnungsanschrift.SetHauptanschriftAsync(0, Input.Kundennummer, Mitarbeiter.PersonalNummer);
            }

            await Kunde.UpdateParsedTelefonnummern(Input.Kundennummer);



            await AddAlertAsync(new AlertBox
            {
                AlertType = AlertType.Success,
                Message = "Kunde wurde erfolgreich gespeichert.",
                DecayTime = 10
            });


            await OnParametersSetAsync();

        }
        private async Task CreateKundeAsync()
        {
            Kunde? kunde = null;
            try
            {
                kunde = await Kunde.CreateKundeAsync(Input.ToKunde(Program.AppDaten.Länder), Mitarbeiter.PersonalNummer);
            }
            catch (IndexOutOfRangeException ex)
            {
                await AddAlertAsync(new AlertBox
                {
                    AlertType = AlertType.Danger,
                    Message = "Es sind keine freien Kundennummern mehr verfügbar"
                });
                navigationManager.NavigateTo($"/Kunden");
                return;
            }


            foreach (var anschrift in Input.Lieferanschriften)
            {
                anschrift.Kundennummer = kunde.KUND_A_NR;
                await Lieferanschrift.CreateLieferanschriftAsync(anschrift.ToLieferanschrift(), Mitarbeiter.PersonalNummer);
            }

            foreach (var anschrift in Input.Rechnungsanschriften)
            {
                anschrift.Kundennummer = kunde.KUND_A_NR;
                await Rechnungsanschrift.CreateRechnungsanschriftAsync(anschrift.ToRechnungsanschrift(), Mitarbeiter.PersonalNummer);
            }

            await Kunde.UpdateParsedTelefonnummern(kunde.KUND_A_NR);

            await AddAlertAsync(new AlertBox { AlertType = AlertType.Success, Message = "Kunde wurde erfolgreich angelegt" });
            navigationManager.NavigateTo($"/Kunden/{kunde.KUND_A_NR}");
        }
        private async Task Submit()
        {
            if (SperreDurchAnderenUser || !Input.HasBeenModified(StartCopy)) return;

            if (_form?.EditContext is not null)
            {

                if (_form.EditContext.Validate())
                {
                    Pipeline.Reset();
                    await Pipeline.RunUntilFailureAsync(Input);
                    //await SubmitForm();
                }
            }
        }
        #endregion
        #region Weiteres
        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";
        private void ZurückZurKundenübersicht() => navigationManager.NavigateTo("/Kunden");
        private async Task BtnVatCheck_Click()
        {
            if (String.IsNullOrWhiteSpace(Input.Kundennummer))
            {
                await jsRuntime.ShowToast(ToastType.error, "Der Kunde muss zuerst gespeichert werden, bevor eine Prüfung der Ust.Id möglich ist");
                return;
            }

            try
            {
                var result = await Input.PrüfeUstIdAsync(vatService);
                await AutoCompleteMwstAsync();
                _vatResult = result;
                _showVatModal = true;
            }
            catch (Exception ex)
            {
                await jsRuntime.ShowToast(ToastType.error, ex.Message);
            }
        }
        #endregion

        #region Validation
        private AnsprechpartnerInputValidator _partValidator = new AnsprechpartnerInputValidator();
        private LieferanschriftInputValidator _liefValidator = new LieferanschriftInputValidator();
        private RechnungsanschriftInputValidator _rechValidator = new RechnungsanschriftInputValidator();
        #endregion

        private async Task ShowKundenrabatte()
        {
            if (String.IsNullOrWhiteSpace(Input.Kundennummer))
            {
                return;
            }

            Kundenrabatte.Clear();
            _showKundenrabatteModal = true;
            await foreach (Kundenrabatt sachnummer in Kundenrabatt.GetKundensachnummernAsync(Input.Kundennummer))
            {
                Kundenrabatte.Add(await sachnummer.ToInputAsync());
            }
        }

        public bool _showKundenArtikelHistorieModal { get; set; }
        public bool _showEmpfohlenVonKundenSuche { get; set; }

        private bool _showUstIdModalWarnung { get; set; }

        private async Task KundenHistorieZuSachnummerÜbernahme(KundenArtikelHistorie historie)
        {
            if (Kundenrabatte.Where(x => x.Artikelnummer.Equals(historie.Artikelnummer, StringComparison.OrdinalIgnoreCase)).Any())
            {
                KundenrabattInput input = Kundenrabatte.Where(x => x.Artikelnummer.Equals(historie.Artikelnummer, StringComparison.OrdinalIgnoreCase)).First();
                input.Preis = historie.Preis;
            }
            else
            {
                using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
                Artikel? artikel = await artikelService.GetAsync(historie.Artikelnummer, fbController);
                if (artikel is null)
                {
                    return;
                }
                Kundenrabatte.Add(new KundenrabattInput(true, artikel.GetBezeichnung())
                {
                    Artikelnummer = historie.Artikelnummer,
                    ZeitlichBegrenzen = false,
                    Artikelpreis = artikel.ARTI_N_VK1,
                    Preis = historie.Preis,
                    Kundennummer = Input.Kundennummer ?? String.Empty,
                });
            }
            _showKundenArtikelHistorieModal = false;
            _showKundenrabatteModal = true;
            StateHasChanged();
        }

        public async Task SetupPipelineAsync()
        {
            Pipeline = new Pipeline<KundeInput>();
            await Pipeline.HardReset();

            if (Modus is EditMode.Anlage)
            {
                Pipeline.Add((input) =>
                {
                    if (Input.Land != "DE" && Program.AppDaten.Länder.Any(x => x.WK5_LAND_L_ISTEULAND && x.LAND_A_ID == Input.Land) && String.IsNullOrWhiteSpace(Input.UstId))
                    {
                        // Modal 
                        _showUstIdModalWarnung = true;
                        return false;
                    }

                    return true;
                });

                Pipeline.Add(async (input) =>
                {
                    _ähnlicheKunden = await kundenService.GetÄhnlicheKundenAsync(Input.ToKunde(Program.AppDaten.Länder)).ToListAsync();

                    if (_ähnlicheKunden.Any())
                    {
                        _showÄhnlicheKundenModal = true;
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                });
            }

            Pipeline.Add(async (input) =>
            {
                await SubmitForm();
                return true;
            });
        }

        public int UmsatzJahre { get; set; } = 4;
        public Dictionary<int, Jahresumsatz> Umsatzdaten { get; set; } = new Dictionary<int, Jahresumsatz>();
        public Dictionary<int, Jahresumsatz> GeworbeneKundenUmsatz { get; set; } = new Dictionary<int, Jahresumsatz>();
        public List<string> GeworbeneKunden { get; set; } = new List<string>();
        public async Task LadeUmsatz()
        {
            Umsatzdaten = new Dictionary<int, Jahresumsatz>();
            if (_kunde is null)
            {
                return;
            }
            for (int i = 0; i < UmsatzJahre; i++)
            {
                if (!Umsatzdaten.ContainsKey(i))
                {
                    Umsatzdaten.Add(i, await kundenService.GetKundenJahresUmsatzAsync(_kunde.KUND_A_NR, DateTime.Now.Year - i));
                }
            }

            GeworbeneKunden = await Kunde.GetGeworbeneKunden(_kunde.KUND_A_NR).ToListAsync();

            if (GeworbeneKunden.Count > 0)
            {
                GeworbeneKundenUmsatz = new Dictionary<int, Jahresumsatz>();
                for (int i = 0; i < UmsatzJahre; i++)
                {
                    if (!GeworbeneKundenUmsatz.ContainsKey(i))
                    {
                        GeworbeneKundenUmsatz.Add(i, Jahresumsatz.FromList(await kundenService.GetGeworbeneKundenJahresumsätze(_kunde.KUND_A_NR, DateTime.Now.Year - i).ToListAsync()));
                    }
                }
            }
        }

        private bool _gesamtUmsatzGeladen = false;
        private bool _ladeGesamtUmsatz = false;
        private decimal _gesamtUmsatz = 0.0m;
        private List<Jahresumsatz> _gesamtUmsätze = new List<Jahresumsatz>();
        public async Task GetGesamtumsatz()
        {
            _ladeGesamtUmsatz = true;
            _gesamtUmsätze.Clear();
            await InvokeAsync(StateHasChanged);
            try
            {
                await foreach (Jahresumsatz umsatz in kundenService.GetAlleKundenJahresUmsätzeAsync(_kunde.KUND_A_NR, _ctsGesamtUmsatz.Token))
                {
                    _gesamtUmsatz += umsatz.Total;
                    _gesamtUmsätze.Add(umsatz);
                }
                _gesamtUmsatzGeladen = true;
            }
            catch (Exception ex)
            {

            }
            finally
            {
                _ladeGesamtUmsatz = false;
            }
        }

        public bool _showKundenBelegeModal { get; set; }
        public Pipeline<KundeInput> Pipeline { get; set; } = new Pipeline<KundeInput>();

        public string _modalTelefonnummer { get; set; } = String.Empty;
        public bool _showTelefonnummerModal { get; set; } = false;
        public List<KundenTabs> EditOnlyTabs { get; set; } = new List<KundenTabs>
        {
            KundenTabs.Ansprechpartner,
            KundenTabs.Umsatz,
            KundenTabs.Kundenkontakte,
            KundenTabs.Dokumentenablage,
            KundenTabs.Historie
        };
        public List<KundenTabs> AdminOnlyTabs { get; set; } = new List<KundenTabs>
        {

        };

        public Task Call(string? number)
        {
            if (number is not null)
            {
                _modalTelefonnummer = number;
                _showTelefonnummerModal = true;
                StateHasChanged();
            }
            return Task.CompletedTask;
        }


        private async Task AutoCompleteOrtAsync(string postleitzahl, object target)
        {
            if (target is null)
            {
                return;
            }

            if (target == Input)
            {
                Input.Postleitzahl = postleitzahl;
            }
            else if (target == Input.SelectedLieferanschrift)
            {
                Input.SelectedLieferanschrift.Postleitzahl = postleitzahl;
            }
            else if (target == Input.SelectedRechnungsanschrift)
            {
                Input.SelectedRechnungsanschrift.Postleitzahl = postleitzahl;
            }

            if (Input.Postleitzahl.Length <= 8 && !Input.Postleitzahl.Equals(String.Empty) && target is not null)
            {
                using FbController2 fbController = new FbController2();
                fbController.AddParameter("@PLZV_A_PLZ", Input.Postleitzahl);
                string? ort = await fbController.FetchObjectAsync("SELECT PLZV_A_ORT as ort FROM PLZ WHERE PLZV_A_PLZ = @PLZV_A_PLZ") as string;
                if (ort != null)
                {
                    if (target == Input)
                    {
                        Input.Ort = ort;
                    }
                    else if (target == Input.SelectedLieferanschrift)
                    {
                        Input.SelectedLieferanschrift.Ort = ort;
                    }
                    else if (target == Input.SelectedRechnungsanschrift)
                    {
                        Input.SelectedRechnungsanschrift.Ort = ort;
                    }
                }
            }
        }

        public async Task DeleteKundeAsync()
        {
            DeletePipeline.Reset();
            await DeletePipeline.RunUntilFailureAsync(Input);
        }

        public async Task LadeEditModeAsync()
        {
            Modus = EditMode.Bearbeiten;

            _kunde = await Kunde.GetKundeAsync(Kundennummer.ToString());
            if (_kunde is not null)
            {
                _kundeExists = true;
                Input = await _kunde.ToInputAsync();
                KundenBelegeFilter.Suchbegriff = Kundennummer.ToString();
                FilterZeiterfassung.Suchbegriff = Kundennummer.ToString();
                FilterZeiterfassung.Kundennummer = Kundennummer.ToString();
            }
            else
            {
                await AddAlertAsync(new AlertBox
                {
                    AlertType = AlertType.Danger,
                    Message = $"Kunde {Kundennummer} konnte nicht gefunden werden"
                });


                navigationManager.NavigateTo("/Kunden");
            }
        }

        private Task AutoCompleteMwstAsync()
        {
            if(Input.Land.Equals("DE"))
            {
                Input.MwstBerechnen = true;
            }
            else if(Program.AppDaten.Länder.Any(x => x.WK5_LAND_L_ISTEULAND && x.LAND_A_ID == Input.Land))
            {
                Input.MwstBerechnen = !Input.UstIdIstGültig;
            }
            else
            {
                Input.MwstBerechnen = false;
            }

            return Task.CompletedTask;
        }   

        private async Task LandChangedAsync(string land)
        {
            Input.Land = land;
            await AutoCompleteMwstAsync();
        }

        public override ValueTask DisposeAsync()
        {
            _ctsGesamtUmsatz.Cancel();
            _ctsHistorie.Cancel();     
            return base.DisposeAsync();
        }


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

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

                found = true;
            }

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

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

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

                found = true;
            }

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

        private WK5_Blazor.Components.AnsprechpartnerComponent? _ansprechPartnerComponent;
        private WK5_Blazor.Components.KundenKontakte? _kundenKontaktComponent;
        public async Task HandleCtrlPlus()
        {
            switch (ActiveTab)
            {
                case KundenTabs.Ansprechpartner:
                    if(_ansprechPartnerComponent is not null)
                    {
                        await _ansprechPartnerComponent.AddAnsprechpartnerAsync();
                    }
                    break;
                case KundenTabs.Lieferanschriften:
                    Input.AddLieferanschrift();
                    StateHasChanged();
                    break;
                case KundenTabs.Rechnungsanschriften:
                    Input.AddRechnungsanschrift();
                    StateHasChanged();
                    break;
                case KundenTabs.Kundenkontakte:                    
                    if(_kundenKontaktComponent is not null)
                    {
                        await _kundenKontaktComponent.AddKundenKontakt();
                    }
                    break;                
                default:
                    break;
            }                        
        }

        public async Task OnTabChange(KundenTabs newActiveTab)
        {
            switch (newActiveTab)
            {                
                case KundenTabs.Umsatz:
                    await LadeUmsatz();
                    break;                
                case KundenTabs.Kundenkontakte:
                    await LoadKontakte();
                    break;
                case KundenTabs.Historie:
                    await LoadHistorie();
                    break;                
                default:
                    break;
            }

            if(newActiveTab == KundenTabs.Umsatz)
            {
                await LadeUmsatz();
            }
        }

        public string GetTabValidatorClass(KundenTabs tabs)
        {
            if(tabs == KundenTabs.Ansprechpartner)
            {                
                foreach (AnsprechpartnerInput partner in Input.Ansprechpartner)
                {
                    if (!_partValidator.Validate(partner).IsValid)
                    {
                        return "bg-danger text-light";
                    }
                }
            }else if(tabs == KundenTabs.Lieferanschriften)
            {                
                foreach (LieferanschriftInput anschrift in Input.Lieferanschriften)
                {
                    if (!_liefValidator.Validate(anschrift).IsValid)
                    {
                        return "bg-danger text-light";
                    }
                }
            }else if(tabs == KundenTabs.Rechnungsanschriften)
            {                
                foreach (RechnungsanschriftInput anschrift in Input.Rechnungsanschriften)
                {
                    if (!_rechValidator.Validate(anschrift).IsValid)
                    {
                        return "bg-danger text-light";
                    }
                }
            }

            return String.Empty;
        }

        public string GetTabName(KundenTabs tab)
        {
            if(tab is KundenTabs.UstIdAdresse)
            {
                return "Ust.Id Adresse";
            }

            return tab.ToString();
        }
    }
}
