using KarleyLibrary.Erweiterungen;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Serilog;
using System;
using System.Collections.Generic;
using System.Data;
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.Models;
using WK5.Core.PageModels.Stammdaten.Artikeldaten;
using WK5.Core.Validators;
using WK5.Core.Validators.Stammdaten.Artikeldaten;
using WK5_Blazor.Components;

namespace WK5_Blazor.Pages.Stammdaten.Artikeldaten
{
    public partial class ArtikelForm : IPipeline<Artikel>, IEditPage, ITabPage<ArtikelTabs>
    {
        [Parameter] public string Artikelnummer { get => _artikelnummer; set => (_artikelnummer = value ?? String.Empty).ToUpper(); }
#nullable disable
        [CascadingParameter] public AppMitarbeiter Mitarbeiter { get; set; }
#nullable enable
        public Artikel Input { get; set; } = new Artikel();
        public Artikel StartCopy { get; set; } = new Artikel();
        public Pipeline<Artikel> Pipeline { get; set; } = new Pipeline<Artikel>();
        public Pipeline<Artikel> DeletePipeline { get; set; } = new Pipeline<Artikel>();
        public Pipeline<Artikel> ChangeArtikelNummerPipeline { get; set; } = new Pipeline<Artikel>();

        public string ActivePageName => Modus switch
        {
            EditMode.Anlage => "Artikelanlage",
            EditMode.Bearbeiten => $"Artikel {Input.Artikelnummer}",
            _ => "Unbekannt"
        };

        public string FinalBreadcrumbItemName => Modus switch
        {
            EditMode.Anlage => "Neu",
            EditMode.Bearbeiten => $"{Artikelnummer}",
            _ => "Unbekannt"
        };
        public EditMode Modus { get; set; } = EditMode.Anlage;
        public List<ArtikelTabs> EditOnlyTabs { get; set; } = new List<ArtikelTabs>()
        {
            ArtikelTabs.Bilder,
            ArtikelTabs.Dokumente,
            ArtikelTabs.Lieferanten,
            ArtikelTabs.Verbrauchsdaten,
            ArtikelTabs.Historie,
            ArtikelTabs.Zubehör,
            ArtikelTabs.Termine,
        };
        public List<ArtikelTabs> AdminOnlyTabs { get; set; } = new List<ArtikelTabs>();
        public ArtikelTabs ActiveTab { get; set; }
        public List<int> OffenerBedarf { get; set; } = new List<int>();

        public Zolltarif? SelectedZolltarif { get; set; }

        private EditForm? _form;
        private bool _showBundleModal;
        private bool _showAngebotSucheModal;
        private bool _showPreisgruppenSucheModal;
        private bool _showZolltarifSucheModal;
        private bool _showHerstellerSucheModal;
        private bool _showArtikelErsatzSuche;
        private bool _showVerbrauchsdaten;
        private bool _lädtHistorie;
        private bool _speichert;
        private bool _showStaffelfehlerModal;
        private bool _showKeineLieferantenVorhandenModal;
        private bool _showEtikettenWarengruppeBxHxLModal;
        private bool _disableEk = true;
        private bool _showLabelPrintModal;
        private bool _showDokumenteFileBrowserModal;
        private bool _showArtikelDeleteConfirmModal;
        private bool _showCopyModal;
        private bool _showArtikelInBelegenModal;
        private bool _showArtikelBestandsModal;
        private bool _showArtikelBestelltModal;
        private bool _showBestellÜbersichtModal;
        private bool _showChargenÜbersichtModal;
        private bool _showBewegungsdatenModal;
        private bool _showArtikelBelegübersichtModal;
        private bool _showSeriennummernÜbersichtModal;
        private bool _showZubehörArtikelSuche;
        private bool _showBilderFileBrowserModal;
        private bool _showArtikelnummerÄndernModal;
        private bool _showFehlerBeiArtikelnummerWechselSeriennummerModal;
        private bool _showConfirmArtikelnummerWechselModal;
        private bool _showPrintSeriennummerModal;
        private bool _showInventurModal;
        private int _anzahlEtiketten;
        private string _neueArtikelnummer = string.Empty;
        private string _confirmArtikelnummerWechselMarkup = string.Empty;
        private Seriennummer? _selectedSeriennummer;
        private StaffelpreisCollectionValidator _staffelValidator = new();
        private BelegFilter _angebotFilter = new BelegFilter(BelegTyp.Angebot);
        private ArtikelFilter _artikelErsatzFilter = new();
        private ArtikelVerbrauchsdatenModus _verbrauchdatenModus = ArtikelVerbrauchsdatenModus.Menge;
        private List<BelegChangeAnsicht> _historie = new();
        private List<KeyValuePair<string, int>> _belegeMitArtikel = new();
        

        private ArtikelValidator _validator = new(new StaffelpreisCollectionValidator(), new ArtikelAngebotValidator());
        private LieferantenArtikelList? _lieferantenArtikelList;
        private EinzelInventurInput _inventurInput = new EinzelInventurInput();
        private string _artikelnummer = string.Empty;

