using ecoDMS.Library;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WK5.Core;
using WK5.Core.Basis;
using WK5.Core.Basis.Erweiterungen;
using WK5.Core.Basis.Filter;
using WK5.Core.Models;
using WK5.Core.Models.Lager;
using WK5.Core.PageModels.Tools;
using WK5.Core.Validators.Tools;
using WK5_Blazor.CoreExtensions;

namespace WK5_Blazor.Pages.Bestellungen
{
    public partial class RechnungsPrüfung
    {
        private List<RechnungsPrüfungInput> _zugänge = new List<RechnungsPrüfungInput>();
        private CancellationTokenSource _cts = new CancellationTokenSource();
        
        private bool _showLieferantenKontakteModal;
        private int lieferantenId;
        private LieferantenkontaktFilter _filterLieferantenKontakte = new LieferantenkontaktFilter
        {
            Typ = LieferantenKontaktTyp.Buchhaltung
        };
#nullable disable
        private EditForm _editForm;
        [CascadingParameter] public AppMitarbeiter Mitarbeiter { get; set; }
#nullable enable

        private bool _showHilfeModal;
        private Zugang? _selectedZugang;
        private Zugang? _manuellPrüfenZugang;
        private List<string> _ecoVorschauBilder = new List<string>();

        private ZugangZahlungskonditionenValidator _zahlungskonditionenValidator = new ZugangZahlungskonditionenValidator();

        private bool _loadingEcoDokument;
        protected override async Task OnInitializedAsync()
        {
            _cts.Cancel();
            _cts = new CancellationTokenSource();
            using FbController2 fbController = new FbController2();
            await foreach (var zugang in lagerService.GetZugängeZuPrüfenAsync(fbController, _cts.Token))
            {
                _zugänge.Add(new RechnungsPrüfungInput(zugang));
                StateHasChanged();
            }
        }
        public async Task UpdateZahlungskonditionenAsync(Zugang zugang, bool updateLieferantenZahlungsbedinung)
        {
            using FbController2 fbController = new FbController2();
            await lagerService.UpdateZahlungskonditionenZugangAsync(fbController, zugang);
            await lagerService.UpdateZahlungskonditionenLieferantAsync(fbController, zugang, updateLieferantenZahlungsbedinung);


            foreach (var item in _zugänge.Where(x => x.Zugang.ZUGA_N_LIEF == zugang.ZUGA_N_LIEF).Select(x => x.Zugang))
            {
                item.LIEF_A_BIC = zugang.LIEF_A_BIC;
                item.LIEF_A_IBAN = zugang.LIEF_A_IBAN;
            }

            foreach (var item in _zugänge.Where(x => zugang.WeitereZugangsnummern.Contains(x.Zugang.ZUGA_N_NR)).Select(x => x.Zugang))
            {
                item.ZUGA_A_RE_NR = zugang.InputRechnungsnummer;
            }

            // Korrektur in ecoDMS

            try
            {
#if DEBUG
                EcoDmsController ecoDmsController = await EcoDmsController.CreateAsync(new Uri(GlobalConfig.ECODMS_BASIS_URL), GlobalConfig.ECODMS_DEFAULT_USER, Log.Logger);
#else
                EcoDmsController ecoDmsController = await EcoDmsController.CreateAsync(new Uri(GlobalConfig.ECODMS_BASIS_URL), $"{Mitarbeiter.Username}:{Mitarbeiter.Passwort}", Log.Logger);
#endif

                List<EcoSearchFilter> suchbedingungen = new List<EcoSearchFilter>
                {
                    new EcoSearchFilter
                    {
                        ClassifyAttribut = ecoDmsController.ClassifyAttributes.GetKeyByValue("Belegnummer")!,
                        SearchOperator = SuchOperator.Gleich,
                        SearchValue = zugang.ZUGA_A_RE_NR
                    },
                    new EcoSearchFilter
                    {
                        ClassifyAttribut = "docart",
                        SearchOperator = SuchOperator.Gleich,
                        SearchValue = "15"
                    }
                };

                List<EcoDMSdocInfoCL> result = await ecoDmsController.EcoSucheDoksAsync(suchbedingungen);
                EcoDMSdocInfoCL? ecoDokument = result.FirstOrDefault();
                if (ecoDokument is not null)
                {
                    ecoDokument.ClassifyAttributes["cdate"] = zugang.ZUGA_D_RE_DATUM.ToString("yyyy-MM-dd");
                    ecoDokument.ClassifyAttributes[ecoDmsController.ClassifyAttributes.GetKeyByValue("Belegnummer")!] = zugang.InputRechnungsnummer;
                    await ecoDmsController.ClassifyAsync(ecoDokument);
                }
                else
                {
                    await jsRuntime.ShowToast(ToastType.warning, $"Rechnung {zugang.ZUGA_A_RE_NR} konnte in ecoDMS nicht gefunden werden.");
                }
            }
            catch (Exception ex)
            {
                await jsRuntime.ShowToast(ToastType.warning, $"Klassifizierung in ecoDMS fehlgeschlagen. Bitte manuell in ecoDMS klassifizieren.");
                Log.Logger.Error("Fehler beim Klassifizieren der Rechnung {rechnungsnummer} StackTrace\r\n{StackTrace}", zugang.ZUGA_A_RE_NR, ex.StackTrace);

            }

            // Nachdem korrigiert wurde, kann die Nummer des Zugangs aktualisiert werden
            zugang.ZUGA_A_RE_NR = zugang.InputRechnungsnummer;

            await jsRuntime.ShowToast(ToastType.success, "Zahlungskonditionen wurden erfolgreich aktualisiert.");
        }

