using KarleyLibrary.Attributes;
using KarleyLibrary.Erweiterungen;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using WK5.Core.Basis.Erweiterungen;
using WK5.Core.Services;

namespace WK5.Core.Models
{
    public class Artikel
    {
        #region Felder
        private decimal _bestand = 0;
        private string _artikelnummer = String.Empty;
        private string _wartungsText = string.Empty;
        private string _hersteller = string.Empty;
        private string _bezeichnung1 = String.Empty;
        private string _bezeichnung2 = String.Empty;
        private string _bezeichnung3 = String.Empty;
        private string _bezeichnung4 = String.Empty;
        private string _bezeichnung5 = String.Empty;
        private string _herstellernummer = string.Empty;
        private string _lagerplatz = string.Empty;
        private string _selektionsmerkmal1 = string.Empty;
        private string _selektionsmerkmal2 = string.Empty;
        private string _selektionsmerkmal3 = string.Empty;
        private string _warengruppe = string.Empty;
        private string _unterwarengruppe = string.Empty;
        private string _langtext = string.Empty;
        private string _notiz = string.Empty;
        private string _preisgruppe = string.Empty;
        private bool _fixVK3;
        private bool _fixVK4;
        private bool _fixVK5;
        private bool _inaktivNachAbverkauf;
        private bool _istDienstleistung;
        private bool _istAbverkauf;
        private string _packtext = string.Empty;
        #endregion
        #region Datenbankfelder
        [CompareField("ARTI_A_BEZ1")]
        public string Bezeichnung1 { get => _bezeichnung1; set => _bezeichnung1 = value ?? string.Empty; }
        [CompareField("ARTI_A_BEZ2")]
        public string Bezeichnung2 { get => _bezeichnung2; set => _bezeichnung2 = value ?? string.Empty; }
        [CompareField("ARTI_A_BEZ3")]
        public string Bezeichnung3 { get => _bezeichnung3; set => _bezeichnung3 = value ?? string.Empty; }
        [CompareField("ARTI_A_BEZ4")]
        public string Bezeichnung4 { get => _bezeichnung4; set => _bezeichnung4 = value ?? string.Empty; }
        [CompareField("ARTI_A_BEZ5")]
        public string Bezeichnung5 { get => _bezeichnung5; set => _bezeichnung5 = value ?? string.Empty; }
        public string? ARTI_A_BEZETIKETT { get; set; }
        public string? ARTI_A_EAN { get; set; }
        public string ARTI_A_EINHEIT { get; set; } = String.Empty;
        public string? ARTI_A_ERSATZART { get; set; }
        public string? ARTI_A_G_RASTER { get; set; }
        [CompareField("ARTI_A_HERST_NR")]
        public string Herstellernummer { get => _herstellernummer; set => _herstellernummer = value ?? string.Empty; }
        [CompareField("ARTI_A_HERSTELLER")]
        public string Hersteller { get => _hersteller; set => _hersteller = value ?? string.Empty; }
        [CompareField("ARTI_A_LAGER")]
        public string Lagerplatz { get => _lagerplatz; set => _lagerplatz = value ?? string.Empty; }
        public string? ARTI_A_LAGER2 { get; set; }
        public string? ARTI_A_LAGER3 { get; set; }
        public string? ARTI_A_NACHFOLGER { get; set; }
        [CompareField("ARTI_A_NR")]
        public string Artikelnummer { get => _artikelnummer; set => _artikelnummer = (value ?? string.Empty).ToUpper(); }
        public string? ARTI_A_POSBEZEICH { get; set; }
        public string? ARTI_A_PREISEINHEIT { get; set; }
        [CompareField("ARTI_A_PREISGRUPPE")]
        public string Preisgruppe { get => _preisgruppe; set => _preisgruppe = value ?? string.Empty; }
        public string? ARTI_A_PRODLAGER { get; set; }
        [CompareField("ARTI_A_SELEKTION1")]
        public string Selektionsmerkmal1 { get => _selektionsmerkmal1; set => _selektionsmerkmal1 = value ?? string.Empty; }
        [CompareField("ARTI_A_SELEKTION2")]
        public string Selektionsmerkmal2 { get => _selektionsmerkmal2; set => _selektionsmerkmal2 = value ?? string.Empty; }
        [CompareField("ARTI_A_SELEKTION3")]
        public string Selektionsmerkmal3 { get => _selektionsmerkmal3; set => _selektionsmerkmal3 = value ?? string.Empty; }
        public string? ARTI_A_STAFFELWAEHR { get; set; }
        [CompareField("ARTI_A_UNTERWARENG")]
        public string Unterwarengruppe { get => _unterwarengruppe; set => _unterwarengruppe = value ?? string.Empty; }
        public string? ARTI_A_URSPRUNGSLAND { get; set; }
        public string? ARTI_A_VORGAENGER { get; set; }
        [CompareField("ARTI_A_WARENGRUPPE")]
        public string Warengruppe { get => _warengruppe; set => _warengruppe = value ?? string.Empty; }
        public string? WK5_ARTI_A_HINWEIS { get; set; }