        private ArtikelBelegübersichtFilter FilterArtikelBelegübersicht { get; set; } = new();
        public SeriennummerFilter FilterSeriennummern { get; set; } = new();
        
        public string CopyArtikelNummer { get; set; } = String.Empty;
        public List<ArtikelZubehör> ZubehörArtikel { get; set; } = new List<ArtikelZubehör>();
        protected override async Task OnParametersSetAsync()
        {

            if (!string.IsNullOrWhiteSpace(Artikelnummer))
            {
                await LadeEditModeAsync();
            }

            if (!_isDisposed && Modus is EditMode.Bearbeiten)
            {
                await CheckActivePageAsync();
            }

            await SetAlerts();

            StartCopy = Input.DeepCopy();
            await SetupPipelineAsync();
            await SetupDeletePipelineAsync();
            await SetupChangeArtikelNummerPipeline();
        }
        public async Task SetupPipelineAsync()
        {
            Pipeline = new Pipeline<Artikel>();
            await Pipeline.HardReset();

            Pipeline.Add((input) =>
            {
                if (!String.IsNullOrWhiteSpace(CheckStaffelpreiseMultiples()))
                {
                    _showStaffelfehlerModal = true;
                    return false;
                }
                else
                {
                    return true;
                }
            });

            Pipeline.Add(async (input) =>
            {
                using FbController2 fbController = new FbController2();
                if (Modus == EditMode.Anlage || !input.ARTI_L_LAGERFUEHR || await Lieferantenartikel.GetLieferantenartikelAsync(Input.Artikelnummer, fbController).AnyAsync())
                {
                    return true;
                }
                else
                {
                    _showKeineLieferantenVorhandenModal = true;
                    return false;
                }
            });

            // Wenn Warengruppe Etiketten ist, erinnern wir die Vertriebler daran Dimensionen zu hinterlegen
            Pipeline.Add((input) =>
            {
                if (input.Warengruppe == "2172" && input.Breite <= 0 && input.ARTI_N_HOEHE <= 0)
                {
                    _showEtikettenWarengruppeBxHxLModal = true;
                    return false;
                }
                return true;
            });

            Pipeline.Add(async (input) =>
            {
                await SaveAsync();
                return true;
            });
        }
        private async Task SetupDeletePipelineAsync()
        {
            await DeletePipeline.HardReset();

            DeletePipeline.Add(async (input) =>
            {
                using FbController2 fbController = new FbController2();
                

                return true;
            });


            DeletePipeline.Add(async (input) =>
            {
                using FbController2 fbController = new FbController2();
                string suchSql = @"SELECT DISTINCT BPOS_N_NR, BPOS_A_TYP FROM BELEGSTUECKLISTE
LEFT JOIN BELEGPOS ON BPOS_N_POSID = BSTU_N_POSID
WHERE BSTU_A_UNTERARTI = @ARTINR
AND(COALESCE(BPOS_A_TYP, '') != '' AND COALESCE(BPOS_N_NR, 0) != 0)
AND COALESCE(BPOS_A_TYP,'') != 'AN'";

                fbController.AddParameter("@ARTINR", input.Artikelnummer);
                DataTable data = await fbController.SelectDataAsync(suchSql);

                if (data.Rows.Count > 0)
                {
                    _belegeMitArtikel.Clear();
                    foreach (DataRow row in data.Rows)
                    {
                        _belegeMitArtikel.Add(new KeyValuePair<string, int>(row.Field<string>("BPOS_A_TYP"), row.Field<int>("BPOS_N_NR")));
                    }

                    _belegeMitArtikel = _belegeMitArtikel.OrderBy(x => x.Key).ThenBy(x => x.Value).ToList();

                    return false;
                }
                else
                {
                    // Wir haben vorher festgestellt dass der Artikel nicht in anderen Belegtypen auftritt
                    string updateSql = @"UPDATE BELEGSTUECKLISTE SET BSTU_A_UNTERARTI = 'DIVERS' WHERE BSTU_A_UNTERARTI = @ARTINR";
                    fbController.AddParameter("@ARTINR", input.Artikelnummer);
                    await fbController.QueryAsync(updateSql);
                    return true;
                }
            });

            DeletePipeline.Add(async (input) =>
            {
                using FbController2 fbController = new FbController2();
                string sql = "SELECT * FROM BELEGPOS WHERE BPOS_A_ARTIKELNR = @ARTIKELNR AND BPOS_A_TYP != 'AN'";

                fbController.AddParameter("@ARTIKELNR", input.Artikelnummer);
                DataTable data = await fbController.SelectDataAsync(sql);

                if (data.Rows.Count > 0)
                {
                    _belegeMitArtikel.Clear();
                    foreach (DataRow row in data.Rows)
                    {
                        _belegeMitArtikel.Add(new KeyValuePair<string, int>(row.Field<string>("BPOS_A_TYP"), row.Field<int>("BPOS_N_NR")));
                    }
                    _showArtikelInBelegenModal = true;
                    return false;
                }
                else
                {
                    string updateSql = "UPDATE BELEGPOS SET BPOS_A_ARTIKELNR = 'DIVERS' WHERE BPOS_A_ARTIKELNR = @ARTIKELNR AND BPOS_A_TYP = 'AN'";
                    fbController.AddParameter("@ARTIKELNR", input.Artikelnummer);
                    await fbController.QueryAsync(updateSql);
                    return true;
                }
            });

            DeletePipeline.Add((input) =>
            {
                if (input.Bestand > 0)
                {
                    _showArtikelBestandsModal = true;
                    return false;
                }
                else
                {
                    return true;
                }
            });

            DeletePipeline.Add(async (input) =>
            {
                if (await bestellService.GetOffeneBestellungenFürArtikelAsync(Input.Artikelnummer).AnyAsync())
                {
                    _showArtikelBestelltModal = true;
                    return false;
                }
                else
                {
                    return true;
                }
            });

            DeletePipeline.Add(async (input) =>
            {
                using FbController2 fbController = new FbController2();
                List<Charge> chargen = await Charge.GetChargenAsync(input.Artikelnummer, fbController).ToListAsync();
                if (chargen.Count > 0)
                {
                    //_showArtikelChargenModal = true;
                    return false;
                }
                else
                {
                    return true;
                }
            });

            DeletePipeline.Add((input) =>
            {
                _showArtikelDeleteConfirmModal = true;
                return false;
            });



            DeletePipeline.Add(async (input) =>
            {
                using FbController2 fbController = new FbController2();
                await fbController.StartTransactionAsync();
                try
                {
                    await artikelService.DeleteArtikel(input.Artikelnummer, fbController);
                    await fbController.CommitChangesAsync();
                    await AddAlertAsync(new AlertBox()
                    {
                        AlertType = AlertType.Success,
                        Message = $"Artikel {input.Artikelnummer} wurde erfolgreich gelöscht"
                    });
                    navigationManager.NavigateTo("/Artikel");
                }
                catch (Exception ex)
                {
                    await fbController.RollbackChangesAsync();
                    await AddAlertAsync(new AlertBox()
                    {
                        AlertType = AlertType.Danger,
                        Message = $"Artikel {input.Artikelnummer} konnte nicht gelöscht werden! Fehler: {ex}"
                    });
                }
                return true;
            });
        }
        public async Task SetupChangeArtikelNummerPipeline()
        {
            if (!Mitarbeiter.IsAdmin) return;

            await ChangeArtikelNummerPipeline.HardReset();
            ChangeArtikelNummerPipeline.Add(async (input) =>
            {
                _neueArtikelnummer = _neueArtikelnummer.ToUpper();

                if (String.IsNullOrWhiteSpace(_neueArtikelnummer))
                {
                    await jsRuntime.ShowToast(ToastType.error, $"Neue Artikelnummer darf nicht leer sein.");
                    return false;
                }

                if (!System.Text.RegularExpressions.Regex.IsMatch(_neueArtikelnummer, "^[a-zA-Z0-9äÄöÖüÜ_-]*$"))
                {
                    await jsRuntime.ShowToast(ToastType.error, $"Neue Artikelnummer darf nur '-', '_' und Alphanumerische Zeichen enthalten.");
                    _showArtikelnummerÄndernModal = true;
                    return false;
                }

                return true;
            });

            ChangeArtikelNummerPipeline.Add(async (input) =>
            {
                using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);

                fbController.AddParameter("@ARTIKELNR", _neueArtikelnummer);
                DataRow? row = await fbController.SelectRowAsync("SELECT ARTI_A_NR, ARTI_L_SN FROM ARTIKEL WHERE ARTI_A_NR = @ARTIKELNR");

                if (row is null)
                {
                    return true;
                }
                else
                {
                    bool sn = row["ARTI_L_SN"].ToString() == "Y";
                    if (sn == input.ARTI_L_SN)
                    {
                        return true;
                    }
                    else
                    {
                        _showFehlerBeiArtikelnummerWechselSeriennummerModal = true;
                        return false;
                    }
                }


            });

