using KarleyLibrary.Attributes;
using KarleyLibrary.Erweiterungen;
using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;
using WK5.Core.Services;

namespace WK5.Core.Models.Lager
{
    public class Zugang
    {
        private string _lief_a_name1 = String.Empty;
        private string _lief_a_kundennr = String.Empty;
        private string _lief_a_land = String.Empty;
        private string _lief_a_bic = String.Empty;
        private string _lief_a_iban = String.Empty;
        private string? _zuga_a_re_nr;
        private string _inputRechnungsnummer = String.Empty;

        public int ZUGA_N_NR { get; set; }
        public int ZUGA_N_LIEF { get; set; }
        public DateTime ZUGA_D_DATUM { get; set; }
        public string? ZUGA_A_LS_NR { get; set; }
        public DateTime ZUGA_D_LS_DATUM { get; set; }
        public DateTime ZUGA_D_RE_DATUM { get; set; }
        public decimal ZUGA_N_NETTO { get; set; }
        public decimal ZUGA_N_TRANSPORT { get; set; }
        [Obsolete("Mit diesem Wert sollt enicht gerechnet werden. Verwenden Sie stattdessen WK5_ZUGA_N_MWST")]
        public decimal ZUGA_N_MWST { get; set; }
        public bool ZUGA_L_MWST { get; set; }
        public decimal ZUGA_N_ZAHLTBETR { get; set; }
        public DateTime ZUGA_D_ZAHLDATUM { get; set; }
        public bool ZUGA_L_GEBUCHT { get; set; }
        public bool ZUGA_L_INPRUEFUNG { get; set; }
        public DateTime ZUGA_D_INPRUEFUNG { get; set; }
        public bool ZUGA_L_GEPRUEFT { get; set; }
        public bool ZUGA_L_GESPERRT { get; set; }
        public bool ZUGA_L_BETRIEBSBEDARF { get; set; }
        public bool ZUGA_L_FIBU { get; set; }
        public bool ZUGA_L_ERLEDIGT { get; set; }
        public DateTime ZUGA_D_FIBU { get; set; }
        public string? ZUGA_A_NOTIZ { get; set; }
        public int ZUGA_N_BESTELLNR { get; set; }
        public string ZUGA_A_WAEHRUNG { get; set; } = String.Empty;
        public int ZUGA_N_ZABD { get; set; }
        public int ZUGA_N_AB_NR { get; set; }
        public decimal ZUGA_N_RABATT { get; set; }
        public DateTime ZUGA_TIMESTAMP { get; set; }
        public int ZUGA_N_LASTUSER { get; set; }
        public string? ZUGA_A_RE_NR
        {
            get => _zuga_a_re_nr;
            set
            {
                _zuga_a_re_nr = value;

                InputRechnungsnummer = value ?? String.Empty;
            }
        }

        public decimal WK5_ZUGA_N_MWST { get; set; }

        public bool WK5_ZUGA_L_TEILZUGANG { get; set; }
        public bool WK5_ZUGA_L_BEZAHLT { get; set; }
        public decimal WK5_ZUGA_N_NETTO_GESAMTRECHNUNG { get; set; }

        public decimal ZUGA_N_ZOLLKOSTEN { get; set; }

        [CompareField("ZUGA_N_NR_RMA")]
        public int RmaNummerVerknüpfung { get; set; }

        public string InputRechnungsnummer { get => _inputRechnungsnummer; set => _inputRechnungsnummer = value?.Trim() ?? String.Empty; }
        public decimal Brutto
        {
            get
            {
                decimal brutto = ZUGA_N_NETTO + WK5_ZUGA_N_MWST;
                return Math.Round(brutto, 2, MidpointRounding.AwayFromZero);
            }
        }

        public int AnzahlZugängeZurRechnungsnummer { get; internal set; } = 1;

        /// <summary>
        /// Ruft weitere Zugangsnummern ab, die unter der selben Rechnungsnummer geführt werden.
        /// <para>Dieser Wert kann nur dann Zugangsnummern enthalten, wenn der Zugang aus <see cref="LagerService.GetZugängeZuPrüfenAsync(FbController2, System.Threading.CancellationToken)"/> oder <see cref="LagerService.GetZugängeZuZahlenAsync(FbController2, System.Threading.CancellationToken)"/> geladen wurde.</para>
        /// </summary>

        public List<int> WeitereZugangsnummern { get; set; } = new List<int>();
        public string LIEF_A_NAME1 { get => _lief_a_name1; set => _lief_a_name1 = value ?? String.Empty; }

        public string LIEF_A_KUNDENNR { get => _lief_a_kundennr; set => _lief_a_kundennr = value ?? String.Empty; }
        public string LIEF_A_LAND { get => _lief_a_land; set => _lief_a_land = value ?? String.Empty; }
        public string LIEF_A_BIC
        {
            get => _lief_a_bic;
            set
            {
                if (value is null)
                {
                    _lief_a_bic = String.Empty;
                }
                else
                {
                    _lief_a_bic = value.ToUpper().Trim();
                }
            }
        }

