@page "/PrivateList"
@rendermode InteractiveServer

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

@inject ApplicationDbContext CouchLogDb
@inject UserManager<ApplicationUser> UserManager
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject NavigationManager NavigationManager

@attribute [Authorize]

<PageTitle>Private List</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;">Private List</MudText>
        </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">
                No Filters avalible yet!
                <!--@*Entity allready added*@
                <MudSwitch @bind-Value="_showAlreadyAddedEntities" Color="Color.Primary">
                    Show already added Entities
                </MudSwitch>-->
                @*To be exstendet*@
            </MudCollapse>
        </MudPaper>
    </MudContainer>
    
    <br/>


    <!--<editor-fold desc="Active Watching">-->
    <MudContainer MaxWidth="MaxWidth.False">
        <MudText Typo="Typo.h4">Active Watching</MudText>
        <br/>
        <MudGrid Spacing="6" Justify="Justify.Center">
            @foreach (var privateEntity in VisibleActiveWatchingEntities)
            {
                <MudItem xs="12" sm="8" md="6" lg="4">
                    <PrivateEntityCard 
                        PrivateEntity="privateEntity" 
                        UserWatchStatuses="_userWatchStatuses"
                        OnWatchStatusChange="@(newStatusId => ChangeWatchStatus(privateEntity, newStatusId))"
                        OnSeasonChange="@(newSeason => ChangeSeason(privateEntity, newSeason))"
                        OnEpisodeChange="@(newEpisode => ChangeEpisode(privateEntity, newEpisode))"
                        OnRemove="() => RemovePrivateEntity(privateEntity)"
                    />
                </MudItem>
            }
        </MudGrid>
    </MudContainer>
    <br/>
    
    <MudContainer>
        <MudStack AlignItems="AlignItems.Center">
            <MudPagination Count="@TotalPagesActiveWatching" @bind-Selected="_currentActiveWatchingPage"/>
        </MudStack>
    </MudContainer>
    <!--</editor-fold>-->
    
    <br/>
    
    <!--<editor-fold desc="Library">-->
    <MudContainer MaxWidth="MaxWidth.False">
        <MudText Typo="Typo.h4">Library</MudText>
        <MudGrid Spacing="6" Justify="Justify.Center">
            @foreach (var privateEntity in VisibleLibraryEntities)
            {
                <MudItem xs="12" sm="8" md="6" lg="4">
                    <PrivateEntityCard 
                        PrivateEntity="privateEntity" 
                        UserWatchStatuses="_userWatchStatuses"
                        OnWatchStatusChange="@(newStatusId => ChangeWatchStatus(privateEntity, newStatusId))"
                        OnSeasonChange="@(newSeason => ChangeSeason(privateEntity, newSeason))"
                        OnEpisodeChange="@(newEpisode => ChangeEpisode(privateEntity, newEpisode))"
                        OnRemove="() => RemovePrivateEntity(privateEntity)"
                    />
                </MudItem>
            }
        </MudGrid>
    </MudContainer>
    
    <br/>
    
    <MudContainer>
        <MudStack AlignItems="AlignItems.Center">
            <MudPagination Count="@TotalPagesLibrary" @bind-Selected="_currentLibraryPage"/>
        </MudStack>
    </MudContainer>
    <!--</editor-fold>-->
</MudContainer>

@code
{
    //Filter
    private string? _searchString;
    private bool _showFilters;
    private bool _showAlreadyAddedEntities = false;
    private IEnumerable<PrivateEntity> FiltertGlobalEntities => _privateEntities.Where(entity =>
            (string.IsNullOrWhiteSpace(_searchString) || entity.GlobalEntity.Title.Contains(_searchString, StringComparison.OrdinalIgnoreCase)) //Search bar
    );
    
    //Paging Active Watching
    private int _currentActiveWatchingPage = 1;
    private readonly int _pageSizeActiveWatching = 12;
    private int TotalPagesActiveWatching => (int)Math.Ceiling(ActiveWatchingEntities.Count() / (double)_pageSizeActiveWatching);
    private IEnumerable<PrivateEntity> VisibleActiveWatchingEntities => ActiveWatchingEntities.Skip((_currentActiveWatchingPage - 1) * _pageSizeActiveWatching).Take(_pageSizeActiveWatching);
    
    //Paging Library
    private int _currentLibraryPage = 1;
    private readonly int _pageSizeLibrary = 12;
    private int TotalPagesLibrary => (int)Math.Ceiling(LibraryEntities.Count() / (double)_pageSizeLibrary);
    private IEnumerable<PrivateEntity> VisibleLibraryEntities => LibraryEntities.Skip((_currentLibraryPage - 1) * _pageSizeLibrary).Take(_pageSizeLibrary);
    
    //User
    private ApplicationUser? _appUser;
    
    //Entities
    private List<PrivateEntity> _privateEntities = [];
    private List<UserWatchStatus> _userWatchStatuses = [];

    private IEnumerable<PrivateEntity> ActiveWatchingEntities => FiltertGlobalEntities.Where(x => x.UserWatchStatus?.Name == "Watching").ToList();
    private IEnumerable<PrivateEntity> LibraryEntities => FiltertGlobalEntities.Where(x => x.UserWatchStatus?.Name != "Watching").ToList();

    protected override async Task OnInitializedAsync()
    {
        await GetPrivateEntities();

        _userWatchStatuses = await CouchLogDb.UserWatchStatuses.OrderBy(entity => entity.Id).ToListAsync();
    }

    private async Task GetPrivateEntities()
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        _appUser = await UserManager.GetUserAsync(authState.User);

        if (_appUser != null)
        {
            _privateEntities = await CouchLogDb.PrivateEntities
                .Where(x => x.UserId == _appUser.Id)
                .Include(x => x.GlobalEntity)
                .Include(x => x.UserWatchStatus)
                .Include(x => x.GlobalEntity.MediaType)
                .OrderByDescending(entity => entity.LastChange ?? entity.CreationTime)
                .ToListAsync();
        }
    }

    private async Task RefreshPages()
    {
        _currentLibraryPage = 1;
        _currentActiveWatchingPage = 1;
        StateHasChanged();
    }

    private async Task ChangeWatchStatus(PrivateEntity privateEntity, int newUserWatchStatusId)
    {
        privateEntity.UserWatchStatus = _userWatchStatuses.FirstOrDefault(s => s.Id == newUserWatchStatusId);
        await CouchLogDb.SaveChangesAsync();
    }

    private async Task ChangeSeason(PrivateEntity privateEntity, int? newSeason)
    {
        privateEntity.Season = newSeason;
        await CouchLogDb.SaveChangesAsync();
    }

    private async Task ChangeEpisode(PrivateEntity privateEntity, int? newEpisode)
    {
        privateEntity.Episode = newEpisode;
        await CouchLogDb.SaveChangesAsync();
    }

    private async Task RemovePrivateEntity(PrivateEntity privateEntity)
    {
        CouchLogDb.PrivateEntities.Remove(privateEntity);
        await CouchLogDb.SaveChangesAsync();
        await GetPrivateEntities();
    }
}