@page "/GlobalList"
@rendermode InteractiveServer

@using Microsoft.AspNetCore.Authorization
@using CouchLog.Data
@using Microsoft.AspNetCore.Identity
@using Microsoft.EntityFrameworkCore
@using CouchLog.Components.Pages.GlobalList.Dialogs
@using CouchLog.Components.Pages.GlobalList.Components

@inject ApplicationDbContext CouchLogDb
@inject UserManager<ApplicationUser> UserManager
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject IDialogService DialogService
@inject ISnackbar Snackbar

@attribute [Authorize]

<PageTitle>GlobalList</PageTitle>

<MudContainer MaxWidth="MaxWidth.False">
    @*Top of the Page*@
    <MudContainer>
        <MudStack Row="true" AlignItems="AlignItems.Center">
            @*Page Title*@
            <MudText Typo="Typo.h3" Style="font-weight: bold;">Global List</MudText>
            
            @*Spacer*@
            <MudSpacer />

            @*Button for adding GlobalEntity*@
            <MudTooltip Text="Add GlobalEntity">
                <MudFab StartIcon="@Icons.Material.Filled.Add" Color="Color.Primary" OnClick="OpenAddNewGlobalEntityDialog"/>
            </MudTooltip>
        </MudStack>
    </MudContainer>
    
    <br/>
    
    <MudContainer>
        <MudPaper Class="pa-2" Elevation="1">
            <MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
                @*Search bar*@
                <MudTextField @bind-Value="_searchString"
                              Placeholder="Search..."
                              Adornment="Adornment.Start"
                              AdornmentIcon="@Icons.Material.Filled.Search"
                              Immediate="true"
                              Variant="Variant.Outlined"
                              Margin="Margin.Dense"
                              Style="max-width: 300px;"/>
                @*Refresh button*@
                @*<MudTooltip Text="Refresh Entities">
                    <MudIconButton Icon="@Icons.Material.Filled.Refresh" OnClick="RefreshPage"/>
                </MudTooltip>*@
                @*More Filters button*@
                <MudTooltip Text="More filters">
                    <MudIconButton Icon="@(_showFilters
                                             ? Icons.Material.Filled.ExpandLess
                                             : Icons.Material.Filled.FilterList)"
                                   OnClick="@(() => _showFilters = !_showFilters)"
                                   Color="Color.Default"/>
                </MudTooltip>
            </MudStack>
            <MudCollapse Expanded="_showFilters">
                @*Entity allready added*@
                <MudSwitch @bind-Value="_showAlreadyAddedEntities" Color="Color.Primary">
                    Show already added Entities
                </MudSwitch>
                @*To be exstendet*@
            </MudCollapse>
        </MudPaper>
    </MudContainer>
    
    <br/>
    
    <MudContainer MaxWidth="MaxWidth.False">
        <MudGrid Spacing="6" Justify="Justify.Center">
            @foreach (var globalEntity in VisibleGlobalEntities)
            {
                <MudItem xs="12" sm="6" md="4" lg="3" xl="2">
                    <GlobalEntityCard GlobalEntity="globalEntity"
                                      UserPrivateEntityIds="_userPrivateEntityIds"
                                      OnAddToPrivate="AddGlobalEntityToPrivateList"
                                      OnAddToShared="AddGlobalEntityToSharedList"/>
                </MudItem>
            }
        </MudGrid>
    </MudContainer>
    
    <br/>
    
    <MudContainer>
        <MudStack AlignItems="AlignItems.Center">
            <MudPagination Count="@TotalPages" @bind-Selected="_currentPage"/>
        </MudStack>
    </MudContainer>
</MudContainer>

@code
{
    //Filter
    private string? _searchString;
    private bool _showFilters;
    private bool _showAlreadyAddedEntities = false;
    private IEnumerable<GlobalEntity> FiltertGlobalEntities => _globalEntities.Where(entity =>
        (string.IsNullOrWhiteSpace(_searchString) || entity.Title.Contains(_searchString, StringComparison.OrdinalIgnoreCase)) && //Search bar
        (_showAlreadyAddedEntities || !_userPrivateEntityIds.Contains(entity.Id)) //Filter for already added Entitys
        );
    
    //Paging
    private int _currentPage = 1;
    private int _pageSize = 12;
    private int TotalPages => (int)Math.Ceiling(FiltertGlobalEntities.Count() / (double)_pageSize);
    private IEnumerable<GlobalEntity> VisibleGlobalEntities => FiltertGlobalEntities.Skip((_currentPage - 1) * _pageSize).Take(_pageSize);
    
    //User
    private ApplicationUser? _appUser;
    
    //Core
    private List<GlobalEntity> _globalEntities = [];
    private HashSet<int> _userPrivateEntityIds = [];
    
    protected override async Task OnInitializedAsync()
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        _appUser = await UserManager.GetUserAsync(authState.User);

        if (_appUser is null)
        {
            Snackbar.Add("Not authenticated.", Severity.Error);
            return;
        }
        
        _globalEntities = await CouchLogDb.GlobalEntities
            .OrderByDescending(entity => entity.CreationTime)
            .Where(entity => !entity.IsPrivate || (entity.IsPrivate && entity.CreatorId == _appUser.Id))
            .ToListAsync();

        _userPrivateEntityIds = await CouchLogDb.PrivateEntities
            .Where(entity => entity.UserId == _appUser.Id)
            .Select(p => p.GlobalEntityId)
            .ToHashSetAsync();
    }

    private async Task RefreshPage()
    {
        _currentPage = 1;
        StateHasChanged();
    }

    private async Task OnNewEntity(GlobalEntity entity)
    {
        _globalEntities.Add(entity);
        await RefreshPage();
    }
    
    private async Task OpenAddNewGlobalEntityDialog()
    {
        var dialog = await DialogService.ShowAsync<AddNewGlobalEntityDialog>("Add new Global Entity");
        var result = await dialog.Result;
        if (!result!.Canceled)
        {
            var entity = (GlobalEntity)result.Data!;
            await OnNewEntity(entity);
        }
    }
    
    public async Task AddGlobalEntityToPrivateList(GlobalEntity globalEntity)
    {
        if(_appUser is null) { Snackbar.Add("Not logged in!", Severity.Error); return;}
        
        if (!await IsInPrivateList(globalEntity.Id))
        {
            PrivateEntity privateEntity = new()
            {
                UserId = _appUser.Id,
                CreationTime = DateTime.Now,
                GlobalEntityId = globalEntity.Id,
                UserWatchStatusId = 1,
                //Season = 0,
                //Episode = 0
            };

            CouchLogDb.PrivateEntities.Add(privateEntity);
            await CouchLogDb.SaveChangesAsync();
            
            _userPrivateEntityIds.Add(globalEntity.Id);
            StateHasChanged();
            Snackbar.Add("Added Entity to private List", Severity.Success);
        }
        else
        {
            Snackbar.Add("Entity already in private List!", Severity.Warning);
        }
    }

    private async Task<bool> IsInPrivateList(int globalEntityId)
    {
        if (_appUser is null) return false;
        
        return await CouchLogDb.PrivateEntities.Where(entity => entity.UserId == _appUser.Id).AnyAsync(entity => entity.GlobalEntityId == globalEntityId);
    }
    
    private void AddGlobalEntityToSharedList()
    {
        Snackbar.Add("Feature not implemented yet!", Severity.Error);
    }
}