using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using WK5.Core;
using WK5.Core.Models;
using WK5.Core.PageModels;
using WK5.Core.PageModels.Lagerregal;
using WK5.Core.Basis.Erweiterungen;
using WK5.Core.Email;
using WK5.Core.PageModels.Verkauf.Aufträge;
using WK5.Core.Basis.Filter;
using System.Threading;
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;

namespace WK5_Blazor.Pages.Verkauf.Aufträge
{
    public partial class Auftragsfreigabe : IHilfeModal, IAsyncDisposable
    {
        public const string LocalStorageFilterKey = "AuftragsFreigabe.OffeneAufträgeFilter";

#nullable disable
        [CascadingParameter] public AppMitarbeiter Mitarbeiter { get; set; }
#nullable enable
        public AuftragsfreigabeTabs ActiveTab { get; set; } = AuftragsfreigabeTabs.OffeneAufträge;
        public AuftragsFreigabeFilter OffeneAufträgeFilter { get; set; } = new AuftragsFreigabeFilter();
        public bool ShowHilfeModal { get; set; }

        private readonly List<AuftragFreigegeben> _offeneAufträge = new List<AuftragFreigegeben>();
        private readonly List<AuftragFreigegeben> _freigegebeneAufträge = new List<AuftragFreigegeben>();
        private readonly List<Auftrag> _zuPrüfendeAufträge = new List<Auftrag>();
        private AuftragFreigegeben? _selectedAuftrag = null;
        public CancellationTokenSource _cts = new CancellationTokenSource();
        private AuftragsfreigabeDatumAuswahlInput _datumAuswahlInput = new AuftragsfreigabeDatumAuswahlInput();
        private bool _lädt = false;
        private bool _isDisposed;

        private bool _showDatumAuswahlModal;
        private bool _showFreigabeEntfernenModal;
        private bool _showZahlungNichtErhaltenModal;
        private bool _showLieferdatumNichtErreichtModal;
        private bool _showTeillieferungsFreigabeModal;

        protected override async Task OnInitializedAsync()
        {
            if (!_isDisposed)
            {
                var localStorageResult = await LocalStorage.GetAsync<AuftragsFreigabeFilter>(LocalStorageFilterKey);
                if (localStorageResult.Success)
                {
                    if (localStorageResult.Value is not null)
                    {
                        OffeneAufträgeFilter = localStorageResult.Value;
                    }
                }

                await LadeÜbersicht();

                await foreach (var item in auftragsfreigabeService.GetFreigegebeneAufträgeAsync())
                {
                    _freigegebeneAufträge.Add(item);
                    StateHasChanged();
                }
            }
        }
        private async Task LadeÜbersicht()
        {
            _lädt = true;
            _offeneAufträge.Clear();
            _zuPrüfendeAufträge.Clear();

            _cts.Cancel();
            _cts = new CancellationTokenSource();
            await LocalStorage.SetAsync(LocalStorageFilterKey, OffeneAufträgeFilter);
            var token = _cts.Token;

            using FbController2 fbController = new FbController2();
            try
            {
                await foreach (var übersicht in auftragsfreigabeService.GetOffeneAufträgeAsync(OffeneAufträgeFilter, token))
                {
                    _offeneAufträge.Add(übersicht);
                    StateHasChanged();
                }

                await foreach (var item in auftragsfreigabeService.GetZuPrüfenAsync(fbController, token))
                {
                    _zuPrüfendeAufträge.Add(item);
                    StateHasChanged();
                }

            }
            catch (OperationCanceledException) { }
            catch (Exception)
            {
                OffeneAufträgeFilter = new AuftragsFreigabeFilter();
                await LocalStorage.SetAsync(LocalStorageFilterKey, OffeneAufträgeFilter);
                throw;
            }

            _lädt = false;
        }
        private Task SwitchTabAsync(AuftragsfreigabeTabs tab)
        {
            ActiveTab = tab;
            _selectedAuftrag = null;
            return Task.CompletedTask;
        }
        public string GetNavListClass(bool active) => active ? "nav-link active" : "nav-link";
        public string GetTabClass(bool active) => active ? "tab-pane fade active show" : "tab-pane fade";
        private async Task LieferDatumNichtErreichtModal_Confirmed()
        {
            if (_selectedAuftrag is not null)
            {
                await auftragsfreigabeService.SetLieferterminHeuteAsync(_selectedAuftrag.Belegnummer, Mitarbeiter.PersonalNummer);
                await Auftragfreigeben(DateTime.Now);
            }
            _showLieferdatumNichtErreichtModal = false;
        }
        private async Task AuftragfreigebenMitDatum()
        {
            await Auftragfreigeben(_datumAuswahlInput.PackDatum);
            _showDatumAuswahlModal = false;
            _datumAuswahlInput = new AuftragsfreigabeDatumAuswahlInput();
        }
        private async Task Auftragfreigeben(DateTime date)
        {
            if (_selectedAuftrag is null)
            {
                return;
            }

            using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);