        [CompareField("ARTI_B_LANGTEXT")]
        public string Langtext { get => _langtext; set => _langtext = value ?? string.Empty; }
        [CompareField("ARTI_B_NOTIZ")]
        public string Notiz { get => _notiz; set => _notiz = value ?? string.Empty; }

        public DateTime ARTI_D_ERFASSDATUM { get; set; }
        public DateTime ARTI_TIMESTAMP { get; set; }
        public DateTime WK5_ARTI_D_SUPPORT_VALID_UNTIL { get; set; }

        public bool ARTI_L_ABMASSVERWALTUNG { get; set; }
        public bool ARTI_L_ABVERKAUF { get => ARTI_L_DIENSTLEIST ? false : _istAbverkauf; set => _istAbverkauf = value; }
        public bool ARTI_L_DIENSTLEIST { get => ARTI_L_LAGERFUEHR ? false : _istDienstleistung; set => _istDienstleistung = value; }
        public bool ARTI_L_ERSATZEIL { get; set; }
        public bool ARTI_L_FAXLISTE { get; set; }
        public bool ARTI_L_FERTIGUNG { get; set; }
        public bool ARTI_L_FIXPREIS { get; set; }
        public bool ARTI_L_FIXVK3 { get => ARTI_L_FIXPREIS || _fixVK3; set => _fixVK3 = value; }
        public bool ARTI_L_FIXVK4 { get => ARTI_L_FIXPREIS || _fixVK4; set => _fixVK4 = value; }
        public bool ARTI_L_FIXVK5 { get => ARTI_L_FIXPREIS || _fixVK5; set => _fixVK5 = value; }
        public bool ARTI_L_INAKT_ABVER { get => ARTI_L_DIENSTLEIST ? false : _inaktivNachAbverkauf; set => _inaktivNachAbverkauf = value; }
        public bool ARTI_L_INAKTIV { get; set; }
        public bool ARTI_L_INTERNET { get; set; }
        public bool ARTI_L_KAPAZITAET { get; set; }
        public bool ARTI_L_LAGERFUEHR { get; set; }
        public bool ARTI_L_LANGTEXT_DR { get; set; }
        public bool ARTI_L_NICHT_IN_BELEGEN { get; set; }
        public bool ARTI_L_NORMTEIL { get; set; }
        public bool ARTI_L_OHNE_DRUCK { get; set; }
        public bool ARTI_L_OHNE_PROV { get; set; }
        public bool ARTI_L_PREISLISTE { get; set; }
        public bool ARTI_L_PRUEFPLAN { get; set; }
        public bool ARTI_L_RABATTAUSSCHLUSS { get; set; }
        public bool ARTI_L_RESTEVERWALTUNG { get; set; }
        public bool ARTI_L_SCHWVERFUEG { get; set; }
        public bool ARTI_L_SN { get; set; }
        public bool ARTI_L_SN_ABGANG { get; set; }
        public bool ARTI_L_SN_EINGANG { get; set; }
        public bool ARTI_L_STL_VEREDELUNG { get; set; }
        public bool ARTI_L_VERBRAUCH { get; set; }
        public bool ARTI_L_VERSCHLEISS { get; set; }
        public bool WK5_ARTI_L_SUPPORT_AGREEMENT { get; set; }
        public bool WK5_ARTI_L_KEIN_ZPU { get; set; }
        public bool WK5_ARTI_L_KEIN_TEXT_UPDATE { get; set; }
        public bool WK5_ARTI_L_HAUPTARTIKEL { get; set; }

