using Blazorise;
using FoodsharingSiegen.Contracts.Entity;
using FoodsharingSiegen.Contracts.Enums;
using FoodsharingSiegen.Contracts.Helper;
using FoodsharingSiegen.Server.Data.Service;
using FoodsharingSiegen.Server.Dialogs;
using Microsoft.AspNetCore.Components;

namespace FoodsharingSiegen.Server.Pages
{
    /// <summary>
    ///     The users class (a. beging, 01.04.2022)
    /// </summary>
    public partial class Users
    {
        #region Dependencies

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Gets or sets the user service. </summary>
        /// <value> The user service. </value>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        [Inject]
        public UserService UserService { get; set; } = null!;

        [Inject]
        public new FoodsharingSiegen.Server.Auth.AuthService AuthService { get; set; } = null!;

        [Inject]
        public new NavigationManager NavigationManager { get; set; } = null!;

        #endregion

        #region Private Properties

        /// <summary>
        ///     Gets or sets the value of the password modal (ab)
        /// </summary>
        private SetPasswordModal? PasswordModal { get; set; }

        /// <summary>
        ///     Gets or sets the edit user modal
        /// </summary>
        private Modal? editUserModal { get; set; }

        /// <summary>
        ///     Gets or sets the selected group texts
        /// </summary>
        private List<string> SelectedGroupTexts { get; set; } = new();

        /// <summary>
        ///     Gets or sets the edit model
        /// </summary>
        private User? EditModel { get; set; }

        /// <summary>
        ///     Gets or sets a value indicating whether we are editing an existing user
        /// </summary>
        private bool IsEditing { get; set; }

        /// <summary>
        ///     Gets a value indicating whether the current editing user is the last admin
        /// </summary>
        private bool IsLastAdmin => IsEditing && EditModel?.Type == UserType.Admin && UserList?.Count(x => x.Type == UserType.Admin) <= 1;

        /// <summary>
        ///     Gets the value of the user groups (ab)
        /// </summary>
        private IEnumerable<UserGroup> UserGroups => Enum.GetValues<UserGroup>();

        /// <summary>
        ///     Gets or sets the value of the user list (ab)
        /// </summary>
        private List<User>? UserList { get; set; }

        /// <summary>
        ///     Gets the sorted users list
        /// </summary>
        private IEnumerable<User> SortedUsers => UserList?.OrderByDescending(x => x.Type).ThenBy(x => x.Name) ?? Enumerable.Empty<User>();

        #endregion

        #region Override InitializeDataAsync

        /// <inheritdoc />
        protected override async Task InitializeDataAsync()
        {
            if (!CurrentUser.IsAdmin()) NavigationManager.NavigateTo("/");
            await LoadUsers();
        }

        #endregion

        #region Private Method LoadUsers

        /// <summary>
        ///     Loads the users (a. beging, 01.04.2022)
        /// </summary>
        private async Task LoadUsers()
        {
            var usersR = await UserService.GetUsersAsync();
            if (usersR.Success) UserList = usersR.Data;

            await InvokeAsync(StateHasChanged);
        }

        #endregion

        #region Actions

        private void CreateNewUser()
        {
            EditModel = new User();
            IsEditing = false;
            editUserModal?.Show();
        }

        private void EditUser(User user)
        {
            EditModel = user.Clone();
            IsEditing = true;
            editUserModal?.Show();
        }

        private void SetPassword(User user)
        {
            PasswordModal?.Show(user);
        }

        private async Task SendPasswordSetupMail(User user)
        {
            await ConfirmDialog.ShowAsync(ModalService, "Bestätigen", $"Soll eine E-Mail zum Festlegen des Passworts an {user.Mail} gesendet werden?", async () =>
            {
                await AuthService.InitiateInitialPasswordSetup(user.Mail, NavigationManager.BaseUri);
                if (Notification != null)
                {
                    await Notification.Success("E-Mail gesendet. Bitte weise den Benutzer darauf hin, auch den Spam-Ordner zu prüfen.");
                }
            });
        }

        private async Task SaveUser()
        {
            if (EditModel == null) return;

            if (IsEditing)
            {
                var updateR = await UserService.Update(EditModel);
                if (!updateR.Success)
                    await Notification.Error($"Fehler beim Speichern: {updateR.ErrorMessage}")!;
                else
                    await Notification.Success("Benutzer aktualisiert");
            }
            else
            {
                var addUserR = await UserService.AddUserAsync(EditModel);
                if (!addUserR.Success)
                    await Notification.Error($"Fehler beim Anlegen: {addUserR.ErrorMessage}")!;
                else
                    await Notification.Success("Benutzer erstellt");
            }

            await editUserModal?.Hide()!;
            await LoadUsers();
        }

        #endregion

        #region Private Method OnPasswordSet

        /// <summary>
        ///     Ons the password set using the specified user (a. beging, 23.05.2022)
        /// </summary>
        /// <param name="user">The user</param>
        private async Task OnPasswordSet(User user)
        {
            var setPasswordR = await UserService.SetPassword(user);
            if (setPasswordR.Success)
                await Notification.Success("Passwort gespeichert");
        }

        #endregion

        #region Private Method RemoveUserAsync

        /// <summary>
        ///     Removes the specified user if they are not an admin, after confirming the action with a dialog.
        /// </summary>
        /// <param name="user">The user to be removed.</param>
        /// <returns>A task that represents the asynchronous remove operation.</returns>
        private async Task RemoveUserAsync(User user)
        {
            await ConfirmDialog.ShowAsync(ModalService, "Bestätigen", $"User {user.Mail} löschen?", async () =>
            {
                var removeR = await UserService.RemoveAsync(user.Id);
                if (!removeR.Success)
                    await Notification.Error($"Löschen: {removeR.ErrorMessage}")!;
                else
                    await LoadUsers();
            });
        }

        #endregion
    }
}