@using Blazored.LocalStorage;
@using Microsoft.AspNetCore.Identity;
@using MongoDB.Driver;
@using Insight.Infrastructure

@inject IServiceScopeFactory ServiceScopeFactory
@inject ILocalStorageService LocalStorageService
@inject IMongoDatabase Database
@inject AuthenticationStateProvider AuthenticationStateProvider

<MudThemeProvider Theme="CurrentTheme" IsDarkMode="DarkMode" />

@if (DisableIcon is false)
{
    <MudIconButton OnClick="@OnDarkModeToggleAsync" Icon="@(DarkMode ? Icons.Material.Filled.Brightness5 : Icons.Material.Filled.Brightness4)" Color="Color.Inherit" />
}

@code {
    [Parameter] public bool DisableIcon { get; set; }

    private MudTheme CurrentTheme { get; } = Themes.Default();
    private bool DarkMode { get; set; }

    protected override async Task OnInitializedAsync()
    {
        await LoadDarkModeAsync();
    }

    public async Task LoadDarkModeAsync()
    {
        // local storage
        var storageDarkMode = await LocalStorageService.GetItemAsync<bool?>("darkmode");
        if (storageDarkMode is bool darkmodeValue) DarkMode = darkmodeValue;

        // database override
        var state = await AuthenticationStateProvider.GetAuthenticationStateAsync();

        if (state?.User.Identity is not null && state.User.Identity.IsAuthenticated)
        {
            using var scope = ServiceScopeFactory.CreateScope();
            var userManager = scope.ServiceProvider.GetRequiredService<UserManager<InsightUser>>();

            if (await userManager.FindByNameAsync(state.User.Identity.Name) is not InsightUser user) return;

            var userPrefs = await Database.UserPreference()
                .Find(p => p.User == user.Id.ToString())
                .FirstOrDefaultAsync();

            if (userPrefs is null) return;

            DarkMode = userPrefs.DarkMode;

            await LocalStorageService.SetItemAsync("darkmode", DarkMode);
        }
    }

    private async Task OnDarkModeToggleAsync()
    {
        // update current
        DarkMode = !DarkMode;

        // update local storage
        await LocalStorageService.SetItemAsync("darkmode", DarkMode);

        // update database
        var state = await AuthenticationStateProvider.GetAuthenticationStateAsync();

        if (state?.User.Identity is not null && state.User.Identity.IsAuthenticated)
        {
            using var scope = ServiceScopeFactory.CreateScope();
            var userManager = scope.ServiceProvider.GetRequiredService<UserManager<InsightUser>>();

            if (await userManager.FindByNameAsync(state.User.Identity.Name) is not InsightUser user) return;

            var date = DateTime.Now;

            var userPrefs = await Database.UserPreference()
                .UpdateOneAsync(p => p.User == user.Id.ToString(), Builders<InsightUserPreferences>.Update
                .SetOnInsert(p => p.User, user.Id.ToString())
                .SetOnInsert(p => p.Insert, date)
                .Set(p => p.Update, date)
                .Set(p => p.DarkMode, DarkMode), new UpdateOptions
                    {
                        IsUpsert = true
                    });
        }

        await InvokeAsync(StateHasChanged);
    }
}