        private Task ShowLieferantenKontakte(int LIEF_N_NR)
        {
            lieferantenId = LIEF_N_NR;
            _filterLieferantenKontakte.LieferantenId = LIEF_N_NR;
            _showLieferantenKontakteModal = true;
            return Task.CompletedTask;
        }
        private bool _exportiereDaten = false;
        private async Task ExportierenAsync()
        {
            _exportiereDaten = true;
            await InvokeAsync(StateHasChanged);
            if (_editForm.EditContext is not null && _editForm.EditContext.Validate())
            {

                using FbController2 fbController = new FbController2();
                await fbController.StartTransactionAsync();
                try
                {
                    var exportZugänge = _zugänge.Where(x => x.Exportieren).ToList();

                    foreach (var input in exportZugänge)
                    {
                        // Lieferanten land prüfen

                        Lieferant lieferant = await Lieferant.GetLieferantAsync(input.Zugang.ZUGA_N_LIEF) ?? throw new ArgumentNullException(nameof(lieferant));
                        bool success = false;
                        try
                        {
                            success = await SetEcoZugangStatus(input);
                        }
                        catch (Exception ex)
                        {
                            Log.Logger.Error("[RECHNUNGS-PRÜFUNG] ERROR {error}", ex);
                            await AddAlertAsync(new AlertBox
                            {
                                AlertType = AlertType.Danger,
                                Message = $"Der Status von der Rechnungsnummer {input.Zugang.ZUGA_A_RE_NR} konnte nicht in ecoDMS umgestellt werden. Bitte manuell umstellen.\r\nFehler: {ex.Message}"
                            });
                            success = false;
                        }


                        if (success)
                        {
                            await lagerService.SetGeprueft(fbController, input.Zugang.ZUGA_N_NR);

                            if (input.Zugang.WeitereZugangsnummern.Any())
                            {
                                foreach (int weitereZugangsnummer in input.Zugang.WeitereZugangsnummern)
                                {
                                    await lagerService.SetGeprueft(fbController, weitereZugangsnummer);
                                }
                            }

                            _zugänge.Remove(input);
                        }
                    }
                    await SetAlerts();
                    await fbController.CommitChangesAsync();
                }
                catch (Exception)
                {
                    await fbController.RollbackChangesAsync();
                    throw;

                }

            }

            _exportiereDaten = false;
        }

