using Serilog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WK5.Core;
using WK5.Core.Basis.Filter;
using WK5.Core.Models;
using WK5.Core.Models.Lager;
using WK5.Core.Services;

namespace CoreTester
{
    public class IdeaExport
    {
        private readonly DateTime _from;
        private readonly DateTime _to;
        private readonly string _save_Directory;
        private readonly List<string> _kundennummern = new();
        private readonly List<int> _lieferantennummern = new();

        public IdeaExport(DateTime from, DateTime to, string save_directory)
        {
            _from = from;
            _to = to;
            _save_Directory = save_directory;
        }

        public async Task ExportAsync(FbController2 fbController)
        {
            await ExportBelegeAsync(fbController);
            await ExportKundenAsync(fbController);
            await ExportBestellungenAsync(fbController);
            await ExportLieferantenAsync(fbController);
            await ExportZugängeAsync(fbController);
            await ExportAbgängeAsync(fbController);
        }

        public async Task ExportBelegeAsync(FbController2 fbController)
        {
            Log.Logger.Information("[IdeaExport] Belege exportieren...");
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("Belegnummer;Belegtyp;Belegdatum;Kundennummer;GutschriftNummer;Netto;Brutto;MwstSatz");

            BelegFilter filter = new BelegFilter();
            filter.ZeitraumEingrenzen = true;
            filter.Zeitraum.Von = _from;
            filter.Zeitraum.Bis = _to;
            filter.IdeaExportSuche = true;

            BelegService belegService = new BelegService();
            int total = await belegService.GetSuchBelegAmountAsync(filter, default);
            int abgearbeitet = 0;
            List<Beleg> belege = new List<Beleg>();
            while (total - abgearbeitet > 0)
            {
                await foreach (var beleg in belegService.SucheBelegeAsync(filter, fbController, default))
                {
                    belege.Add(beleg);
                    if (!_kundennummern.Contains(beleg.Kundennummer))
                    {
                        _kundennummern.Add(beleg.Kundennummer);
                    }
                    abgearbeitet++;
                }

                if (abgearbeitet != total)
                {
                    filter.Seite++;
                }
            }

            Mehrwertsteuer? mehrwertsteuer = await Mehrwertsteuer.GetVersandMehrwertsteuerAsync(fbController);
            var optionen = await Option.GetOptionenAsync(fbController);

            foreach (var beleg in belege)
            {
                sb.AppendLine($"{beleg.Belegnummer};{beleg.Belegtyp};{beleg.BELE_D_DATE.ToShortDateString()};{beleg.Kundennummer};{(beleg.Belegtyp is "RE" ? beleg.GutschriftnummerVerknüpfung : 0)};{beleg.GetNettoBetrag(optionen)};{beleg.GetBruttoBetrag(optionen, mehrwertsteuer)};{(beleg.MwstBerechnen ? beleg.BELE_N_MWST_SATZ1 : 0)}");
            }

            await File.WriteAllTextAsync(Path.Combine(_save_Directory, "belege.csv"), sb.ToString());
            Log.Logger.Information("[IdeaExport] Belege erfolgreich exportiert!");
        }
        public async Task ExportKundenAsync(FbController2 fbController)
        {
            Log.Logger.Information("[IdeaExport] Kunden exportieren...");
            KundenService kundenService = new KundenService();

            KundenFilter filter = new KundenFilter();

            int total = await kundenService.GetAnzahlKundenAsync(filter, default);
            int abgearbeitet = 0;
            List<Kunde> kunden = new List<Kunde>();
            while (total - abgearbeitet > 0)
            {
                await foreach (var kunde in kundenService.GetKundenAsync(filter, default))
                {
                    abgearbeitet++;
                    if (_kundennummern.Contains(kunde.KUND_A_NR))
                    {
                        kunden.Add(kunde);
                    }
                }

                if (abgearbeitet != total)
                {
                    filter.Seite++;
                }
            }

            StringBuilder sb = new StringBuilder();
            sb.AppendLine("Kundennummer;Kundenname;UstId;Strasse;Ort;Postleitzahl;Land;IBAN;BIC;Steuernummer");

            foreach (var kunde in kunden)
            {
                sb.AppendLine($"{kunde.KUND_A_NR};{kunde.KUND_A_NAME1};{kunde.KUND_A_USTIDNR};{kunde.KUND_A_STRASSE};{kunde.KUND_A_ORT};{kunde.KUND_A_PLZ};{kunde.KUND_A_LAND};{kunde.KUND_A_IBAN};{kunde.KUND_A_BIC};{kunde.KUND_A_STEUERNR}");
            }


            await File.WriteAllTextAsync(Path.Combine(_save_Directory, "kunden.csv"), sb.ToString());

            Log.Logger.Information("[IdeaExport] Kunden erfolgreich exportiert!");
        }
        public async Task ExportLieferantenAsync(FbController2 fbController)
        {
            Log.Logger.Information("[IdeaExport] Lieferanten exportieren...");
            LieferantenService lieferantenService = new LieferantenService();

            LieferantenFilter filter = new LieferantenFilter();

            int total = await lieferantenService.GetAnzahlLieferantenAsync(filter, default);
            int abgearbeitet = 0;
            List<Lieferant> lieferanten = new();
            while (total - abgearbeitet > 0)
            {
                await foreach (var lieferant in lieferantenService.GetLieferantenAsync(filter, default))
                {

                    abgearbeitet++;
                    if (_lieferantennummern.Contains(lieferant.LIEF_N_NR))
                    {
                        lieferanten.Add(lieferant);
                    }
                }

                if (abgearbeitet != total)
                {
                    filter.Seite++;
                }
            }

            StringBuilder sb = new StringBuilder();
            sb.AppendLine("Lieferantennummer;Lieferantenname;UstId;Strasse;Ort;Postleitzahl;Land;IBAN;BIC");

            foreach (var lieferant in lieferanten)
            {
                sb.AppendLine($"{lieferant.LIEF_N_NR};{lieferant.LIEF_A_NAME1};{lieferant.LIEF_A_USTIDNR};{lieferant.LIEF_A_STR};{lieferant.LIEF_A_ORT};{lieferant.LIEF_A_PLZ};{lieferant.LIEF_A_LAND};{lieferant.LIEF_A_IBAN};{lieferant.LIEF_A_BIC}");
            }


            await File.WriteAllTextAsync(Path.Combine(_save_Directory, "lieferanten.csv"), sb.ToString());
            Log.Logger.Information("[IdeaExport] Lieferanten erfolgreich exportiert!");
        }

