using KarleyLibrary.Erweiterungen;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Forms;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Toolbelt.Blazor.HotKeys;
using WK5.Core;
using WK5.Core.Basis;
using WK5.Core.Basis.Erweiterungen;
using WK5.Core.Models;
using WK5.Core.Models.VatChecker;
using WK5.Core.PageModels;
using WK5.Core.PageModels.Stammdaten.Lieferanten;
using WK5.Core.Services;
using WK5.Core.Validators.Stammdaten.Lieferanten;
using WK5_Blazor.CoreExtensions;

namespace WK5_Blazor.Pages.Stammdaten.Lieferanten
{
    public partial class LieferantenForm : IEditPage, ITabView<LieferantenTabs>
    {
        [Parameter] public int Lieferantennummer { get; set; }
        public LieferantenTabs ActiveTab { get; set; } = LieferantenTabs.Allgemein;
        public bool showLieferantenBestellungenModal { get; set; } = false;
        public bool showLieferantenArtikelModal { get; set; } = false;
        public bool showLieferantenPaketeModal { get; set; } = false;

        private bool lieferantExists = false;

        public List<LieferantenTabs> EditOnlyTabs { get; set; } = new List<LieferantenTabs>()
        {
            LieferantenTabs.Umsatzdaten,
            LieferantenTabs.Lieferantenkontakte,
            LieferantenTabs.Historie,
            LieferantenTabs.Ansprechpartner
        };
        public List<LieferantenTabs> AdminOnlyTabs { get; set; } = new List<LieferantenTabs>();

        public string _modalTelefonnummer { get; set; } = String.Empty;
        private bool _showTelefonnummerModal;
        private bool _showZugängeModal;


#nullable disable
        [CascadingParameter] public Task<AuthenticationState> AuthStateTask { get; set; }
        [CascadingParameter] public AppMitarbeiter Mitarbeiter { get; set; }

#nullable enable

        private EditForm? _form;
        private List<BelegChangeAnsicht> Historie { get; set; } = new List<BelegChangeAnsicht>();
        public LieferantenInput Input { get; set; } = new LieferantenInput();
        public LieferantenInput StartCopy { get; set; } = new LieferantenInput();

        public LieferantenPartnerInputValidator _liefPartnerValidator { get; set; } = new LieferantenPartnerInputValidator();

        public Dictionary<int, Jahresumsatz> Umsatzdaten { get; set; } = new Dictionary<int, Jahresumsatz>();

        public Pipeline<LieferantenInput> DeletePipeline { get; set; } = new Pipeline<LieferantenInput>();

        private List<LieferantenPartner> _ansprechpartner = new List<LieferantenPartner>();

        public int UmsatzJahre { get; set; } = 4;

        public bool _showLöschenBestellungenModal { get; set; }
        public List<int> _löschenBestellungen { get; set; } = new List<int>();
        public bool _showLöschenZugängeModal { get; set; }
        public bool _showLöschenConfirmation { get; set; }        


        #region Schnittstelle IEditPage
        public EditMode Modus { get; set; } = EditMode.Anlage;
        public string ActivePageName => Modus switch
        {
            EditMode.Anlage => "Lieferantenanlage",
            EditMode.Bearbeiten => $"Lieferant {Lieferantennummer}{(!String.IsNullOrWhiteSpace(Input.Name1) ? $" ({Input.Name1})" : String.Empty)}",
            _ => "Unbekannt"
        };


        public string FinalBreadcrumbItemName => Modus switch
        {
            EditMode.Anlage => "Neu",
            EditMode.Bearbeiten => $"{Lieferantennummer}",
            _ => "Unbekannt"
        };
        
        
        #endregion

        public override void AddHotKeys(HotKeysContext context)
        {
            context
                .Add(ModKeys.Alt, Keys.S, Submit, "Speichert den Lieferanten", Exclude.Default)                
                .Add(ModKeys.Alt, Keys.Insert, HandleCtrlPlus, "Alias für das Plus Symbol", Exclude.Default)
                .Add(ModKeys.Alt, Keys.Right, NextTab, "Wechselt zum nächsten Tab", Exclude.Default)
                .Add(ModKeys.Alt, Keys.Left, PrevTab, "Wechselt zum vorherigen Tab", Exclude.Default)
                .Add(ModKeys.Alt, Keys.B, () => { showLieferantenBestellungenModal = true; StateHasChanged(); }, "Zeigt die Lieferanten Bestellungen an", Exclude.Default)
                .Add(ModKeys.Alt, Keys.P, () => { showLieferantenPaketeModal = true; StateHasChanged(); }, "Zeigt die Pakete an", Exclude.Default)                
            ;
        }

