using System;
using System.Threading.Tasks;
using WK5.Core.Basis.Filter;
using WK5.Core.Drucken;
using WK5.Core.Drucken.Angebote;
using WK5.Core.Drucken.Aufträge;
using WK5.Core.Drucken.Briefe;
using WK5.Core.Drucken.Gutschriften;
using WK5.Core.Drucken.Lieferscheine;
using WK5.Core.Drucken.Rechnungen;
using WK5.Core.Models;
using WK5.Core.Models.Starmoney;

namespace WK5.Core
{
    public static class EnumHelper
    {
        /// <summary>
        /// Wandelt einen Belegtyp in das Equivalent der URL um
        /// </summary>
        /// <param name="belegTyp"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static string GetBelegTypUrl(BelegTyp belegTyp) => belegTyp switch
        {
            BelegTyp.Rechnung => "/Rechnungen",
            BelegTyp.Auftrag => "/Auftraege",
            BelegTyp.Lieferschein => "/Lieferscheine",
            BelegTyp.Gutschrift => "/Gutschriften",
            BelegTyp.Angebot => "/Angebote",
            _ => throw new ArgumentOutOfRangeException(nameof(belegTyp)),
        };
        /// <summary>
        /// Wandelt einen Belegtyp mit einer Belegnummer in das Equivalent der URL um
        /// </summary>
        /// <param name="belegTyp"></param>
        /// <param name="belegnummer"></param>
        /// <returns></returns>
        public static string GetBelegUrl(string belegTyp, int belegnummer) => GetBelegUrl(EnumHelper.GetBelegTyp(belegTyp), belegnummer);
        /// <summary>
        /// Wandelt einen Belegtyp mit einer Belegnummer in das Equivalent der URL um
        /// </summary>
        /// <param name="belegTyp"></param>
        /// <param name="belegnummer"></param>
        /// <returns></returns>
        public static string GetBelegUrl(BelegTyp belegTyp, int belegnummer) => belegTyp switch
        {
            BelegTyp.Rechnung => $"/Rechnungen/{belegnummer}",
            BelegTyp.Auftrag => $"/Auftraege/{belegnummer}",
            BelegTyp.Lieferschein => $"/Lieferscheine/{belegnummer}",
            BelegTyp.Gutschrift => $"/Gutschriften/{belegnummer}",
            BelegTyp.Angebot => $"/Angebote/{belegnummer}",
            _ => throw new ArgumentOutOfRangeException(nameof(belegTyp)),
        };
        /// <summary>
        /// Wandelt einen String in einen <see cref="BelegTyp"/> um.
        /// </summary>
        /// <param name="BELE_A_TYP"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static BelegTyp GetBelegTyp(string BELE_A_TYP) => BELE_A_TYP.ToUpper() switch
        {
            "RE" => BelegTyp.Rechnung,
            "AU" => BelegTyp.Auftrag,
            "AN" => BelegTyp.Angebot,
            "GU" => BelegTyp.Gutschrift,
            "LS" => BelegTyp.Lieferschein,
            _ => throw new ArgumentOutOfRangeException(nameof(BELE_A_TYP)),
        };
        /// <summary>
        /// Wandelt einen <see cref="BelegTyp"/> in einen string um.
        /// </summary>
        /// <param name="belegTyp"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static string GetBelegTypString(BelegTyp belegTyp) => belegTyp switch
        {
            BelegTyp.Rechnung => "RE",
            BelegTyp.Auftrag => "AU",
            BelegTyp.Lieferschein => "LS",
            BelegTyp.Gutschrift => "GU",
            BelegTyp.Angebot => "AN",
            _ => throw new ArgumentOutOfRangeException(nameof(belegTyp)),
        };
        /// <summary>
        /// Wandelt einen string in einen <see cref="PaketTyp"/> um
        /// </summary>
        /// <param name="PAKE_A_TYP"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static PaketTyp GetPaketTyp(string PAKE_A_TYP) => PAKE_A_TYP switch
        {
            "KU" => PaketTyp.Kunde,
            "LI" => PaketTyp.Lieferant,
            "AN" => PaketTyp.Angebot,
            "AU" => PaketTyp.Auftrag,
            "LS" => PaketTyp.Lieferschein,
            "RE" => PaketTyp.Rechnung,
            "RM" => PaketTyp.RMA,
            _ => throw new ArgumentOutOfRangeException(nameof(PAKE_A_TYP)),
        };
        /// <summary>
        /// Wandelt einen <see cref="PaketTyp"/> in das Equivalent einer URL um
        /// </summary>
        /// <param name="typ"></param>
        /// <param name="nummer"></param>
        /// <returns></returns>
        public static string GetPaketTypUrl(string typ, string nummer) => GetPaketTypUrl(EnumHelper.GetPaketTyp(typ), nummer);
        /// <summary>
        /// Wandelt einen <see cref="PaketTyp"/> in das Equivalent einer URL um
        /// </summary>
        /// <param name="typ"></param>
        /// <param name="nummer"></param>
        /// <returns></returns>
        public static string GetPaketTypUrl(PaketTyp typ, string nummer) => typ switch
        {
            PaketTyp.Kunde => $"/Kunden/{nummer}",
            PaketTyp.Lieferant => $"/Lieferanten/{nummer}",
            PaketTyp.Angebot => $"/Angebote/{nummer}",
            PaketTyp.Auftrag => $"/Auftraege/{nummer}",
            PaketTyp.Lieferschein => $"/Lieferscheine/{nummer}",
            PaketTyp.Rechnung => $"/Rechnungen/{nummer}",
            PaketTyp.RMA => $"RMAS/{nummer}",
            _ => "",
        };

