using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;

namespace WK5.Core.Models.Starmoney
{
    //https://hilfe.starmoney.de/hc/de/articles/360016426753-Import-von-Zahlungsverkehrsauftr%C3%A4gen-in-StarMoney-Business
    /// <summary>
    /// Stellt eine SEPA-Überweisung für StarMoney dar.
    /// </summary>
    public class SepaÜberweisung
    {
        /// <summary>
        /// Ruft die Anzahl der möglichen Verwendungszwecke ab.
        /// <para>
        /// 14 ist der Max wert.
        /// </para>
        /// </summary>
        public const int ANZAHL_VERWENDUNGSZWECKE = 14;
        public bool OfflineVerwalten { get; set; }
        public bool Adressbuchübernahme { get; set; }
        public bool Eilauftrag { get; set; }
        public DateTime Datum { get; set; }
        [MaxLength(35)]
        public string Begünstiger { get; set; } = String.Empty;
        [MaxLength(35)]
        public string BegünstigerZeile2 { get; set; } = String.Empty;
        [MaxLength(35)]
        public string BegünstigerZeile3 { get; set; } = String.Empty;
        [MaxLength(35)]
        public string BegünstigerZeile4 { get; set; } = String.Empty;
        [MaxLength(10)]
        public string KontoDesBegünstigten { get; set; } = String.Empty;
        [MaxLength(8)]
        public string BlzDesBegünstigten { get; set; } = String.Empty;

        [MaxLength(34)]
        public string IbanDesBegünstigten { get; set; } = String.Empty;
        [MaxLength(11)]
        public string BicDesBegünstigten { get; set; } = String.Empty;
        public decimal Rechnungsbetrag { get; set; }
        public decimal Skonto { get; set; }
        [MaxLength(3)]
        public string Währung { get; set; } = String.Empty;
        public decimal Betrag => Math.Round(Rechnungsbetrag * (100 - Skonto) / 100, 2);
        private string[] _verwendungszwecke = new string[ANZAHL_VERWENDUNGSZWECKE];
        [MaxLength(27)]
        public string NameDesSpenders { get; set; } = String.Empty;
        [MaxLength(27)]
        public string PlzUndStraßeDesSpenders { get; set; } = String.Empty;

        [MaxLength(27)]
        public string Kontoinhaber { get; set; } = String.Empty;
        [MaxLength(13)]
        public string Rechnungsnummer { get; set; } = String.Empty;

        public SepaTurnus Turnus { get; set; } = SepaTurnus.Einmalig;
        [MaxLength(8)]
        public string Ausführungstag { get; set; } = String.Empty;
        public DateTime Erstmalig { get; set; }
        public DateTime Letztmalig { get; set; }
        public DateTime AuftragAusführenAm { get; set; }
        public SepaMandatsstatus Mandatsstatus { get; set; } = SepaMandatsstatus.Einmalig;
        [MaxLength(35)]
        public string GläubigerIdentifikation { get; set; } = String.Empty;
        [MaxLength(14)]
        public string Mandatsreferenz { get; set; } = String.Empty;
        public DateTime Ausstellungsdatum { get; set; }
        public bool AutomatischLetzmalig { get; set; }

        public SepaTextschlüssel Textschlüssel { get; set; } = SepaTextschlüssel.SEPA_Überweisung;
        public SepaArt Art { get; set; } = SepaArt.SEPA_Terminüberweisung;