            await auftragsfreigabeService.AuftragFreigebenAysnc(_selectedAuftrag.Belegnummer, date, fbController);

            await jsRuntime.ShowToast(ToastType.success, $"Auftrag wurde erfolgreich für den {date.ToShortDateString()} freigegeben.");
            _selectedAuftrag.FREI_D_PACKENAB = date;
            _offeneAufträge.Remove(_selectedAuftrag);
            // Wenn wir das Datum eines freigegebenen Auftrags verändern, dann ist er bereits in der korrekten Liste
            if (!_freigegebeneAufträge.Contains(_selectedAuftrag))
            {
                _freigegebeneAufträge.Add(_selectedAuftrag);
            }

            _freigegebeneAufträge.Sort((x, y) => y.Belegnummer.CompareTo(x.Belegnummer));
            _offeneAufträge.Sort((x, y) => y.Belegnummer.CompareTo(x.Belegnummer));
        }
        private async Task FreigabeEntfernen()
        {
            if (_selectedAuftrag is null)
            {
                return;
            }

            using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);
            await auftragsfreigabeService.FreigabeEntfernenAsync(_selectedAuftrag.Belegnummer, fbController);
            _selectedAuftrag.FREI_D_PACKENAB = default;
            _offeneAufträge.Add(_selectedAuftrag);
            _freigegebeneAufträge.Remove(_selectedAuftrag);
            _freigegebeneAufträge.Sort((x, y) => y.Belegnummer.CompareTo(x.Belegnummer));
            _offeneAufträge.Sort((x, y) => y.Belegnummer.CompareTo(x.Belegnummer));
        }
        private async Task TeillieferungsFreigabe()
        {
            if (_selectedAuftrag is null)
            {
                return;
            }

            using FbController2 fbController = new FbController2(Mitarbeiter.PersonalNummer);

            Belegposition pos = new Belegposition();
            pos.BPOS_N_NR = _selectedAuftrag.Belegnummer;
            pos.BPOS_A_TYP = _selectedAuftrag.Belegtyp;
            pos.Artikelnummer = Belegposition.ARTIKELNR_TEXT;
            pos.Langtext = $"Von {Mitarbeiter.Username} zur Teillieferung freigegeben";
            pos.LangtextDrucken = false;
            pos.PosOhneDruck = true;
            try
            {
                await belegService.CreatePositionAsync(pos, BelegTyp.Auftrag, true, fbController);

                await auftragsfreigabeService.AuftragFreigebenAysnc(_selectedAuftrag.Belegnummer, DateTime.Now, fbController);

                _offeneAufträge.Remove(_selectedAuftrag);
                // Wenn wir das Datum eines freigegebenen Auftrags verändern, dann ist er bereits in der korrekten Liste
                if (!_freigegebeneAufträge.Contains(_selectedAuftrag))
                {
                    _freigegebeneAufträge.Add(_selectedAuftrag);
                }

                _freigegebeneAufträge.Sort((x, y) => y.Belegnummer.CompareTo(x.Belegnummer));
                _offeneAufträge.Sort((x, y) => y.Belegnummer.CompareTo(x.Belegnummer));
            }
            catch (Exception ex)
            {
                await jsRuntime.ShowToast(ToastType.error, "Fehler in der Teillieferungsfreigabe", 0);
            }


        }
        private void SelectAuftrag(AuftragFreigegeben auftrag)
        {
            _selectedAuftrag = auftrag;
        }
        public ValueTask DisposeAsync()
        {
            _cts?.Cancel();
            _cts?.Dispose();
            _isDisposed = true;

            return ValueTask.CompletedTask;
        }

    }
}