        [CompareField("ARTI_N_BREITE")]
        public decimal Breite { get; set; }
        public decimal ARTI_N_BRUTTO { get; set; }
        /// <summary>
        /// Stellt die Mindestabnahme dar
        /// </summary>
        public int ARTI_N_COLLI { get; set; } = 1;
        public decimal ARTI_N_EK { get; set; }
        public int ARTI_N_ERLOESKONTO { get; set; }
        public decimal ARTI_N_FLAECHE { get; set; }
        public decimal ARTI_N_GEWICHT { get; set; }
        public decimal ARTI_N_HOEHE { get; set; }
        public int ARTI_N_KONFIGURATOR { get; set; }
        public decimal ARTI_N_LAENGE { get; set; }
        public int ARTI_N_LASTUSER { get; set; }
        public decimal ARTI_N_MAXBESTAND { get; set; }
        public decimal ARTI_N_MAXRABATT { get; set; }
        [CompareField("ARTI_N_MINBESTAND")]
        public decimal Mindestbestand { get; set; }
        public decimal ARTI_N_MIND_VK { get; set; }
        public int ARTI_N_MINDAUFSCHL { get; set; }
        public int ARTI_N_MWSTKENNUNG { get; set; }
        public int ARTI_N_PREISEINHEITFAKTOR { get; set; }
        public int ARTI_N_RUECKL_ADR { get; set; }
        public decimal ARTI_N_STAERKE { get; set; }
        public decimal ARTI_N_STAFFELM1 { get; set; }
        public decimal ARTI_N_STAFFELM2 { get; set; }
        public decimal ARTI_N_STAFFELM3 { get; set; }
        public decimal ARTI_N_STAFFELM4 { get; set; }
        public decimal ARTI_N_STAFFELM5 { get; set; }
        public decimal ARTI_N_STAFFELP1 { get; set; }
        public decimal ARTI_N_STAFFELP2 { get; set; }
        public decimal ARTI_N_STAFFELP3 { get; set; }
        public decimal ARTI_N_STAFFELP4 { get; set; }
        public decimal ARTI_N_STAFFELP5 { get; set; }
        public decimal ARTI_N_STAFFELR1 { get; set; }
        public decimal ARTI_N_STAFFELR2 { get; set; }
        public decimal ARTI_N_STAFFELR3 { get; set; }
        public decimal ARTI_N_STAFFELR4 { get; set; }
        public decimal ARTI_N_STAFFELR5 { get; set; }
        public decimal ARTI_N_VK1 { get; set; }
        public decimal ARTI_N_VK1BRUTTO { get; set; }
        public decimal ARTI_N_VK2 { get; set; }
        public decimal ARTI_N_VK3 { get; set; }
        public decimal ARTI_N_VK4 { get; set; }
        public decimal ARTI_N_VK5 { get; set; }
        public int ARTI_N_WO_KAPAZITAET { get; set; }
        [CompareField("ARTI_N_ZOLLTARIF")]
        public int ZolltarifId { get; set; }

        public decimal WK5_ARTI_N_HOEHE_VERPACKUNG { get; set; }
        public decimal WK5_ARTI_N_LAENGE_VERPACKUNG { get; set; }
        public decimal WK5_ARTI_N_BREITE_VERPACKUNG { get; set; }