        /// <summary>
        /// Erstellt eine neue SepaÜberweisung mit leeren Verwendungszwecken.
        /// </summary>
        public SepaÜberweisung()
        {
            for (int i = 0; i < ANZAHL_VERWENDUNGSZWECKE; i++)
            {
                _verwendungszwecke[i] = String.Empty;
            }
        }
        /// <summary>
        /// Ruft die einzelnen Verwendungszwecke ab.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<string> GetVerwendungszwecke()
        {
            foreach (string verwendungszweck in _verwendungszwecke)
            {
                yield return verwendungszweck;
            }
        }
        /// <summary>
        /// Setzt alle Vwerendungszwecke für die übergebenen Rechnungsnummern
        /// </summary>
        /// <param name="unsereKundennummerBeimLieferanten"></param>
        /// <param name="rechnungsnummern"></param>
        private void SetVerwendungszwecke(string? unsereKundennummerBeimLieferanten, params string[] rechnungsnummern)
        {
            StringBuilder sb = new StringBuilder();

            if (unsereKundennummerBeimLieferanten is null)
            {
                unsereKundennummerBeimLieferanten = String.Empty;
            }

            if (!unsereKundennummerBeimLieferanten.Equals(String.Empty))
            {
                sb.Append($"Kd: {unsereKundennummerBeimLieferanten}, ");
            }

            foreach (string rechnungsnummer in rechnungsnummern)
            {
                sb.Append($"{rechnungsnummer}, ");
            }

            string tmp = sb.ToString();

            for (int i = 0; i < ANZAHL_VERWENDUNGSZWECKE; i++)
            {
                string inhalt = String.Empty;
                if (tmp.Length > 27)
                {
                    inhalt = tmp.Substring(0, 27).Trim();
                    tmp = tmp.Remove(0, 27);
                }
                else
                {
                    inhalt = tmp;
                    tmp = String.Empty;
                }

                if (inhalt.Equals(String.Empty))
                {
                    break;
                }

                _verwendungszwecke[i] = inhalt;
            }

        }

        public List<string> Rechnungsnummern { get; } = new List<string>();
        public string? UnsereKundennummerBeimLieferanten { get; set; }
        /// <summary>
        /// Generiert eine Überweisungsline in für den CSV-Export.
        /// </summary>
        /// <param name="sb"></param>
        public void WriteLine(ref StringBuilder sb)
        {
            SetVerwendungszwecke(UnsereKundennummerBeimLieferanten, Rechnungsnummern.ToArray());
            sb.Append($"{(OfflineVerwalten ? "1" : "0")};");
            sb.Append($"{(Adressbuchübernahme ? "1" : "0")};");
            sb.Append($"{(Eilauftrag ? "1" : "0")};");
            sb.Append($"{Datum:dd.MM.yyyy};");
            sb.Append($"{Begünstiger};");
            sb.Append($"{BegünstigerZeile2};");
            sb.Append($"{BegünstigerZeile3};");
            sb.Append($"{BegünstigerZeile4};");
            sb.Append($"{KontoDesBegünstigten};");
            sb.Append($"{BlzDesBegünstigten};");
            sb.Append($"{IbanDesBegünstigten};");
            sb.Append($"{BicDesBegünstigten};");
            sb.Append($"{Rechnungsbetrag};");
            sb.Append($"{Skonto};");
            sb.Append($"{Währung};");
            sb.Append($"{Betrag};");
            foreach (string verwendungszweck in GetVerwendungszwecke())
            {
                sb.Append($"{verwendungszweck};");

            }
            sb.Append($"{NameDesSpenders};");
            sb.Append($"{PlzUndStraßeDesSpenders};");
            sb.Append($"{Kontoinhaber};");
            sb.Append($"{Rechnungsnummer};");
            sb.Append($"{EnumHelper.GetSepaTurnusString(Turnus)};");
            sb.Append($"{Ausführungstag};");
            if (Erstmalig == default)
            {
                sb.Append(";");
            }
            else
            {
                sb.Append($"{Erstmalig:dd.MM.yyyy};");
            }

            if (Letztmalig == default)
            {
                sb.Append(";");
            }
            else
            {
                sb.Append($"{Letztmalig:dd.MM.yyyy};");
            }

            sb.Append($"{AuftragAusführenAm:dd.MM.yyyy};");
            sb.Append($"{EnumHelper.GetSepaMandatsstatusString(Mandatsstatus)};");
            sb.Append($"{GläubigerIdentifikation};");
            sb.Append($"{Mandatsreferenz};");
            sb.Append($"{Ausstellungsdatum:dd.MM.yyyy};");
            sb.Append($"{(AutomatischLetzmalig ? "1" : "0")};");
            sb.Append($"{EnumHelper.GetSepaTextschlüsselString(Textschlüssel)};");
            sb.Append($"{EnumHelper.GetSepaArtString(Art)};{Environment.NewLine}");
        }
    }
}