            ChangeArtikelNummerPipeline.Add(async (input) =>
            {
                using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
                fbController.AddParameter("@ARTIKELNR", _neueArtikelnummer);
                DataRow? row = await fbController.SelectRowAsync("SELECT ARTI_A_NR, ARTI_L_SN FROM ARTIKEL WHERE ARTI_A_NR = @ARTIKELNR");

                if (row is not null)
                {
                    _confirmArtikelnummerWechselMarkup = $"<p>Der Artikel {_neueArtikelnummer} existiert bereits!</p><p>Möchtest du die beiden Artikel wirklich vereinen?</p>";
                }
                else
                {
                    _confirmArtikelnummerWechselMarkup = $"<p>Möchtest du die Artikelnummer wirklich zu {_neueArtikelnummer} ändern?</p>";
                }

                _showConfirmArtikelnummerWechselModal = true;
                return false;
            });

            ChangeArtikelNummerPipeline.Add(async (input) =>
            {
                using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
                fbController.AddParameter("@ARTI_NEU", _neueArtikelnummer);
                fbController.AddParameter("@ARTI_ALT", input.Artikelnummer);
                await fbController.QueryAsync("EXECUTE PROCEDURE ARTIKELNUMMER_AENDERN(@ARTI_NEU, @ARTI_ALT)");
                navigationManager.NavigateTo($"/Artikel/{_neueArtikelnummer}");
                _neueArtikelnummer = String.Empty;
                return true;
            });

        }