        public int WK5_ARTI_N_KOSTENSTELLE { get; set; }
        public int WK5_ARTI_N_SUPPORT_DOCID { get; set; }
        public decimal WK5_ARTI_N_PRODUKTGEWICHT { get; set; }
        public int WK5_ARTI_N_WICHTIGKEIT { get; set; } = 0;
        public decimal WK5_ARTI_N_MUELL_PLASTIK { get; set; }
        public decimal WK5_ARTI_N_MUELL_VERBUNDSTOFF { get; set; }
        public decimal WK5_ARTI_N_MUELL_PAPIER { get; set; }
        public decimal WK5_ARTI_N_MUELL_ALUMINIUM { get; set; }
        public decimal WK5_ARTI_N_VIRT_LAGER { get; set; }
        public decimal WK5_ARTI_N_GEBINDE { get; set; }
        [CompareField("WK5_ARTI_N_ANGEBOTVORLAGE")]
        public int AngebotsnummerVorlage { get; set; }
        [CompareField("WK5_ARTI_D_LAST_PREIS_CHANGE")]
        public DateTime LetzePreisÄnderung { get; set; }
        [CompareField("ARTI_N_WARTUNGSINTERVALL")]
        public int Wartungsintervall { get; set; }
        [CompareField("ARTI_N_PREISOPTION_ONLINE")]
        public int PreisoptionOnline { get; set; } = 1;

        public bool WK5_ARTI_L_KEINE_ELEKTRONIK { get; set; } = false;
        #endregion

        public DateTime ARWE_D_LETZBEWEG { get; set; }
        public DateTime ARWE_D_LETZTEREKDATUM { get; set; }
        public DateTime ARWE_D_INVENTDATUM { get; set; }        

        /// <summary>
        /// Der Physische Bestand an Lager
        /// </summary>
        [CompareField("ARWE_N_BESTAND")]
        public decimal Bestand
        {
            get
            {
                if (!IstBundle)
                {
                    return _bestand;
                }
                else
                {
                    Dictionary<string, decimal> stklMengen = new Dictionary<string, decimal>();

                    foreach (Artikel artikel in BundleArtikel)
                    {
                        if (stklMengen.ContainsKey(artikel.Artikelnummer))
                        {
                            stklMengen[artikel.Artikelnummer] += artikel.BUNDLE_N_MENGE;
                        }
                        else
                        {
                            stklMengen.Add(artikel.Artikelnummer, artikel.BUNDLE_N_MENGE);
                        }
                    }

                    decimal minAmount = Int32.MaxValue;

                    foreach (Artikel artikel in BundleArtikel)
                    {
                        decimal teiler = stklMengen[artikel.Artikelnummer];

                        // Es kann vorkommen, dass jemand für eine Stückliste vergessen hat eine Menge zu hinterlegen
                        // Dann würden wir durch 0 teilen und eine DivisionByZeroException auslösen
                        // Deshalb geben wir -1 zurück, wenn keine Menge vorhanden ist
                        // Das hat den Vorteil, dass der Auftrag nicht automatisch freigegeben wird, da der Bestand nicht ausreichend ist
                        if (teiler == 0)
                        {
                            return -1;
                        }

                        decimal bestand = artikel.Bestand / teiler;
                        if (bestand >= 0 && bestand < minAmount)
                        {
                            minAmount = bestand;
                        }
                    }

                    return (int)Math.Floor(minAmount);
                }
            }
            set => _bestand = value;
        }
        [CompareField("ARWE_N_BEDARF")]
        public decimal Bedarf { get; set; }
        [CompareField("ARWE_N_OFFBESTELL")]
        public decimal Bestellt { get; set; }
        public decimal Frei => Bestand - Bedarf;
        public decimal MWST_N_PROZENT { get; set; }

        public bool WK5_ARTI_L_ANFRAGEARTIKEL { get; set; }
        public bool WK5_ARTI_L_ETIKETTENBRIEF { get; set; }
        public bool WK5_ARTI_L_AUFGABE_TECHNIK { get; set; }
        public string? WK5_ARTI_A_SUCHBEGRIFF { get; set; }