        public string LIEF_A_IBAN
        {
            get => _lief_a_iban;
            set
            {
                if (value is null)
                {
                    _lief_a_iban = String.Empty;
                }
                else
                {
                    _lief_a_iban = value.ToUpper().Trim();
                }
            }
        }

        public int WK5_ZUGA_N_ECO_DOCID { get; set; }
        public List<Charge> Positionen { get; } = new List<Charge>();

        /// <summary>
        /// Lädt einen Zugang aus der Datenbank
        /// </summary>
        /// <param name="ZUGA_N_NR">Die ID des Zugangs</param>
        public static async Task<Zugang?> GetZugangAsync(int ZUGA_N_NR)
        {
            using FbController2 fbController = new FbController2();
            fbController.AddParameter("@ZUGA_N_NR", ZUGA_N_NR);
            var row = await fbController.SelectRowAsync("SELECT Z.*, LIEF_A_NAME1, LIEF_A_KUNDENNR, LIEF_A_LIEFLAND, LIEF_A_BIC, LIEF_A_IBAN FROM ZUGAENGE Z LEFT JOIN LIEFERANTEN L ON L.LIEF_N_NR = Z.ZUGA_N_LIEF WHERE ZUGA_N_NR = @ZUGA_N_NR");

            if (row is null)
            {
                return null;
            }

            var zugang = ObjectErweiterung.DataRowZuObjekt(new Zugang(), row);

            fbController.AddParameter("@CHAR_N_STAPELNR", ZUGA_N_NR);
            var data = await fbController.SelectDataAsync(@"SELECT C.*, ARTI_N_ERLOESKONTO, ARTI_A_LAGER, ARTI_A_BEZ1, ARTI_A_BEZ2
FROM CHARGEN C
LEFT JOIN ARTIKEL A ON A.ARTI_A_NR = C.CHAR_A_ARTINR
WHERE CHAR_N_STAPELNR = @CHAR_N_STAPELNR");
            foreach (DataRow posRow in data.Rows)
            {
                zugang.Positionen.Add(ObjectErweiterung.DataRowZuObjekt(new Charge(), posRow));
            }

            return zugang;
        }



        public async Task<RechnungBuchenInput> ToInputAsync()
        {
            var input = new RechnungBuchenInput((ZUGA_L_GEBUCHT && ZUGA_L_GEPRUEFT) || ZUGA_L_GESPERRT)
            {
                LieferscheinDatum = ZUGA_D_LS_DATUM,
                LieferscheinNummer = ZUGA_A_LS_NR ?? String.Empty,
                Rechnungsdatum = ZUGA_D_RE_DATUM,
                Rechnungsnummer = ZUGA_A_RE_NR ?? String.Empty,
                Zusatzkosten = ZUGA_N_TRANSPORT,
                Zugangsnummer = ZUGA_N_NR,
                GesamtbetragNetto = ZUGA_N_NETTO,
                NettoGesamtRechnung = WK5_ZUGA_N_NETTO_GESAMTRECHNUNG,
                TeilRechnung = WK5_ZUGA_L_TEILZUGANG,
                EcoDmsDocId = WK5_ZUGA_N_ECO_DOCID,
                Zugangsdatum = ZUGA_D_DATUM,
                Personalnummer = ZUGA_N_LASTUSER,
                Notiz = ZUGA_A_NOTIZ ?? string.Empty,
                RmaNummerVerknüpfung = RmaNummerVerknüpfung,
                MwstBeiBearbeitung = ZUGA_L_MWST,
                Zollkosten = ZUGA_N_ZOLLKOSTEN
            };

            using FbController2 fbController = new FbController2();
            // Wenn wir Bearbeiten, dann wurden schon alle Buchungen vorgenommen. Wir wollen also die Rechnung prüfen.
            // Dazu brauchen wir nur die Preise, Seriennummern sind nicht mehr relevant an dieser Stelle.
            await foreach (var item in Charge.GetChargenAsync(ZUGA_N_NR, fbController))
            {
                var position = new PositionBuchenInput(false, 0)
                {
                    Artikelnummer = item.CHAR_A_ARTINR,
                    ChargenNotiz = item.CHAR_B_NOTIZEN ?? String.Empty,
                    Menge = item.CHAR_N_MENGE,
                    Preis = item.CHAR_N_EKPREIS_ORG,
                    Chargennummer = item.CHAR_N_NR,
                    MwstSatz = item.CHAR_N_STEUERSATZ,
                    Bestellnummer = item.CHAR_N_BESTNR,
                    Auftragsnummer = item.CHAR_N_AB_NR,
                    Gebrauchtware = item.CHAR_L_GEBRAUCHT
                };

                input.Positionen.Add(position);
            }



            return input;
        }
    }
}