        public async Task PostleitzahlChangedAsync(string postleitzahl)
        {
            Input.Postleitzahl = postleitzahl;
            if (Input.Postleitzahl.Length <= 8 && !Input.Postleitzahl.Equals(String.Empty))
            {
                using FbController2 fbController = new FbController2();
                fbController.AddParameter("@PLZV_A_PLZ", Input.Postleitzahl);
                string? ort = await fbController.FetchObjectAsync("SELECT PLZV_A_ORT as ort FROM PLZ WHERE PLZV_A_PLZ = @PLZV_A_PLZ") as string;
                if (ort is not null)
                {
                    Input.Ort = ort;
                }
            }
        }

        private Task LandChangedAsync(string land)
        {
            Input.Land = land;
            if (land == "DE")
            {
                Input.Umsatzsteuer = true;
                Input.Drittland = false;
                Input.EULieferant = false;
            }
            else if (Program.AppDaten.Länder.Any(x => x.WK5_LAND_L_ISTEULAND && x.LAND_A_ID == land))
            {
                Input.Umsatzsteuer = true;
                Input.EULieferant = true;
                Input.Drittland = false;
            }
            else
            {
                Input.Umsatzsteuer = false;
                Input.Drittland = true;
                Input.EULieferant = false;
            }

            return Task.CompletedTask;
        }

        private Task UstIdChangedAsync(string ustId)
        {
            Input.UstId = ustId;

            if (!String.IsNullOrWhiteSpace(Input.Land))
            {
                if (Input.Land.Equals("DE", StringComparison.OrdinalIgnoreCase))
                {
                    Input.Umsatzsteuer = true;
                    Input.Drittland = false;
                    Input.EULieferant = false;
                }
                else if (!Program.AppDaten.Länder.Any(x => x.WK5_LAND_L_ISTEULAND && x.LAND_A_ID == Input.Land))
                {
                    Input.Drittland = true;
                    Input.Umsatzsteuer = false;
                    Input.EULieferant = false;
                }
            }

            return Task.CompletedTask;
        }
        