        public bool ARTI_L_MIETE { get; set; }
        public string ARTI_B_PACKTEXT { get => _packtext; set => _packtext = value ?? string.Empty; }
        public DateTime LetzteBewegung { get; set; }
        public decimal DurchschnittsEinkaufspreis { get; set; }
        [CompareField("ARTI_B_WARTUNGSTEXT")]
        public string WartungsText { get => _wartungsText; set => _wartungsText = value ?? string.Empty; }
        public StaffelpreisCollection Staffelpreise { get; set; } = new StaffelpreisCollection(5);
        public List<ArtikelAngebot> Sonderangebote { get; set; } = new List<ArtikelAngebot>();
        public List<ArtikelBild> Bilder { get; set; } = new List<ArtikelBild>();
        public List<ArtikelDokument> Dokumente { get; set; } = new List<ArtikelDokument>();
        public decimal Preis1Prozent { get; set; }
        public decimal Preis2Prozent { get; set; }
        public decimal Preis3Prozent { get; set; }
        public decimal Preis4Prozent { get; set; }
        public decimal Preis5Prozent { get; set; }
        public decimal Preis6Prozent { get; set; }

        public string GetBezeichnung() => Regex.Replace($"{Bezeichnung1} {Bezeichnung2} {Bezeichnung3} {Bezeichnung4} {Bezeichnung5}", "  +/g", " ").Trim();
        public async Task<decimal> GetEinkaufspreis(List<Lieferantenartikel>? liefArtikel = null)
        {
            using FbController2 fbController = new FbController2();
            ArtikelService artikelService = new ArtikelService();

            
            if (IstBundle)
            {
                decimal tmp = 0.0m;

                foreach (Artikel bundleArtikel in BundleArtikel)
                {
                    Artikel? tmpArti = await artikelService.GetAsync(bundleArtikel.Artikelnummer, fbController);
                    if (tmpArti is not null)
                    {
                        decimal ek = await tmpArti.GetEinkaufspreis();
                        if (ek != tmpArti.ARTI_N_EK)
                        {
                            await artikelService.UpdateArtikelEinkaufspreisAsync(tmpArti.Artikelnummer, ek, fbController);
                        }
                        tmp += ek * bundleArtikel.BUNDLE_N_MENGE;
                    }
                }
                return tmp;
            }
            else
            {
                if (liefArtikel is null || liefArtikel.Count <= 0)
                {
                    liefArtikel = await Lieferantenartikel.GetLieferantenartikelAsync(Artikelnummer, fbController).ToListAsync();
                }

                if (liefArtikel.Count <= 0)
                {
                    return ARTI_N_EK;
                }

                if (liefArtikel.Where(x => x.ARLI_L_HAUPTLIEFERANT).Any())
                {
                    var arti = liefArtikel.Where(x => x.ARLI_L_HAUPTLIEFERANT).First();
                    decimal preis = MathExtensions.BerechnePreis(arti.ARLI_N_PREIS, arti.ARLI_N_RABATT);
                    preis = MathExtensions.BerechnePreis(preis, arti.ARLI_N_RABATT2);

                    return preis;
                }

                var possibles = liefArtikel.Where(x => (DateTime.Now - x.ARLI_D_LETZAEND).TotalDays <= 14 && x.ARLI_N_PREIS > 0 && x.ARLI_N_LIEFNR != 70246 && x.WK5_ARLI_N_LIEFBESTAND > 0);

                if (possibles.Any())
                {
                    return possibles.Min(x => x.ARLI_N_PREIS * ((100 - x.ARLI_N_RABATT) / 100));
                }
                else
                {
                    var maxPossibles = liefArtikel.Where(x => x.ARLI_N_PREIS > 0 && x.ARLI_N_LIEFNR != 70246);

                    if (maxPossibles.Any())
                    {
                        return maxPossibles.Max(x => x.ARLI_N_PREIS * ((100 - x.ARLI_N_RABATT) / 100));
                    }
                }
            }
            return 0.0m;
        }
        public StaffelpreisCollection GetStaffelpreise()
        {
            StaffelpreisCollection artikelStaffelCollection = new StaffelpreisCollection(5);
            artikelStaffelCollection.SetBezugspreis(ARTI_N_VK1);
            artikelStaffelCollection.Add(ARTI_N_STAFFELM1, ARTI_N_STAFFELP1, ARTI_N_STAFFELR1);
            artikelStaffelCollection.Add(ARTI_N_STAFFELM2, ARTI_N_STAFFELP2, ARTI_N_STAFFELR2);
            artikelStaffelCollection.Add(ARTI_N_STAFFELM3, ARTI_N_STAFFELP3, ARTI_N_STAFFELR3);
            artikelStaffelCollection.Add(ARTI_N_STAFFELM4, ARTI_N_STAFFELP4, ARTI_N_STAFFELR4);
            artikelStaffelCollection.Add(ARTI_N_STAFFELM5, ARTI_N_STAFFELP5, ARTI_N_STAFFELR5);
            return artikelStaffelCollection;
        }

