using KarleyLibrary.Attributes;
using System.Linq;

namespace WK5.Core.Models.Bestellungen
{
    public class AuftragBestellenLieferantArtikel
    {
        private decimal _mindestabnahme = 1;

        public string Artikelnummer { get; set; }
        public AuftragBestellenLieferant Lieferant { get; set; }
        [CompareField("ARLI_A_BESTELLNR")]
        public string? Bestellnummer { get; set; }
        [CompareField("ARLI_L_HAUPTLIEFERANT")]
        public bool IstHauptlieferant { get; set; }
        [CompareField("ARLI_N_PREIS")]
        public decimal Preis { private get; set; }
        [CompareField("ARLI_N_RABATT")]
        public decimal Rabatt1 { private get; set; }
        [CompareField("ARLI_N_RABATT2")]
        public decimal Rabatt2 { private get; set; }
        [CompareField("ARLI_N_MINDESTABNAHME")]
        public decimal Mindestabnahme { get => _mindestabnahme; set => _mindestabnahme = value <= 0 ? 1 : value; }

        [CompareField("LIEFERANTEN_BESTAND")]
        public decimal Bestand { get; set; }
        [CompareField("ARLI_A_BEZ1")]
        public string? Bezeichnung1 { get; set; }
        [CompareField("ARLI_A_BEZ2")]
        public string? Bezeichnung2 { get; set; }
        [CompareField("ARLI_A_BEZ3")]
        public string? Bezeichnung3 { get; set; }
        [CompareField("ARLI_A_BEZ4")]
        public string? Bezeichnung4 { get; set; }
        [CompareField("ARLI_A_BEZ5")]
        public string? Bezeichnung5 { get; set; }

        [CompareField("ARLI_B_NOTIZ")]
        public string? Langtext { get; set; }
        [CompareField("ARLI_N_MENGE1")]
        public decimal StaffelMenge1 { get; set; }
        [CompareField("ARLI_N_MENGE2")]
        public decimal StaffelMenge2 { get; set; }
        [CompareField("ARLI_N_MENGE3")]
        public decimal StaffelMenge3 { get; set; }
        [CompareField("ARLI_N_MENGE4")]
        public decimal StaffelMenge4 { get; set; }

        [CompareField("ARLI_N_PREISMENGE1")]
        public decimal StaffelPreis1 { get; set; }
        [CompareField("ARLI_N_PREISMENGE2")]
        public decimal StaffelPreis2 { get; set; }
        [CompareField("ARLI_N_PREISMENGE3")]
        public decimal StaffelPreis3 { get; set; }
        [CompareField("ARLI_N_PREISMENGE4")]
        public decimal StaffelPreis4 { get; set; }

        [CompareField("ARLI_N_RABATTMENGE1")]
        public decimal StaffelRabatt1 { get; set; }
        [CompareField("ARLI_N_RABATTMENGE2")]
        public decimal StaffelRabatt2 { get; set; }
        [CompareField("ARLI_N_RABATTMENGE3")]
        public decimal StaffelRabatt3 { get; set; }
        [CompareField("ARLI_N_RABATTMENGE4")]
        public decimal StaffelRabatt4 { get; set; }
        [CompareField("ARLI_L_NURVIELFACHES")]
        public bool NurVielfaches { get; set; }

        /// <summary>
        /// Liefert den Preis abzüglich aller Rabatte.
        /// <para>
        /// Staffelpreise werden ebenfalls berücksichtigt.
        /// </para>
        /// </summary>
        public decimal PreisMitRabatt(decimal menge)
        {
            if (StaffelMenge4 != 0 && StaffelMenge4 <= menge)
            {
                return (StaffelPreis4 > 0 ? StaffelPreis4 : Preis) * (100 - StaffelRabatt4) / 100;
            }
            else if (StaffelMenge3 != 0 && StaffelMenge3 <= menge)
            {
                return (StaffelPreis3 > 0 ? StaffelPreis3 : Preis) * (100 - StaffelRabatt3) / 100;

            }
            else if (StaffelMenge2 != 0 && StaffelMenge2 <= menge)
            {
                return (StaffelPreis2 > 0 ? StaffelPreis2 : Preis) * (100 - StaffelRabatt2) / 100;
            }
            else if (StaffelMenge1 != 0 && StaffelMenge1 <= menge)
            {
                return (StaffelPreis1 > 0 ? StaffelPreis1 : Preis) * (100 - StaffelRabatt1) / 100;
            }
            else
            {
                // Kein Staffelpreis gefunden, also rechnen wir auf Basis des normalen Preises und Rabattes.
                decimal preis = Preis;

                if (Rabatt1 > 0)
                {
                    preis *= (100 - Rabatt1) / 100;
                }

                if (Rabatt2 > 0)
                {
                    preis *= (100 - Rabatt2) / 100;
                }

                return preis;
            }
        }

        public decimal GetPreis(decimal menge)
        {
            var (staffelMenge, staffelPreis, _) = GetStaffelpreis(menge);

            // Default von decimal ist 0, wenn also 0, dann gibt es keine Staffelmenge.
            return staffelMenge > 0 ? staffelPreis : Preis;
        }

        /// <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 staffelPreis, decimal staffelRabatt) GetStaffelpreis(decimal menge)
        {
            // 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 staffelPreis, decimal staffelRabatt)[] staffelpreise = new (decimal, decimal, decimal)[]
            {
                (StaffelMenge1, Preis, StaffelRabatt1),
                (StaffelMenge2, Preis, StaffelRabatt2),
                (StaffelMenge3, Preis, StaffelRabatt3),
                (StaffelMenge4, Preis, StaffelRabatt4)
            };

            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)
        {
            var (staffelMenge, _, staffelRabatt) = GetStaffelpreis(menge);
            // 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) : (Rabatt1, Rabatt2);
        }

        public AuftragBestellenLieferantArtikel(string artikelnummer, AuftragBestellenLieferant lieferant)
        {
            Artikelnummer = artikelnummer;
            Lieferant = lieferant;
        }
    }
}
