using Microsoft.AspNetCore.Components;

namespace Guestlist.Components.Pages;

public partial class Setup : ComponentBase
{
    [Inject]
    protected SetupStatusService SetupStatusService { get; set; } = default!;

    [Inject]
    protected UserService UserService { get; set; } = default!;
    
    [Inject]
    protected AccessCodeService AccessCodeService { get; set; } = default!;
    
    protected string Username { get; set; } = "";
    protected string DisplayName { get; set; } = "";
    protected string Password { get; set; } = "";
    protected string ErrorMessage { get; set; } = "";
    
    protected bool? HasAnyUsers { get; set; }
    protected bool? HasAnyUserBackups { get; set; }
    
    protected string GuestAccessCode { get; set; } = "";
    
    protected bool? IsSetupComplete { get; set; }

    protected override async Task OnInitializedAsync()
    {
        try
        {
            IsSetupComplete = await SetupStatusService.IsSetupCompleteAsync();
            HasAnyUsers = await UserService.HasAnyUsersAsync();
            HasAnyUserBackups = await UserService.HasAnyUserBackupsAsync();
        }
        catch
        {
            ErrorMessage = "Setup status could not be loaded. Please try again.";
            IsSetupComplete = false;
            HasAnyUsers = false;
            HasAnyUserBackups = false;
        }
    }
    
    protected async Task CompleteSetup()
    {
        ErrorMessage = "";

        if (await UserService.HasAnyUsersAsync())
        {
            ErrorMessage = "Setup cannot create another initial admin user!";
            return;
        }

        if (string.IsNullOrWhiteSpace(Username))
        {
            ErrorMessage = "Provide a username.";
            return;
        }
        
        if (string.IsNullOrWhiteSpace(DisplayName))
        {
            DisplayName = Username;
        }

        if (string.IsNullOrWhiteSpace(Password))
        {
            ErrorMessage = "Provide a password.";
            return;
        }

        if (Password.Length < 8)
        {
            ErrorMessage = "Password must be at least 8 characters long.";
            return;
        }
        
        if (string.IsNullOrWhiteSpace(GuestAccessCode))
        {
            ErrorMessage = "Provide a guest access code.";
            return;
        }

        var adminCreated = false;

        try
        {
            await UserService.CreateAdminAsync(DisplayName, Username, Password);
            adminCreated = true;

            await AccessCodeService.SetGuestAccessCodeAsync(GuestAccessCode);
            await SetupStatusService.MarkSetupCompleteAsync();
        }
        catch (InvalidOperationException exception)
        {
            ErrorMessage = exception.Message;
            return;
        }
        catch
        {
            if (adminCreated)
            {
                await UserService.DeleteUserByUsernameAsync(Username);
            }

            HasAnyUsers = await UserService.HasAnyUsersAsync();
            ErrorMessage = "Setup could not be completed. No partial admin user was kept.";
            return;
        }

        GuestAccessCode = "";
        Password = "";
        HasAnyUsers = true;
        IsSetupComplete = true;
    }
    
    protected async Task RestoreLatestBackup()
    {
        ErrorMessage = "";

        if (HasAnyUsers == true)
        {
            ErrorMessage = "Cannot restore backup while users already exist.";
            return;
        }

        if (HasAnyUserBackups != true)
        {
            ErrorMessage = "No user backups found.";
            return;
        }

        bool restored;

        try
        {
            restored = await UserService.RestoreLatestUserBackupAsync();
        }
        catch
        {
            ErrorMessage = "Could not restore latest user backup.";
            return;
        }

        if (!restored)
        {
            ErrorMessage = "Could not restore latest user backup.";
            return;
        }

        try
        {
            await SetupStatusService.MarkSetupCompleteAsync();
        }
        catch
        {
            ErrorMessage = "Backup was restored, but setup status could not be updated.";
            return;
        }
        
        HasAnyUsers = true;
        IsSetupComplete = true;
        HasAnyUserBackups = await UserService.HasAnyUserBackupsAsync();
        
        ErrorMessage = "Latest user backup has been restored.";
    }
}