        #region Bundles
        public Artikel? Parent { get; set; }
        public List<Artikel> BundleArtikel { get; set; } = new();
        [CompareField("ARTI_L_BUNDLE")]
        public bool IstBundle { get; set; }

        public decimal BUNDLE_N_MENGE { get; set; }
        public int BUNDLE_N_SORT { get; set; }
        #endregion

        public (decimal preis, decimal rabatt, string rabattbezeichnung) GetPreis(decimal menge, int preislisteId)
        {
            var (staffelMenge, staffelRabatt) = GetStaffelrabatt(menge, preislisteId);

            // 05.01.2022 MK: Die Preise sollen nur noch als Rabatte berechnet werden und sich immer auf den Firmenpreis beziehen.
            
            decimal preis_nach_preisliste = GetPreis(preislisteId);

            if(preis_nach_preisliste > 0 && preis_nach_preisliste != ARTI_N_VK1)
            {
                decimal rabatt_nach_preisliste = MathExtensions.BerechneProzent(preis_nach_preisliste, ARTI_N_VK1);

                if(rabatt_nach_preisliste > staffelRabatt)
                {
                    // Händlerrabatte haben eine gesonderte Rabattbezeichnung
                    if(preislisteId is 3)
                    {
                        return (ARTI_N_VK1, rabatt_nach_preisliste, "Händlerrabatt");
                    }

                    return (ARTI_N_VK1, rabatt_nach_preisliste, "Sonderpreis");
                }
            }

            // Default von decimal ist 0, wenn also 0, dann gibt es keine Staffelmenge.
            if (staffelMenge > 0)
            {
                return (ARTI_N_VK1, staffelRabatt, "Staffelpreis");
            }
            else
            {
                return (ARTI_N_VK1, 0, string.Empty);
            }
            
        }

        private decimal GetPreis(int preislisteId) => preislisteId switch
        {
            1 => ARTI_N_BRUTTO,
            2 => ARTI_N_VK1,
            3 => ARTI_N_VK2,
            4 => ARTI_N_VK3,
            5 => ARTI_N_VK4,
            6 => ARTI_N_VK5,
            _ => ARTI_N_VK1
        };