        private async Task SetupDeletePipelineAsync()
        {
            await DeletePipeline.HardReset();

            DeletePipeline.Add(async (input) =>
            {
                _löschenBestellungen.Clear();
                using FbController2 fbController = new FbController2();

                string sql = "SELECT BEST_N_NR FROM BESTELLUNGEN WHERE BEST_N_LIEFNR = @LIEFNR";
                fbController.AddParameter("@LIEFNR", input.Lieferantennummer);
                DataTable data = await fbController.SelectDataAsync(sql);

                if (data.Rows.Count > 0)
                {
                    foreach (DataRow row in data.Rows)
                    {
                        _löschenBestellungen.Add(row.Field<int>("BEST_N_NR"));
                    }
                    _showLöschenBestellungenModal = true;
                    return false;
                }
                else
                {
                    return true;
                }
            });

            DeletePipeline.Add(async (input) =>
            {
                using FbController2 fbController = new FbController2();

                string sql = "SELECT COUNT(*) FROM ZUGAENGE WHERE ZUGA_N_LIEF = @LIEFNR";
                fbController.AddParameter("@LIEFNR", input.Lieferantennummer);
                object? countObj = await fbController.FetchObjectAsync(sql);

                if (countObj is not null)
                {
                    int count = Convert.ToInt32(countObj);
                    if (count > 0)
                    {
                        _showLöschenZugängeModal = true;
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    return true;
                }
            });

            DeletePipeline.Add((input) =>
            {
                _showLöschenConfirmation = true;
                return false;
            });

            DeletePipeline.Add(async (input) =>
            {

                List<string> queries = new List<string>()
                {
                    "DELETE FROM LIEFERANTEN WHERE LIEF_N_NR = @LIEFNR",
                    "DELETE FROM BELEG_CHANGE WHERE BCNG_A_BELEGTYP = 'LI' AND BCNG_N_BELEGNR = @LIEFNR",
                    "DELETE FROM WK5_LIEFERANTENKONTAKTE WHERE LFKO_N_LFNR = @LIEFNR",
                    "DELETE FROM LIEF_PARTNER WHERE LIEP_N_LIEFNR = @LIEFNR",
                    "DELETE FROM LIEFERANTENARTIKEL WHERE ARLI_N_LIEFNR = @LIEFNR",
                    "DELETE FROM WK5_WICHTIGKEIT_LIEFERANTEN WHERE WICH_N_LIEFNR = @LIEFNR"
                };

                using FbController2 fbController = new FbController2();

                foreach (string query in queries)
                {
                    fbController.AddParameter("@LIEFNR", input.Lieferantennummer);
                    await fbController.QueryAsync(query);
                }

                navigationManager.NavigateTo("/Lieferanten");

                return true;
            });
        }


        public async Task SubmitForm()
        {
            switch (Modus)
            {
                case EditMode.Anlage:
                    await CreateLieferant();
                    break;
                case EditMode.Bearbeiten:
                    await UpdateLieferant();
                    break;
                default:
                    break;
            }
        }

        private async Task Delete()
        {
            DeletePipeline.Reset();
            await DeletePipeline.RunUntilFailureAsync(Input);
        }

        protected override async Task OnParametersSetAsync()
        {
            if (Lieferantennummer > 0)
            {
                await LadeEditModeAsync();
            }

            if (!_isDisposed)
            {
                await CheckActivePageAsync();
            }

            await SetAlerts();

            StartCopy = Input.DeepCopy();
        }

        #region VatChecker
        private VatCheck? vatResult;
        private bool showVatModal = false;
        private async Task BtnVatCheck_Click()
        {
            try
            {
                var result = await Input.PrüfeUstIdAsync(vatService);
                vatResult = result;
                showVatModal = true;
            }
            catch (WebException ex)
            {
                await jsRuntime.ShowToast(ToastType.error, ex.Message);
            }
        }
        #endregion  
        private async Task CreateLieferant()
        {
            Lieferant? lieferant = null;
            try
            {
                lieferant = await Lieferant.CreateLieferantAsync(Input.ToLieferant(), Mitarbeiter.PersonalNummer);
            }
            catch (IndexOutOfRangeException ex)
            {
                await AddAlertAsync(new AlertBox
                {
                    AlertType = AlertType.Danger,
                    Message = "Es sind keine freien Lieferantennummern mehr verfügbar"
                });
                navigationManager.NavigateTo($"/Lieferanten");
                return;
            }

            foreach (var anschrift in Input.Anschriften)
            {
                anschrift.Lieferantennummer = lieferant.LIEF_N_NR;
                await LieferantenAnschrift.CreateLieferantenAnschriftAsync(anschrift.ToLieferantenRechnungsAnschrift(), Mitarbeiter.PersonalNummer);
            }

            await Lieferant.UpdateParsedTelefonnummern(lieferant.LIEF_N_NR);

            await AddAlertAsync(new AlertBox
            {
                AlertType = AlertType.Success,
                Message = "Der Lieferant wurde erfolgreich angelegt"
            });

            navigationManager.NavigateTo($"/Lieferanten/{lieferant.LIEF_N_NR}");
        }

        private async Task UpdateLieferant()
        {
            if (Input.Lieferantennummer <= 0)
            {
                throw new ArgumentException();
            }

            await Lieferant.UpdateLieferantAsync(Input.ToLieferant(), Mitarbeiter.PersonalNummer);

            var nummernVorhanden = await LieferantenAnschrift.GetAnschriftenAsync(Input.Lieferantennummer).Select(x => x.LIRE_N_NR).ToListAsync();
            if (nummernVorhanden != null)
            {
                var nummernNeu = Input.Anschriften.Where(x => x.Nummer > -1).Select(x => x.Nummer).ToList();
                int maxAnschrift = nummernVorhanden.Any() ? nummernVorhanden.Max() : 0;

                foreach (int nummer in nummernNeu.Any() ? HashSetErweiterung.FindeFehlendeNummern(nummernNeu, maxAnschrift) : nummernVorhanden)
                {
                    await LieferantenAnschrift.DeleteLieferantenAnschriftAsync(Input.Lieferantennummer, nummer, Mitarbeiter.PersonalNummer);
                }

            }

            foreach (LieferantenAnschriftInput anschrift in Input.Anschriften)
            {
                if (anschrift.Nummer == -1)
                {
                    await LieferantenAnschrift.CreateLieferantenAnschriftAsync(anschrift.ToLieferantenRechnungsAnschrift(), Mitarbeiter.PersonalNummer);
                }
                else
                {
                    await LieferantenAnschrift.UpdateLieferantenAnschriftAsync(anschrift.ToLieferantenRechnungsAnschrift(), Mitarbeiter.PersonalNummer);
                }
            }

            await Lieferant.UpdateParsedTelefonnummern(Input.Lieferantennummer);

            await AddAlertAsync(new AlertBox
            {
                AlertType = AlertType.Success,
                Message = "Lieferant wurde erfolgreich gespeichert."
            });

            await OnParametersSetAsync();
        }

        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";
        public string GetSubNavListClass(bool active) => active ? "list-group-item list-group-item-action active" : "list-group-item list-group-item-action";
        
        private async Task Submit()
        {
            if (SperreDurchAnderenUser || !Input.HasBeenModified(StartCopy)) return;

            if (_form is not null && _form.EditContext is not null)
            {

                if (_form.EditContext.Validate())
                {
                    await SubmitForm();
                }
            }


        }
       
        public Task Call(string? number)
        {
            if (number is not null)
            {
                _modalTelefonnummer = number;
                _showTelefonnummerModal = true;
                StateHasChanged();
            }

            return Task.CompletedTask;
        }

        public async Task LadeEditModeAsync()
        {
            Modus = EditMode.Bearbeiten;

            var lieferant = await Lieferant.GetLieferantAsync(Lieferantennummer);
            if (lieferant is not null)
            {
                lieferantExists = true;
                Input = await lieferant.ToInputAsync();
                Historie = await BelegChangeAnsicht.GetHistorieAsync("LI", Lieferantennummer.ToString()).ToListAsync();


                Umsatzdaten = new Dictionary<int, Jahresumsatz>();
                for (int i = 0; i < UmsatzJahre; i++)
                {
                    if (!Umsatzdaten.ContainsKey(i))
                    {
                        Umsatzdaten.Add(i, await lieferantenService.GetJahresUmsatzAsync(Lieferantennummer, DateTime.Now.Year - i));
                    }
                }
                _ansprechpartner = await LieferantenPartner.GetLieferantenPartnerAsync(Lieferantennummer).ToListAsync();
                await SetupDeletePipelineAsync();

            }
            else
            {
                await AddAlertAsync(new AlertBox { AlertType = AlertType.Danger, Message = $"Lieferant {Lieferantennummer} konnte nicht gefunden werden" });


                navigationManager.NavigateTo("/Lieferanten");
            }
        }

        public override async Task CheckActivePageAsync()
        {
            if(Lieferantennummer <= 0)
            {
                Page = null;
                return;
            }

            var (success, page) = ActivePages.AddActivePage(new ActivePage(PageType.Lieferant, Lieferantennummer.ToString(), Mitarbeiter.PersonalNummer));

            if (success)
            {
                Page = page;
            }
            else
            {
                await AddAlertAsync(new AlertBox
                {
                    AlertType = AlertType.Danger,
                    Message = $"Der Lieferant wird zurzeit durch {Program.AppDaten.GetMitarbeiterName(page.UserId)} bearbeitet."
                });

                SperreDurchAnderenUser = true;
            }
        }

        public Task NextTab()
        {
            bool found = false;
            int tabIndex = ((int)ActiveTab + 1) % Enum.GetValues(typeof(LieferantenTabs)).Length;
            while (!found)
            {
                LieferantenTabs tab = (LieferantenTabs)tabIndex;
                if (EditOnlyTabs.Contains(tab) && Modus != EditMode.Bearbeiten)
                {
                    tabIndex = (tabIndex + 1) % Enum.GetValues(typeof(LieferantenTabs)).Length;
                    continue;
                }

                if (AdminOnlyTabs.Contains(tab) && !Mitarbeiter.IsAdmin)
                {
                    tabIndex = (tabIndex + 1) % Enum.GetValues(typeof(LieferantenTabs)).Length;
                    continue;
                }

                found = true;
            }

            ActiveTab = (LieferantenTabs)tabIndex;
            StateHasChanged();
            return Task.CompletedTask;
        }

        public Task PrevTab()
        {
            bool found = false;
            int tabIndex = (int)ActiveTab - 1 < 0 ? Enum.GetValues(typeof(LieferantenTabs)).Length - 1 : (int)ActiveTab - 1;
            while (!found)
            {
                LieferantenTabs tab = (LieferantenTabs)tabIndex;
                if (EditOnlyTabs.Contains(tab) && Modus != EditMode.Bearbeiten)
                {
                    tabIndex = tabIndex - 1 < 0 ? Enum.GetValues(typeof(LieferantenTabs)).Length - 1 : tabIndex - 1;
                    continue;
                }

                if (AdminOnlyTabs.Contains(tab) && !Mitarbeiter.IsAdmin)
                {
                    tabIndex = tabIndex - 1 < 0 ? Enum.GetValues(typeof(LieferantenTabs)).Length - 1 : tabIndex - 1;
                    continue;
                }

                found = true;
            }

            ActiveTab = (LieferantenTabs)tabIndex;
            StateHasChanged();
            return Task.CompletedTask;
        }

        private Components.LieferantenPartnerComponent? _lieferantenPartnerComponent;
        private Components.LieferantenKontakte? _lieferantenKontakteComponent;

        public async Task HandleCtrlPlus()
        {
            switch (ActiveTab)
            {
                case LieferantenTabs.Ansprechpartner:
                    if (_lieferantenPartnerComponent is not null)
                    {
                        await _lieferantenPartnerComponent.AddPartnerAsync();
                    }
                    break;
                case LieferantenTabs.Anschriften:
                    Input.AddAnschrift();
                    StateHasChanged();
                    break;
                case LieferantenTabs.Lieferantenkontakte:
                    if (_lieferantenKontakteComponent is not null)
                    {
                        await _lieferantenKontakteComponent.AddAsync();
                    }
                    break;                
                default:
                    break;
            }
        }
    }
}
