using System;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using WK5.Core.Basis.Filter;

namespace WK5.Core.Models
{
    public class WiederkehrendeRechnung : ICloneable
    {
        #region Datenbankfelder
        public int WIED_N_ID { get; set; }
        [Required]
        [Range(30000, 90000)]
        public int WIED_N_NR { get; set; }
        [Required]
        [Range(1, 12)]
        public int WIED_N_INTERVALL { get; set; } = 1;
        public DateTime WIED_D_LASTACTION { get; set; }
        public bool WIED_L_STATUS { get; set; }
        [Required]
        public DateTime WIED_D_START { get; set; }
        [Required]
        [Range(1, 24)]
        public int WIED_N_MINDESTLAUFZEIT { get; set; } = 12;
        public DateTime WIED_D_KUENDIGUNGSDATUM { get; set; }
        public int WIED_N_LASTUSER { get; set; }
        public DateTime WIED_D_PREISAENDERUNG_ZUM { get; set; }
        public DateTime WIED_D_FINALERECHNUNG { get; set; }
        public string KUND_A_NAME1 { get; set; } = String.Empty;
        public string KUND_A_NAME2 { get; set; } = String.Empty;
        public string KUND_A_LAND { get; set; } = String.Empty;
        public string KUND_A_STRASSE { get; set; } = String.Empty;
        public string KUND_A_PLZ { get; set; } = String.Empty;
        public string KUND_A_ORT { get; set; } = String.Empty;
        public int BELE_N_NR_AU { get; set; }
        public int BELE_N_RECHADRESSE { get; set; }
        #endregion
        #region Eigenschaften
        public bool IstGekündigt => WIED_D_KUENDIGUNGSDATUM != default;
        [Required]
        [Range(typeof(bool), "true", "true", ErrorMessage = "Bitte geben Sie eine gültige Rechnungsnummer ein")]
        public bool CustomerExists => KUND_A_NAME1 != String.Empty;
        [Required]
        [Range(typeof(bool), "true", "true", ErrorMessage = "Die angebene Rechnung verfügt über keine Auftragsnummer")]
        public bool AuftragForRechnungExists => BELE_N_NR_AU > 0;
        /// <summary>
        /// Gibt an, wie viele Rechnungen innerhalb der Mindestlaufzeit pro Intervall gestellt werden müssen.
        /// </summary>
        public int RechnungenProLaufzeit => WIED_N_MINDESTLAUFZEIT / WIED_N_INTERVALL;
        /// <summary>
        /// Ruft einen Wert ab, der angibt, in welcher Laufzeit sich eine Wiederkehrende Rechnung befindet.
        /// <para>Beispiel:</para>
        /// <para>Start: 01.01.2017</para>
        /// <para>Aktuelles Datum: 02.01.2020</para>
        /// <para>Laufzeit: 12 Monate</para>
        /// <para>Ergebnis: 4</para>
        /// </summary>
        public int LaufzeitMenge
        {
            get
            {
                int yM = (DateTime.Now.Year - WIED_D_START.Year) * 12;
                yM += DateTime.Now.Month - WIED_D_START.Month;

                if (DateTime.Now.Day < WIED_D_START.Day)
                {
                    yM--;
                }

                return (int)Math.Ceiling((decimal)yM / WIED_N_MINDESTLAUFZEIT);
            }

        }
        /// <summary>
        /// Ruft einen Wert ab, der angibt, wie viele Rechnungen bis heute hätten ertsellt werden müssen.
        /// </summary>
        public int AnzahlRechnungenShouldExists
        {
            get
            {
                int yM = (DateTime.Now.Year - WIED_D_START.Year) * 12;
                yM += DateTime.Now.Month - WIED_D_START.Month;

                if (DateTime.Now.Day < WIED_D_START.Day)
                {
                    yM--;
                }

                return yM / WIED_N_INTERVALL + 1;
            }
        }
        /// <summary>
        /// Ruft die derzeitige Vertragslaufzeit ab.
        /// </summary>
        public Zeitraum AktuelleLaufzeit
        {
            get
            {
                // Wir rechnen hier -1, da die derzeite Laufzeit bereits inbegriffen ist<
                return new Zeitraum(
                    von: WIED_D_START.AddMonths((LaufzeitMenge - 1) * WIED_N_MINDESTLAUFZEIT),
                    bis: WIED_D_START.AddMonths(LaufzeitMenge * WIED_N_MINDESTLAUFZEIT)
                );
            }
        }
        /// <summary>
        /// Ruft den Zeitraum des aktuellen Intervalls ab.
        /// <para>Dieser Zeitraum gibt an, von wann bis wann eine Leistung berechnet wird.</para>
        /// </summary>
        public Zeitraum AktuellesIntervall
        {
            get
            {
                // Wir rechen hier -1, da AnzahlRechnungShouldExists uns immer die Anzahl inkl. der zustellenden Rechnung zurückgibt.
                return new Zeitraum(
                    von: WIED_D_START.AddMonths((AnzahlRechnungenShouldExists - 1) * WIED_N_INTERVALL),
                    bis: WIED_D_START.AddMonths(((AnzahlRechnungenShouldExists - 1) * WIED_N_INTERVALL) + WIED_N_INTERVALL)
                );

            }
        }
        #endregion
        public async Task<int> GetWiederkehrendeRechnungenAnzahlAsync(FbController2 fbController)
        {
            fbController.AddParameter("@BELE_N_NR_AU", BELE_N_NR_AU);
            var anzahlObj = await fbController.FetchObjectAsync(@"SELECT COUNT(*) FROM BELEGE WHERE 
BELE_A_TYP = 'RE' AND BELE_N_NR_AU = @BELE_N_NR_AU AND WK5_BELE_L_WDH_RE = 'Y'");

            if (anzahlObj is null)
            {
                return 0;
            }

            int.TryParse(anzahlObj.ToString(), out int anzahl);

            return anzahl;
        }

        public Task UpdateLastActionAsync(FbController2 fbController)
        {
            fbController.AddParameter("@WIED_N_NR", WIED_N_NR);
            return fbController.QueryAsync("UPDATE WK5_WDH_RECHNUNGEN SET WIED_D_LASTACTION = CURRENT_TIMESTAMP WHERE WIED_N_NR = @WIED_N_NR");
        }


        public Task AufInaktivAsync(FbController2 fbController)
        {
            fbController.AddParameter("@WIED_N_NR", WIED_N_NR);
            return fbController.QueryAsync("UPDATE WK5_WDH_RECHNUNGEN SET WIED_L_STATUS = 'N' WHERE WIED_N_NR = @WIED_N_NR");
        }



        public object Clone() => MemberwiseClone();

    }
}