        /// <summary>
        /// Prüft ob es für die übergebene Menge einen Staffelpreis gibt und gibt diesen zurück.
        /// </summary>
        /// <param name="menge"></param>
        /// <returns>Wenn kein Staffelpreis gefunden wurde, dann ist staffelMenge 0. Ansonsten liefert die Funktion ein Tuple mit der Menge, dem Preis und Rabatt zurück.</returns>
        private (decimal staffelMenge, decimal staffelRabatt) GetStaffelrabatt(decimal menge, int preislisteId)
        {
            // Die Staffelpreise können in der W4 in einer falschen Reihenfolge hinterlegt sein, daher packen wir alle Staffelpreise in ein Array und sortieren manuell
            (decimal staffelMenge, decimal staffelRabatt)[] staffelpreise = new (decimal, decimal)[]
            {
                (ARTI_N_STAFFELM1, ARTI_N_STAFFELR1),
                (ARTI_N_STAFFELM2, ARTI_N_STAFFELR2),
                (ARTI_N_STAFFELM3, ARTI_N_STAFFELR3),
                (ARTI_N_STAFFELM4, ARTI_N_STAFFELR4),
                (ARTI_N_STAFFELM5, ARTI_N_STAFFELR5)
            };

            var sucheStaffelpreis = staffelpreise.Where(x => x.staffelMenge > 0 && x.staffelMenge <= menge).OrderByDescending(x => x.staffelMenge);
            return sucheStaffelpreis.FirstOrDefault();
        }

        /// <summary>
        /// Holt die Rabatte für den Lieferantenartikel in Abhängigkeit der Bestellmenge zur Staffelmenge
        /// </summary>
        /// <param name="menge"></param>
        /// <returns></returns>
        public (decimal rabatt1, decimal rabatt2) GetRabatte(decimal menge, int preislisteId)
        {
            var (staffelMenge, staffelRabatt) = GetStaffelrabatt(menge, preislisteId);
            // Wenn es einen Staffelpreis gibt, dann ist Rabatt2 immer 0, da wir auf den Staffelpreis keinen zweiten Rabatt gewähren.
            return staffelMenge > 0 ? (staffelRabatt, 0) : (0, 0);
        } 

        public static async Task<ArtikelBild?> GetArtikelHauptImageAsync(string artikelnummer)
        {
            return await ArtikelBild.GetHauptBildAsync(artikelnummer);
        }


        /// <summary>
        /// Erstellt ein Dictionary das als Key die Assoziationsnnummer enthält und als Value unsere Artikelnummer
        /// </summary>
        /// <returns>Gibt ein Objekt der Klasse <see cref="Dictionary{TKey, TValue}"/> wo TKey ein <see cref="string"/> ist und TValue ein <see cref="string"/> ist</returns>
        public static async IAsyncEnumerable<KeyValuePair<string, string>> GetReplaceArtikelnummernAsync(FbController2 fbController)
        {
            DataTable data = await fbController.SelectDataAsync("SELECT * FROM WK5_ARTIKELNUMMER_REPLACE");

            Dictionary<string, string> replaces = new Dictionary<string, string>();
            foreach (DataRow row in data.Rows)
            {
                yield return new KeyValuePair<string, string>(row["REPLACE_A_PRODUKT"].ToString()!, row["REPLACE_A_UNSERE"].ToString()!);

            }
        }

        public static async Task<bool> Exists(string ARTI_A_NR)
        {
            using FbController2 fbController = new FbController2();
            fbController.AddParameter("@ARTI_A_NR", ARTI_A_NR);
            object? amount = await fbController.FetchObjectAsync("SELECT COUNT(*) FROM ARTIKEL WHERE ARTI_A_NR = @ARTI_A_NR");
            return amount is not null && Convert.ToInt32(amount) > 0;
        }

     

       
        [SupportedOSPlatform("windows")]
        public void PrintEtikett()
        {

            var writer = new ZXing.Windows.Compatibility.BarcodeWriter()
            {
                Format = ZXing.BarcodeFormat.DATA_MATRIX
            };

            var barcode = writer.Write(Artikelnummer);
            Bitmap etikett = new Bitmap(415, 207);

            using (Graphics g = Graphics.FromImage(etikett))
            {
                g.CompositingQuality = CompositingQuality.HighQuality;
                g.InterpolationMode = InterpolationMode.High;
                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                barcode = barcode.ResizeImage(150, 150);
                g.DrawImage(barcode, new Point((etikett.Width / 2) - (barcode.Width / 2), 10));

                string tmpArtikelnummer = Artikelnummer.Length > 27 ? Artikelnummer[0..27] : Artikelnummer;
                Font font = new Font("Printer Display Font 1", 15f);
                SizeF textSize = g.MeasureString(tmpArtikelnummer, font);


                // Resize text to fit on Bitmap
                while (textSize.Width > (etikett.Width - 10) || textSize.Height > etikett.Height)
                {
                    font = new Font(font.FontFamily, font.Size - 0.1f, font.Style, font.Unit);
                    textSize = g.MeasureString(tmpArtikelnummer, font);
                }

                float xText = (etikett.Width / 2) - (textSize.Width / 2);
                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                g.DrawString(tmpArtikelnummer, font, new SolidBrush(Color.Black), new PointF(xText, 165));
            }


            Printer.Print(etikett.ImageToByte(), GlobalConfig.GetArtikeletikettenPrinter());
            etikett.Save(Path.Combine(GlobalConfig.Configuration.OutputPfad, $"{Artikelnummer}.png"));
        }
        