        public async Task LadeEditModeAsync()
        {
            using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
            Artikel? artikel = await artikelService.GetAsync(Artikelnummer, fbController);
            if (artikel is not null)
            {
                Input = artikel;
                Artikelnummer = artikel.Artikelnummer;
                FilterSeriennummern.Artikelnummer = Artikelnummer;
                FilterArtikelBelegübersicht.Suchbegriff = Artikelnummer;
                Modus = EditMode.Bearbeiten;

                OffenerBedarf = await artikelService.GetBelegBedarf(Input.Artikelnummer).ToListAsync();
                //ParentStücklistenArtikel = await Artikel.GetParentStücklisten(artikel.Artikelnummer).ToListAsync();

                await CheckEKPreis();
                Input.RecalculateProzente(Program.AppDaten.Preisgruppen.FirstOrDefault(x => x.PRGR_A_NR == Input.Preisgruppe));
                if (artikel.ZolltarifId is > 0)
                {
                    SelectedZolltarif = await Zolltarif.GetZolltarifAsync(artikel.ZolltarifId);
                }
            }
            else
            {
                await AddAlertAsync(new AlertBox($"Artikel {Artikelnummer} konnte nicht gefunden werden", AlertType.Danger));
                navigationManager.NavigateTo("/Artikel");
            }
        }
        private async Task SubmitAsync()
        {
            if (SperreDurchAnderenUser || _speichert || !Input.HasBeenModified(StartCopy))
            {
                return;
            }

            await CheckEKPreis();

            if (_form is not null && _form.EditContext is not null)
            {
                //var tmp = _form.EditContext.GetValidationMessages();
                if (_form.EditContext.Validate())
                {
                    Pipeline.Reset();
                    await Pipeline.RunUntilFailureAsync(Input);
                }
            }
        }
        private async Task SaveAsync()
        {
            if (_speichert)
            {
                return;
            }

            _speichert = true;
            StateHasChanged();

            await CheckEKPreis();


            using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);

            if (Modus is EditMode.Anlage)
            {
                bool exists = await Artikel.Exists(Input.Artikelnummer);
                if (exists)
                {
                    await jsRuntime.ShowToast(ToastType.error, "Fehler beim anlegen des Artikels! Ein Artikel mit dieser Artikelnummer existiert bereits!");

                    Log.Logger.Error($"Artikel {Input.Artikelnummer} konnte nicht lokal angelegt werden. Fehler: Artikel existiert bereits");
                    return;
                }
            }

            await fbController.StartTransactionAsync();

            try
            {
                if (Modus is EditMode.Anlage)
                {
                    await artikelService.CreateAsync(Input, fbController);
                }
                else
                {
                    await artikelService.UpdateAsync(Input, fbController);

                    await foreach (ArtikelBild bild in ArtikelBild.GetBilderAsync(Input.Artikelnummer))
                    {
                        if (!Input.Bilder.Any(x => x.ARBI_N_NR == bild.ARBI_N_NR))
                        {
                            await ArtikelBild.DeleteAsync(bild);
                        }
                    }

                    foreach (ArtikelBild bild in Input.Bilder)
                    {
                        if (bild.ARBI_N_NR > 0)
                        {
                            await ArtikelBild.UpdateAsync(bild);
                        }
                        else
                        {
                            var nBild = await ArtikelBild.CreateAsync(bild);
                        }
                    }


                    await foreach (ArtikelAngebot angebot in ArtikelAngebot.GetAngeboteAsync(Input.Artikelnummer))
                    {
                        if (!Input.Sonderangebote.Where(x => x.ARAN_N_NR == angebot.ARAN_N_NR).Any())
                        {
                            await angebot.DeleteAsync(fbController);
                        }
                    }

                    foreach (ArtikelAngebot angebot in Input.Sonderangebote)
                    {
                        angebot.ARAN_N_OPENCART_GRUPPE = angebot.ARAN_N_PREISLISTE switch
                        {
                            2 => 2,
                            3 => 3,
                            _ => 2,
                        };
                        if (angebot.ARAN_N_NR > 0)
                        {
                            await ArtikelAngebot.UpdateArtikelAngebotAsync(angebot, fbController);

                        }
                        else
                        {
                            await ArtikelAngebot.InsertArtikelAngebotAsync(angebot, fbController);
                        }
                    }


                    await foreach (ArtikelDokument dokument in ArtikelDokument.GetArtikelDokumenteAsync(Input.Artikelnummer, fbController))
                    {
                        if (!Input.Dokumente.Any(x => x.ARDI_N_NR == dokument.ARDI_N_NR))
                        {
                            await ArtikelDokument.DeleteArtikelDokumentAsync(dokument.ARDI_N_NR, fbController);
                        }
                    }

                    foreach (ArtikelDokument dokument in Input.Dokumente)
                    {
                        if (dokument.ARDI_N_NR > 0)
                        {
                            await ArtikelDokument.UpdateArtikelDokumentAsync(dokument, fbController);
                        }
                        else
                        {
                            await ArtikelDokument.CreateArtikelDokumentAsync(dokument, fbController);
                        }
                    }
                }

                await fbController.CommitChangesAsync();

                await AddAlertAsync(new AlertBox
                {
                    AlertType = AlertType.Success,
                    Message = "Artikel wurde erfolgreich gespeichert",
                    DecayTime = 10
                });
            }
            catch (Exception)
            {
                await fbController.RollbackChangesAsync();
                throw;
            }