        public async Task ExportBestellungenAsync(FbController2 fbController)
        {
            Log.Logger.Information("[IdeaExport] Bestellungen exportieren...");
            BestellService bestellService = new BestellService();

            BestellungFilter filter = new BestellungFilter();
            filter.Option = BestellungFilterOption.AlleBestellungen;
            filter.ZeitraumEingrenzen = true;
            filter.Von = _from;
            filter.Bis = _to;
            int total = await bestellService.GetAnzahlBestellungenAsync(filter, fbController, default);
            int abgearbeitet = 0;
            List<Bestellung> bestellungen = new();
            while (total - abgearbeitet > 0)
            {
                await foreach (var bestellung in bestellService.GetBestellungenAsync(filter, fbController, default))
                {
                    if (!_lieferantennummern.Contains(bestellung.LieferantenId))
                    {
                        _lieferantennummern.Add(bestellung.LieferantenId);
                    }
                    bestellungen.Add(bestellung);
                    abgearbeitet++;
                }

                if (abgearbeitet != total)
                {
                    filter.Seite++;
                }
            }

            StringBuilder sb = new StringBuilder();
            sb.AppendLine("Bestellnummer;Lieferantennummer;Bestelldatum;Netto;Waehrung");

            foreach (var bestellung in bestellungen)
            {
                sb.AppendLine($"{bestellung.Bestellnummer};{bestellung.LieferantenId};{bestellung.Belegdatum.ToShortDateString()};{bestellung.GetNettoBetrag()};{bestellung.Währung}");
            }


            await File.WriteAllTextAsync(Path.Combine(_save_Directory, "bestellungen.csv"), sb.ToString());
            Log.Logger.Information("[IdeaExport] Bestellungen erfolgreich exportiert!");
        }