        public static string GetPaketTypString(PaketTyp paketTyp) => paketTyp switch
        {
            PaketTyp.Kunde => "KU",
            PaketTyp.Lieferant => "LI",
            PaketTyp.Angebot => "AN",
            PaketTyp.Auftrag => "AU",
            PaketTyp.Lieferschein => "LS",
            PaketTyp.Rechnung => "RE",
            PaketTyp.RMA => "RM",
            _ => string.Empty,
        };

        public static string GetSepaTurnusString(SepaTurnus turnus) => turnus switch
        {
            SepaTurnus.Einmalig => "e",
            SepaTurnus.JedeWoche => "w",
            SepaTurnus.Alle2Wochen => "2w",
            SepaTurnus.Alle3Wochen => "3w",
            SepaTurnus.JedenMonat => "m",
            SepaTurnus.Alle2Monate => "2m",
            SepaTurnus.Alle3Monate => "3m",
            SepaTurnus.Alle6Monate => "6m",
            SepaTurnus.Alle12Monate => "12m",
            _ => throw new ArgumentOutOfRangeException(nameof(turnus)),
        };

        public static string GetSepaTextschlüsselString(SepaTextschlüssel textschlüssel) => textschlüssel switch
        {
            SepaTextschlüssel.Lastschrift_Abbuchungsauftragsverfahren => "4",
            SepaTextschlüssel.Lastschrift_Einzugsermächtigungsverfahren => "5",
            SepaTextschlüssel.SepaBasisLastschrift => "16",
            SepaTextschlüssel.SepaFirmenLastschrift => "17",
            SepaTextschlüssel.Überweisungsgutschrift => "51",
            SepaTextschlüssel.VW_Leistungen_AM => "54",
            SepaTextschlüssel.VW_Leistungen_VM => "5400",
            SepaTextschlüssel.VW_Leistungen_FM => "5401",
            SepaTextschlüssel.ÜberweisungÖffentlicherKassen => "56",
            SepaTextschlüssel.EU_Überweisung => "63",
            SepaTextschlüssel.SEPA_Überweisung => "66",
            SepaTextschlüssel.BZÜ_Überweisung => "67",
            SepaTextschlüssel.GutschriftEinerSpendenüberweisung => "69",
            _ => throw new ArgumentOutOfRangeException(nameof(textschlüssel)),
        };

        public static string GetSepaMandatsstatusString(SepaMandatsstatus status) => status switch
        {
            SepaMandatsstatus.Einmalig => "ei",
            SepaMandatsstatus.Erste => "st",
            SepaMandatsstatus.Wiederkehrend => "wk",
            SepaMandatsstatus.Letzte => "1z",
            _ => throw new ArgumentOutOfRangeException(nameof(status)),
        };

        public static string GetSepaArtString(SepaArt art) => art switch
        {
            SepaArt.SEPA_Überweisung => "CCS",
            SepaArt.SEPA_Terminüberweisung => "CSE",
            SepaArt.SEPA_BasisLastschrift => "CDS",
            SepaArt.SEPA_FirmenLastschrift => "BDD",
            _ => throw new ArgumentOutOfRangeException(nameof(art)),
        };

        public static string GetZeiterfassungTyp(ZeitenFilterOption option) => option switch
        {
            ZeitenFilterOption.Angebot => "AN",
            ZeitenFilterOption.Auftrag => "AU",
            ZeitenFilterOption.Lieferschein => "LS",
            ZeitenFilterOption.Rechnung => "RE",
            ZeitenFilterOption.Gutschrift => "GU",
            ZeitenFilterOption.RMA => "RM",
            ZeitenFilterOption.Kunde => "KU",
            _ => throw new Exception($"'{option}' wird nicht unterstützt")
        };

        public static async Task<PrintBase?> PrintBeleg(Beleg beleg, FbController2? fbController)
        {

            if (beleg is Angebot or Auftrag or Rechnung or Gutschrift && fbController is null)
            {
                throw new ArgumentNullException("Bei Angeboten, Aufträgen, Rechnungen und Gutschriften muss ein FbController übergeben werden");
            }

            if (beleg is Angebot angebot)
            {
                return await PrintAngebot.CreateAsync(angebot, new PrintAngebotRegelsatz
                {
                    ShowFooter = true,
                    ShowHeader = true
                }, fbController!);
            }
            else if (beleg is Auftrag auftrag)
            {
                return await PrintAuftrag.CreateAsync(auftrag, new PrintAuftragRegelsatz
                {
                    ShowFooter = true,
                    ShowHeader = true
                }, fbController!);
            }
            else if (beleg is Lieferschein lieferschein)
            {
                return await PrintLieferschein.CreateAsync(lieferschein, new PrintLieferscheinRegelsatz
                {
                    ShowFooter = true,
                    ShowHeader = true
                });
            }
            else if (beleg is Rechnung rechnung)
            {
                return await PrintRechnung.CreateAsync(rechnung, new PrintRechnungRegelsatz
                {
                    ShowFooter = true,
                    ShowHeader = true
                }, fbController!);
            }
            else if (beleg is Gutschrift gutschrift)
            {
                return await PrintGutschrift.CreateAsync(gutschrift, new PrintGutschriftRegelsatz
                {
                    ShowFooter = true,
                    ShowHeader = true
                }, fbController!);
            }

            return null;
        }
    }
}