            _speichert = false;
            if(Modus is EditMode.Anlage)
            {
                navigationManager.NavigateTo($"/Artikel/{Input.Artikelnummer}");
            }
            else
            {
                await OnParametersSetAsync();
            }
        }
        private async Task ChangeArtikelnummerAsync()
        {
            if (!Mitarbeiter.IsAdmin)
            {
                return;
            }

            ChangeArtikelNummerPipeline.Reset();
            await ChangeArtikelNummerPipeline.RunUntilFailureAsync(Input);
        }
        private async Task CheckEKPreis()
        {
            if (Input.ARTI_L_DIENSTLEIST || (!Input.ARTI_L_LAGERFUEHR && !Input.IstBundle))
            {
                return;
            }
            using FbController2 fbController = new FbController2();

            if (!Input.IstBundle)
            {
                var lieferantenartikel = await Lieferantenartikel.GetLieferantenartikelAsync(Input.Artikelnummer, fbController).ToListAsync();

                if (lieferantenartikel.Count is 0)
                {
                    return;
                }

                Input.ARTI_N_EK = await Input.GetEinkaufspreis(lieferantenartikel);
            }
            else
            {
                Input.ARTI_N_EK = await Input.GetEinkaufspreis();
            }

            await artikelService.UpdateArtikelEinkaufspreisAsync(Input.Artikelnummer, Input.ARTI_N_EK, fbController);
        }
        private async Task LadeHistorieAsync()
        {
            _historie.Clear();
            _lädtHistorie = true;
            await foreach (var item in BelegChangeAnsicht.GetHistorieAsync("AR", Artikelnummer))
            {
                _historie.Add(item);
                StateHasChanged();
            }

            _lädtHistorie = false;
        }
        private async Task LadeArtikelZubehörAsync()
        {
            using FbController2 fbController = new FbController2();
            ZubehörArtikel = await ArtikelZubehör.GetArtikelZubehörAsync(Artikelnummer, fbController).ToListAsync();
        }


        private string CheckStaffelpreiseMultiples()
        {
            string artikelMarkup = "";
            if (Input.ARTI_N_COLLI > 0)
            {
                for (int i = 0; i < Input.Staffelpreise.Count(); i++)
                {
                    Staffelpreis? preis = Input.Staffelpreise.Get(i);
                    if (preis is not null)
                    {
                        if (preis.Menge % Input.ARTI_N_COLLI != 0)
                        {
                            artikelMarkup += $"<span>Staffelmenge {i + 1} ({preis.Menge}) ist kein vielfaches der Mindestabnahme ({Input.ARTI_N_COLLI})</span><br/>";
                        }
                    }
                }
            }

            string liefMarkup = "";


            string markup = "";
            if (!String.IsNullOrWhiteSpace(artikelMarkup) || !String.IsNullOrWhiteSpace(liefMarkup))
            {
                markup += "<h2> Unschlüssige Staffelmengen gefunden</h2>";
                markup += "<p> Es wurden Staffelmengen gefunden die kein Vielfaches der Mindestabnahme sind.</p>";
                markup += "<br/>";
                markup += "<h3>Artikelstaffel</h3>";
                markup += artikelMarkup;
                markup += "<br/>";
                markup += liefMarkup;
                markup += "<br/>";
                markup += "<br/>";
                markup += "<p>Möchtest du mit dem speichern fortfahren?</p>";
                return markup;
            }
            else
            {
                return String.Empty;
            }


        }
        private async Task DeleteAsync()
        {
            DeletePipeline.Reset();
            await DeletePipeline.RunUntilFailureAsync(Input);
        }
        public async Task CopyAsync()
        {
            if (String.IsNullOrWhiteSpace(CopyArtikelNummer))
            {
                await jsRuntime.ShowToast(ToastType.error, $"Artikelnummer darf nicht leer sein.");
                _showCopyModal = true;
                return;
            }

            if (!System.Text.RegularExpressions.Regex.IsMatch(CopyArtikelNummer, "^[a-zA-Z0-9äÄöÖüÜ_-]*$"))
            {
                await jsRuntime.ShowToast(ToastType.error, $"Artikelnummer darf nur '-', '_' und Alphanumerische Zeichen enthalten.");
                _showCopyModal = true;
                return;
            }

            using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);

            Artikel? newArtikel = await artikelService.GetAsync(CopyArtikelNummer, fbController);

            if (newArtikel is not null)
            {
                await jsRuntime.ShowToast(ToastType.error, $"Der Artikel kann nicht kopiert werden: Die neue Artikelnummer gibt es bereits!", 0);
            }
            else
            {
                try
                {
                    await artikelService.CopyAsync(Input.Artikelnummer, CopyArtikelNummer.ToUpper(), fbController);
                    _showCopyModal = false;
                    navigationManager.NavigateTo($"/Artikel/{CopyArtikelNummer}", true);
                }
                catch (Exception ex)
                {
                    await jsRuntime.ShowToast(ToastType.error, $"Fehler beim kopieren des Artikel. Fehler: {ex.Message}", 0);
                }
            }
        }

        public Task HauptBildChangedAsync(ArtikelBild bild, bool selected)
        {
            if (selected)
            {
                foreach (ArtikelBild b in Input.Bilder)
                {
                    b.ARBI_L_HAUPT = false;
                }

                bild.ARBI_L_HAUPT = true;
            }
            else
            {
                bild.ARBI_L_HAUPT = false;
            }

            return Task.CompletedTask;
        }
        private async Task ArtikelDokumentDownloadAsync(ArtikelDokument dokument)
        {
            var data = await dokument.GetBytesAsync();
            await downloadService.DownloadFile(Path.GetFileName(dokument.ARDI_A_REL_DOCPFAD), data, $"application/{Path.GetExtension(dokument.ARDI_A_REL_DOCPFAD).Trim('.')}");
        }

        private Task ArtikelDokumentSelectedAsync(FileBrowserElement element)
        {
            Input.Dokumente.Add(new ArtikelDokument()
            {
                ARDI_A_ARTINR = Input.Artikelnummer,
                ARDI_A_REL_DOCPFAD = Path.GetRelativePath(ArtikelDokument.DokumentenRoot, element.Path),
            });

            _showDokumenteFileBrowserModal = false;

            return Task.CompletedTask;
        }
        private Task ArtikelBildSelectedAsync(FileBrowserElement element)
        {
            Input.Bilder.Add(new ArtikelBild()
            {
                ARBI_A_ARTINR = Input.Artikelnummer,
                ARBI_A_IMGPFAD = element.Path.Replace(Path.GetFullPath(ArtikelBild.LocalImageDirectory), String.Empty),
                ARBI_D_DATE = DateTime.Now,
                ARBI_L_HAUPT = false
            });

            _showBilderFileBrowserModal = false;

            return Task.CompletedTask;
        }
        #region Controlled-Binding
        private Task WarengruppeSelectedAsync(string warengruppe)
        {
            Input.Warengruppe = warengruppe;
            Input.Unterwarengruppe = string.Empty;
            return Task.CompletedTask;
        }
        private Task PreisgruppeSelectedAsync(Preisgruppe preisgruppe)
        {
            Input.Preisgruppe = preisgruppe.PRGR_A_NR;
            _showPreisgruppenSucheModal = false;
            Input.RecalculatePreise(preisgruppe);
            return Task.CompletedTask;
        }
        private Task ZolltarifSelectedAsync(Zolltarif zolltarif)
        {
            Input.ZolltarifId = zolltarif.ZOTA_N_NR;
            SelectedZolltarif = zolltarif;
            _showZolltarifSucheModal = false;
            return Task.CompletedTask;
        }
        public Task HerstellerSelectedAsync(Hersteller hersteller)
        {
            Input.Hersteller = hersteller.HEST_A_NR;
            _showHerstellerSucheModal = false;
            return Task.CompletedTask;
        }
        private Task ArtikelErsatzSelectedAsync(Artikel artikel)
        {
            Input.ARTI_A_ERSATZART = artikel.Artikelnummer;
            _showArtikelErsatzSuche = false;
            return Task.CompletedTask;
        }
        private Task SearchArtikelErsatzAsync()
        {
            _artikelErsatzFilter.Suchbegriff = Input.ARTI_A_ERSATZART ?? String.Empty;
            _artikelErsatzFilter.ZeigeInaktive = false;
            _showArtikelErsatzSuche = true;
            return Task.CompletedTask;
        }

        private async Task ZubehörArtikelSelectedAsync(Artikel artikel)
        {
            ArtikelZubehör zubehör = new ArtikelZubehör
            {
                ARZU_A_ZUBEHOERART = artikel.Artikelnummer,
                ARZU_A_AUSGANGSART = Artikelnummer,
                Beschreibung = artikel.GetBezeichnung()
            };

            using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
            try
            {
                await zubehör.CreateAsync(fbController);
                ZubehörArtikel.Add(zubehör);
                await jsRuntime.ShowToast(ToastType.success, "Zubehör erfolgreich hinzugefügt");
            }
            catch (Exception ex)
            {
                fbController.ClearParameters();
                await jsRuntime.ShowToast(ToastType.error, $"Zubehör konnte nicht hinzugefügt werden: {ex}");
            }
            

        }

        private async Task DeleteZubehörArtikelAsync(ArtikelZubehör zubehör)
        {
            ZubehörArtikel.Remove(zubehör);
            using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
            await ArtikelZubehör.DeleteAsync(zubehör.ARZU_A_AUSGANGSART, zubehör.ARZU_A_ZUBEHOERART, fbController);
            await jsRuntime.ShowToast(ToastType.success, "Zubehör wurde erfolgreich gelöscht");
        }

        private async Task InventurErfassungAsync()
        {
            using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
            Input.Bestand = await inventurService.DirektBuchungAsync(Input.Artikelnummer, _inventurInput.Menge, fbController);

            if (Input.Bestand != _inventurInput.Menge)
            {
                await jsRuntime.ShowToast(ToastType.warning, $"Inventur wurde erfolgreich durchgeführt. Der Bestand wurde auf {Input.Bestand} gesetzt, da nicht mehr Chargen vorhanden sind.");
            }
            else
            {
                await jsRuntime.ShowToast(ToastType.success, $"Inventur wurde erfolgreich durchgeführt.");
            }
            _showInventurModal = false;
        }

        private async Task InventurSeriennummerErfassungAsync()
        {
            if (_selectedSeriennummer is null)
            {
                return;
            }

            using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
            await inventurService.DirektBuchungSeriennummerAsync(_selectedSeriennummer, fbController);

            _selectedSeriennummer.Ausgeliefert = !_selectedSeriennummer.Ausgeliefert;
            if (_selectedSeriennummer.Ausgeliefert)
            {
                Input.Bestand--;
            }
            else
            {
                Input.Bestand++;
            }
            await jsRuntime.ShowToast(ToastType.success, $"Inventur für Seriennummer {_selectedSeriennummer.Nummer} erfolgreich durchgeführt");
        }
        public override void AddHotKeys(HotKeysContext context)
        {
            context
            .Add(ModKeys.Alt, Keys.S, SubmitAsync, "Speichert den Artikel", Exclude.Default)
            .Add(ModKeys.Alt, Keys.P, () => { _showLabelPrintModal = true; StateHasChanged(); }, "Öffnet die Artikel Druckoptionen", 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)
            ;
        }
        #endregion
        #region Hilfsfunktionen

        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;
        }
        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 OnTabChange(ArtikelTabs newActiveTab)
        {
            ActiveTab = newActiveTab;

            if (newActiveTab == ArtikelTabs.Historie)
            {
                await LadeHistorieAsync();
            }
            else if (newActiveTab is ArtikelTabs.Zubehör)
            {
                await LadeArtikelZubehörAsync();
            }
            else if (newActiveTab is ArtikelTabs.Verbrauchsdaten)
            {
                _showVerbrauchsdaten = true;
            }
        }
        #endregion
        #region AutoComplete
        private Task LagerplatzChangedAsync(string lagerplatz)
        {
            if (!Input.ARTI_L_LAGERFUEHR)
            {
                Input.Lagerplatz = string.Empty;
            }
            else
            {
                Input.Lagerplatz = lagerplatz;
            }

            return Task.CompletedTask;
        }

        private Task LagerführungChangedAsync(bool lagerführung)
        {
            Input.ARTI_L_LAGERFUEHR = lagerführung;

            if (lagerführung)
            {
                Input.ARTI_L_DIENSTLEIST = false;
            }

            return Task.CompletedTask;
        }

        private Task SeriennummerVerwaltungChangedAsync(bool seriennummerVerwaltung)
        {
            Input.ARTI_L_SN = seriennummerVerwaltung;

            if (!seriennummerVerwaltung)
            {
                Input.ARTI_L_SN_ABGANG = false;
                Input.ARTI_L_SN_EINGANG = false;
            }

            return Task.CompletedTask;
        }

        private Task SeriennummerBeiEingangChangedAsync(bool seriennummerBeiEingang)
        {
            Input.ARTI_L_SN_EINGANG = seriennummerBeiEingang;

            if (seriennummerBeiEingang)
            {
                Input.ARTI_L_SN_ABGANG = false;
            }

            return Task.CompletedTask;
        }

        private Task SeriennummerBeiAbgangChangedAsync(bool seriennummerBeiAbgang)
        {
            Input.ARTI_L_SN_ABGANG = seriennummerBeiAbgang;

            if (seriennummerBeiAbgang)
            {
                Input.ARTI_L_SN_EINGANG = false;
            }

            return Task.CompletedTask;
        }

        private Task EinkaufspreisChangedAsync(decimal einkaufspreis)
        {
            Input.ARTI_N_EK = einkaufspreis;
            Input.RecalculatePreise(Program.AppDaten.Preisgruppen.FirstOrDefault(x => x.PRGR_A_NR == Input.Preisgruppe));

            return Task.CompletedTask;
        }

        private Task BruttopreisChangedAsync(decimal bruttopreis)
        {
            Input.ARTI_N_BRUTTO = bruttopreis;
            Input.RecalculateProzente(Program.AppDaten.Preisgruppen.FirstOrDefault(x => x.PRGR_A_NR == Input.Preisgruppe));
            return Task.CompletedTask;
        }

        private async Task ListenpreisChangedAsync(int index, decimal preis)
        {
            switch (index)
            {
                case 1:
                    Input.ARTI_N_VK1 = preis;
                    Input.Staffelpreise.SetBezugspreis(preis);
                    Input.Staffelpreise.Sort();
                    break;
                case 2:
                    Input.ARTI_N_VK2 = preis;
                    break;
                case 3:
                    Input.ARTI_N_VK3 = preis;
                    break;
                case 4:
                    Input.ARTI_N_VK4 = preis;
                    break;
                case 5:
                    Input.ARTI_N_VK5 = preis;
                    break;
                default:
                    break;
            }

            Input.RecalculateProzente(Program.AppDaten.Preisgruppen.FirstOrDefault(x => x.PRGR_A_NR == Input.Preisgruppe));

            //if(ParentStücklistenArtikel.Any())
            //{
            //    await jsRuntime.ShowToast(ToastType.warning, "Der Artikel ist noch in Stücklisten enthalten. Ggf. müssen die VK-Preise auch innerhalb der Stückliste aktualisiert werden!!", 7000);
            //    _showParentStücklistenModal = true;
            //}
        }

        private Task AbverkaufChangedAsync(bool value)
        {
            Input.ARTI_L_ABVERKAUF = value;

            if (!value)
            {
                Input.ARTI_L_INAKT_ABVER = false;
            }
            else
            {
                Input.Mindestbestand = 0;
            }

            return Task.CompletedTask;
        }

        private Task FixpreisChangedAsync(int index, bool fixpreis)
        {
            if (index < 3)
            {
                Input.ARTI_L_FIXPREIS = fixpreis;
                Input.RecalculatePreise(Program.AppDaten.Preisgruppen.FirstOrDefault(x => x.PRGR_A_NR == Input.Preisgruppe));
            }
            else if (index is 3)
            {
                Input.ARTI_L_FIXVK3 = fixpreis;
            }
            else if (index is 4)
            {
                Input.ARTI_L_FIXVK4 = fixpreis;
            }
            else if (index is 5)
            {
                Input.ARTI_L_FIXVK5 = fixpreis;
            }
            return Task.CompletedTask;
        }

        private Task StaffelpreisChangedAsync(Staffelpreis staffel, decimal preis)
        {
            staffel.Rabatt = MathExtensions.BerechneProzent(preis, Input.ARTI_N_VK1);
            return Task.CompletedTask;
        }

        private Task StaffelrabattChangedAsync(Staffelpreis staffel, decimal rabatt)
        {
            staffel.Preis = MathExtensions.BerechnePreis(Input.ARTI_N_VK1, rabatt);
            return Task.CompletedTask;
        }
        public async Task ArtikelEtikettDruckenAsync(string text)
        {
            if (!String.IsNullOrWhiteSpace(Input.Artikelnummer))
            {
                for (int i = 0; i < _anzahlEtiketten; i++)
                {
                    await WK5.Core.Drucken.PrintEtikett.Print(text, jsRuntime);
                }
            }
        }

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

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

                SperreDurchAnderenUser = true;
            }
        }
        #endregion

        #region Hotkeys
        public async Task HandleCtrlPlus()
        {
            bool noneFound = false;
            switch (ActiveTab)
            {
                case ArtikelTabs.Lieferanten:
                    if (_lieferantenArtikelList is not null)
                    {
                        await _lieferantenArtikelList.AddLieferantenArtikelAsync();
                        noneFound = true;
                    }
                    break;
                case ArtikelTabs.Bilder:
                    _showBilderFileBrowserModal = true;
                    break;
                case ArtikelTabs.Dokumente:
                    _showDokumenteFileBrowserModal = true;
                    break;
                case ArtikelTabs.Zubehör:
                    _showZubehörArtikelSuche = true;
                    break;
                default:
                    noneFound = true;
                    break;
            }

            if (!noneFound)
            {
                StateHasChanged();
            }
        }

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

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

                found = true;
            }

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

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

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

                found = true;
            }

            ActiveTab = (ArtikelTabs)tabIndex;
            StateHasChanged();
            return Task.CompletedTask;
        }
        #endregion

    }
}