        public void RecalculatePreise(Preisgruppe? preisgruppe)
        {


            RecalculateProzente(preisgruppe);
            if (!ARTI_L_FIXPREIS)
            {

                if (preisgruppe is not null)
                {
                    //ListenPreisBrutto = pg.GetAbschlagVK(EK, 1);
                    ARTI_N_VK1 = preisgruppe.GetAbschlagVK(ARTI_N_EK, 2);
                    ARTI_N_VK2 = preisgruppe.GetAbschlagVK(ARTI_N_EK, 3);
                    if (!ARTI_L_FIXVK4)
                    {
                        ARTI_N_VK3 = preisgruppe.GetAbschlagVK(ARTI_N_EK, 4);
                    }

                    if (!ARTI_L_FIXVK4)
                    {
                        ARTI_N_VK4 = preisgruppe.GetAbschlagVK(ARTI_N_EK, 5);
                    }

                    if (!ARTI_L_FIXVK5)
                    {
                        ARTI_N_VK5 = preisgruppe.GetAbschlagVK(ARTI_N_EK, 6);
                    }
                }
            }
        }

        public void RecalculateProzente(Preisgruppe? preisgruppe)
        {
            Preis1Prozent = GetPreislistenProzent(1, ARTI_N_EK, preisgruppe);
            Preis2Prozent = GetPreislistenProzent(2, ARTI_N_EK, preisgruppe);
            Preis3Prozent = GetPreislistenProzent(3, ARTI_N_EK, preisgruppe);
            Preis4Prozent = GetPreislistenProzent(4, ARTI_N_EK, preisgruppe);
            Preis5Prozent = GetPreislistenProzent(5, ARTI_N_EK, preisgruppe);
            Preis6Prozent = GetPreislistenProzent(6, ARTI_N_EK, preisgruppe);
        }

        public decimal GetPreislistenProzent(int i, decimal ek, Preisgruppe? preisgruppe)
        {
            decimal preis = i switch
            {
                1 => ARTI_N_BRUTTO,
                2 => ARTI_N_VK1,
                3 => ARTI_N_VK2,
                4 => ARTI_N_VK3,
                5 => ARTI_N_VK4,
                6 => ARTI_N_VK5,
                _ => 0.0m,
            };

            if (preis <= 0.0m)
            {
                return 0.0m;
            }

            bool fixpreis = i switch
            {
                1 => ARTI_L_FIXPREIS,
                2 => ARTI_L_FIXPREIS,
                3 => ARTI_L_FIXPREIS,
                4 => ARTI_L_FIXVK3,
                5 => ARTI_L_FIXVK4,
                6 => ARTI_L_FIXVK5,
                _ => false
            };

            if (!fixpreis && preisgruppe is not null)
            {
                return preisgruppe.GetPreislistenProzent(i);
            }
            else
            {
                return (1 - ek / preis) * 100;
            }
        }
    }
}