        public async Task ExportZugängeAsync(FbController2 fbController)
        {
            Log.Logger.Information("[IdeaExport] Zugänge exportieren...");
            LagerService lagerService = new LagerService();

            ZugangFilter filter = new ZugangFilter();
            filter.Option = ZugangFilterOption.Alle;
            filter.ZeitraumFiltern = true;
            filter.Von = _from;
            filter.Bis = _to;

            int total = await lagerService.GetAnzahlZugängeAsnyc(filter, default);
            int abgearbeitet = 0;
            List<Zugang> zugänge = new();
            while (total - abgearbeitet > 0)
            {
                await foreach (var zugang in lagerService.GetZugängeAsync(filter, default))
                {
                    zugänge.Add(zugang);
                    abgearbeitet++;
                }

                if (abgearbeitet != total)
                {
                    filter.Seite++;
                }
            }

            StringBuilder sb = new StringBuilder();
            sb.AppendLine("Zugangsnummer;Zugangsdatum;Lieferanten-Lieferscheinnummer;LieferscheinDatum;Lieferanten-Rechnungsnummer;Rechnungsdatum;Nettobetrag;Waehrung;Bemerkung");

            foreach (var zugang in zugänge)
            {
                sb.AppendLine($"{zugang.ZUGA_N_NR};{zugang.ZUGA_D_DATUM.ToShortDateString()};{zugang.ZUGA_A_LS_NR};{zugang.ZUGA_D_LS_DATUM.ToShortDateString()};{zugang.ZUGA_A_RE_NR};{zugang.ZUGA_D_RE_DATUM.ToShortDateString()};{zugang.ZUGA_N_NETTO};{zugang.ZUGA_A_WAEHRUNG};{zugang.ZUGA_A_NOTIZ}");
            }


            await File.WriteAllTextAsync(Path.Combine(_save_Directory, "zugaenge.csv"), sb.ToString());
            Log.Logger.Information("[IdeaExport] Zugänge erfolgreich exportiert!");
        }

        public async Task ExportAbgängeAsync(FbController2 fbController)
        {
            Log.Logger.Information("[IdeaExport] Abgänge exportieren...");
            LagerService lagerService = new LagerService();

            AbgangFilter filter = new AbgangFilter();


            int total = await lagerService.GetAnzahlAbgängeAsync(filter, default);
            int abgearbeitet = 0;
            List<Abgang> abgänge = new();
            while (total - abgearbeitet > 0)
            {
                await foreach (var abgang in lagerService.GetAbgängeAsync(filter, default))
                {
                    abgänge.Add(abgang);
                    abgearbeitet++;
                }

                if (abgearbeitet != total)
                {
                    filter.Seite++;
                }
            }

            StringBuilder sb = new StringBuilder();
            sb.AppendLine("Abgangsnummer;Abgangsdatum;Artikelnummer;Menge;Kostenstelle;Bemerkung");

            foreach (var abgang in abgänge)
            {
                sb.AppendLine($"{abgang.ARAB_N_NR};{abgang.ARAB_D_DATUM.ToShortDateString()};{abgang.ARAB_A_ARTIKEL};{abgang.ARAB_N_MENGE};{abgang.ARAB_N_KOSTENSTELL};{abgang.ARAB_A_NOTIZ}");
            }


            await File.WriteAllTextAsync(Path.Combine(_save_Directory, "abgaenge.csv"), sb.ToString());
            Log.Logger.Information("[IdeaExport] Abgänge erfolgreich exportiert!");
        }
    }
}