        private async Task ManuellGeprüftAsync()
        {
            if(_manuellPrüfenZugang is not null)
            {
                using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
                await lagerService.SetGeprueft(fbController, _manuellPrüfenZugang.ZUGA_N_NR);
                await lagerService.SetDatevExportiert(fbController, _manuellPrüfenZugang.ZUGA_N_NR);
                await lagerService.SetBezahltAsync(fbController, _manuellPrüfenZugang.ZUGA_N_NR);
                await jsRuntime.ShowToast(ToastType.success, "Zugang wurde vollständig auf geprüft gesetzt.");
            }
        }
        private async Task<bool> SetEcoZugangStatus(RechnungsPrüfungInput input)
        {
            if (String.IsNullOrWhiteSpace(input.Zugang.ZUGA_A_RE_NR))
            {
                return false;
            }
            EcoDmsController ecoDmsController = await EcoDmsController.CreateAsync(new Uri(GlobalConfig.ECODMS_BASIS_URL), GlobalConfig.ECODMS_DEFAULT_USER, Log.Logger);
            EcoDMSdocInfoCL? sucheDokument = (await ecoDmsController.EcoSucheDoksAsync(new List<EcoSearchFilter>
            {
                new EcoSearchFilter
                {
                    ClassifyAttribut = ecoDmsController.ClassifyAttributes.GetKeyByValue("Belegnummer")!,
                    SearchOperator = SuchOperator.Gleich,
                    SearchValue = input.Zugang.ZUGA_A_RE_NR.Trim()
                },
                new EcoSearchFilter
                {
                    ClassifyAttribut = "docart",
                    SearchOperator = SuchOperator.Gleich,
                    SearchValue = "15"
                }
            })).FirstOrDefault();

            if (sucheDokument is not null)
            {
                string erledigtStatusText = "Erledigt";
                string bearbeitenStatusText = "Zu Bearbeiten";
                EcoDMSStatiCL? erledigtStatus = ecoDmsController.EcoDmsStatusListe?.Where(x => x.Name.Equals(erledigtStatusText, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                EcoDMSStatiCL? bearbeitenStatus = ecoDmsController.EcoDmsStatusListe?.Where(x => x.Name.Equals(bearbeitenStatusText, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                string nichtsToDo = String.Empty;
                string zahlenToDo = "Zu zahlen";
                string datevToDo = "Datev verbuchen";
                string datevZahlenToDo = "Datev & zu zahlen";

                if ((input.Zugang.WK5_ZUGA_L_BEZAHLT || Program.AppDaten.Zahlungsbedingungen.IstLastschrift(input.Zugang.ZUGA_N_ZABD)) && input.Zugang.ZUGA_L_FIBU)
                {
                    sucheDokument.ClassifyAttributes[ecoDmsController.ClassifyAttributes.GetKeyByValue("ToDo")!] = nichtsToDo;
                    if (erledigtStatus is not null)
                    {
                        sucheDokument.ClassifyAttributes[ecoDmsController.ClassifyAttributes.GetKeyByValue("Status")!] = erledigtStatus.Id.ToString();
                    }
                    else
                    {
                        await AddAlertAsync(new AlertBox
                        {
                            AlertType = AlertType.Danger,
                            Message = $@"Der ecoDMS Status konnte für die Rechnung {input.Zugang.ZUGA_A_RE_NR} nicht auf '{erledigtStatusText}' gesetzt werden da der Status nicht gefunden wurde
Die Rechnung wurde bezahlt und in Datev verbucht"
                        });
                        return false;
                    }
                }
                else
                {
                    if ((input.Zugang.WK5_ZUGA_L_BEZAHLT || Program.AppDaten.Zahlungsbedingungen.IstLastschrift(input.Zugang.ZUGA_N_ZABD)) && !input.Zugang.ZUGA_L_FIBU)
                    {
                        sucheDokument.ClassifyAttributes[ecoDmsController.ClassifyAttributes.GetKeyByValue("ToDo")!] = datevToDo;
                        if (bearbeitenStatus is not null)
                        {
                            sucheDokument.ClassifyAttributes[ecoDmsController.ClassifyAttributes.GetKeyByValue("Status")!] = bearbeitenStatus.Id.ToString();
                        }
                        else
                        {
                            await AddAlertAsync(new AlertBox
                            {
                                AlertType = AlertType.Danger,
                                Message = $@"Der ecoDMS Status konnte für die Rechnung {input.Zugang.ZUGA_A_RE_NR} nicht auf '{bearbeitenStatusText}' gesetzt werden da der Status nicht gefunden wurde
Die Rechnung wurde bezahlt aber nicht in Datev verbucht"
                            });
                            return false;
                        }
                    }
                    else if (input.Zugang.ZUGA_L_FIBU && !(input.Zugang.WK5_ZUGA_L_BEZAHLT || Program.AppDaten.Zahlungsbedingungen.IstLastschrift(input.Zugang.ZUGA_N_ZABD)))
                    {
                        sucheDokument.ClassifyAttributes[ecoDmsController.ClassifyAttributes.GetKeyByValue("ToDo")!] = zahlenToDo;
                        if (bearbeitenStatus is not null)
                        {
                            sucheDokument.ClassifyAttributes[ecoDmsController.ClassifyAttributes.GetKeyByValue("Status")!] = bearbeitenStatus.Id.ToString();
                        }
                        else
                        {
                            await AddAlertAsync(new AlertBox
                            {
                                AlertType = AlertType.Danger,
                                Message = $@"Der ecoDMS Status konnte für die Rechnung {input.Zugang.ZUGA_A_RE_NR} nicht auf '{bearbeitenStatusText}' gesetzt werden da der Status nicht gefunden wurde
Die Rechnung wurde in Datev verbucht aber nicht bezahlt"
                            });
                            return false;
                        }
                    }
                    else
                    {
                        sucheDokument.ClassifyAttributes[ecoDmsController.ClassifyAttributes.GetKeyByValue("ToDo")!] = datevZahlenToDo;
                        if (bearbeitenStatus is not null)
                        {
                            sucheDokument.ClassifyAttributes[ecoDmsController.ClassifyAttributes.GetKeyByValue("Status")!] = bearbeitenStatus.Id.ToString();
                        }
                        else
                        {
                            await AddAlertAsync(new AlertBox
                            {
                                AlertType = AlertType.Danger,
                                Message = $@"Der ecoDMS Status konnte für die Rechnung {input.Zugang.ZUGA_A_RE_NR} nicht auf '{bearbeitenStatusText}' gesetzt werden da der Status nicht gefunden wurde
Die Rechnung wurde nicht bezahlt und nicht in Datev archiviert"
                            });
                            return false;
                        }
                    }
                }
                await ecoDmsController.ClassifyAsync(sucheDokument);
                return true;
            }
            else
            {
                await AddAlertAsync(new AlertBox
                {
                    AlertType = AlertType.Danger,
                    Message = $@"Das Dokument zur Rechnung {input.Zugang.ZUGA_A_RE_NR} konnte nicht in ecoDMS gefunden werden"
                });
                return false;
            }
        }

        private async Task GetEcoDokumentAsync(Zugang zugang)
        {
            _loadingEcoDokument = true;
            _ecoVorschauBilder.Clear();
            _selectedZugang = zugang;
            EcoDmsController ecoDmsController = await EcoDmsController.CreateAsync(new Uri(GlobalConfig.ECODMS_BASIS_URL), GlobalConfig.ECODMS_DEFAULT_USER, Log.Logger);

            var sucheDokument = (await ecoDmsController.EcoSucheDoksAsync(new List<EcoSearchFilter>
            {
                new EcoSearchFilter
                {
                    ClassifyAttribut = ecoDmsController.ClassifyAttributes.GetKeyByValue("Belegnummer")!,
                    SearchOperator = SuchOperator.Gleich,
                    SearchValue = zugang.ZUGA_A_RE_NR?.Trim()
                },
                new EcoSearchFilter
                {
                    ClassifyAttribut = "docart",
                    SearchOperator = SuchOperator.Gleich,
                    SearchValue = "15"
                }
            })).FirstOrDefault();


            if (sucheDokument is not null)
            {
                try
                {
                    int zähler = 1;
                    while (true)
                    {
                        var data = await ecoDmsController.GetDokumentenVorschauAsync(sucheDokument.DocId, zähler, 820);
                        string ecoBaseImage = Convert.ToBase64String(data);
                        _ecoVorschauBilder.Add(ecoBaseImage);
                        zähler++;
                    }
                }
                catch (Exception)
                {


                }
            }

            _loadingEcoDokument = false;
        }
    }
}
