@page "/admin/searchpage"

@layout AdminControlPanelLayout

@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Authorization
@using Microsoft.EntityFrameworkCore

@using OpenArchival.Blazor.AdminPages.Shared
@using OpenArchival.Blazor.CustomComponents
@using MudBlazor
@using OpenArchival.DataAccess

@attribute [Authorize(Roles=UserRoles.Admin)]

<MudText Typo="Typo.h6">Search Page Featured Sliders</MudText>
<MudDivider></MudDivider>
<MudText Typo="Typo.subtitle1">Controls what artifacts are shown on the search page before a search happens. This is controlled via selecting tags. The first @ArtifactsPerSlider artifact with the listed tags will be shown in the slider. Only tags belonging to valid archive entries can be used. Entries must have all of the listed tags to be included in the slider.</MudText>

<MudTextField T="string" Placeholder="Title" @bind-Text="_titleInputValue"></MudTextField>
<MudTextField T="string" Placeholder="Description" @bind-Text="_descriptionInputValue"></MudTextField>
<MudGrid Justify="Justify.Center" Class="mt-4"> 
    <MudItem>
        <ChipContainer T="string" @ref="@_tagsChipContainer" @bind-Items="_selectedTagStrings" ItemRemoved="OnTagRemoved">
            <InputContent>
                <MudAutocomplete T="string"
                                 SearchFunc="Helpers.SearchTags"
                                 OnKeyDown="@(ev => HandleChipContainerEnter<string>(ev, _tagsChipContainer, _tagsInputValue, () => _tagsInputValue = string.Empty))"
                                 CoerceValue=true
                                 Placeholder="Add Tags..."
                                 ShowProgressIndicator="true"
                                 @bind-Value=@_tagsInputValue
                                 CoerceText=true
                                 >
                </MudAutocomplete>
            </InputContent>
        </ChipContainer>
    </MudItem>
    <MudItem>
        <MudButton 
            Variant="Variant.Filled" 
            Color="Color.Primary"
            OnClick="OnAddSlider">Add Slider</MudButton>
    </MudItem>
</MudGrid>

@foreach (SearchPageSliderEntry entry in SliderEntries)
{
    <MudPaper Class="pa-4 ma-2 rounded" Elevation="3">
        <MudButton StartIcon="@Icons.Material.Filled.Delete" Color="Color.Error" OnClick="() => OnDeleteSliderClicked(entry)">Delete</MudButton>
        <MudText Typo="Typo.h6">Title: @entry.Title</MudText>
        <MudText Typo="Typo.h6">Description: @entry.Description</MudText>
        <MudText Typo="Typo.h6">Tags:</MudText>
        <ChipContainer T="ArtifactEntryTag" Items="entry.FilterTags" DeleteEnabled=false></ChipContainer>
    </MudPaper>
}

@inject ArtifactEntrySharedHelpers Helpers;
@inject IDbContextFactory<ApplicationDbContext> ContextFactory; 
@inject ISnackbar Snackbar;
@code {
    [Parameter]
    public int ArtifactsPerSlider { get; set; } = 10;

    public List<SearchPageSliderEntry> SliderEntries { get; set; } = [];

    private string _tagsInputValue { get; set; } = "";
    private List<string> _selectedTagStrings { get; set; } = [];
    private List<ArtifactEntryTag> _selectedTags { get; set; } = [];

    private string _titleInputValue { get; set; } = "";

    private string _descriptionInputValue { get; set; } = "";

    private ChipContainer<string> _tagsChipContainer { get; set; } = default!;

    private async Task LoadSliders()
    {
        await using var context = await ContextFactory.CreateDbContextAsync();
        SliderEntries = await context.SearchPageSliderEntries.Include(se=>se.FilterTags).ToListAsync();
    }

    protected override async Task OnParametersSetAsync()
    {
        await LoadSliders();
    }

    public async Task HandleChipContainerEnter<Type>(KeyboardEventArgs args, ChipContainer<Type> container, Type value, Action resetInputAction)
    {
        if (args.Key == "Enter")
        {
            await using var context = await ContextFactory.CreateDbContextAsync();
            ArtifactEntryTag? tagToAdd = await context.ArtifactEntryTags.Where(tag => tag.Name == _tagsInputValue).FirstOrDefaultAsync();
            if (tagToAdd is null)
            {
                tagToAdd = new ArtifactEntryTag() { Name=_tagsInputValue };
            }
            _selectedTags.Add(tagToAdd);                

            await container.AddItem(value);
            resetInputAction?.Invoke();
            StateHasChanged();
        }
    }

    private async Task OnAddSlider(MouseEventArgs args)
    {
        if (string.IsNullOrEmpty(_titleInputValue))
        {
            Snackbar.Add("A slider title is required.", Severity.Error);
            return;
        }

        if (!_selectedTags.Any()) {
            Snackbar.Add("At least one tag is required", Severity.Error);
            return;
        }

        await using var context = await ContextFactory.CreateDbContextAsync();

        // Attach all of the existing tags to the context
        foreach (var tag in _selectedTags.Where(t => t.Id != 0))
        {
            context.ArtifactEntryTags.Attach(tag);
        }

        context.SearchPageSliderEntries.Add(new SearchPageSliderEntry(){
            Title=_titleInputValue, 
            Description=_descriptionInputValue,
            FilterTags=_selectedTags
        });
        await context.SaveChangesAsync();

        Snackbar.Add("Added slider", Severity.Success);

        _selectedTags.Clear();
        _selectedTagStrings.Clear();
        _titleInputValue = "";
        _descriptionInputValue = "";

        LoadSliders();
        StateHasChanged();
    }

    private void OnTagRemoved(string tagString)
    {
        int countRemoved = _selectedTags.RemoveAll(t => t.Name == tagString);

        if (countRemoved != 1)
        {
            throw new ArgumentException("Did not remove 1 element from the list of tags");
        }
    }

    private async Task OnDeleteSliderClicked(SearchPageSliderEntry entry)
    {
        await using var context = await ContextFactory.CreateDbContextAsync();
        SearchPageSliderEntry? entryToRemove = await context.SearchPageSliderEntries.Where(en => en.Id == entry.Id).FirstOrDefaultAsync();
        if (entryToRemove is null)
        {
            throw new ArgumentException("The entry to remove was null and not in the database");
        }

        SliderEntries.Remove(entry);
        context.SearchPageSliderEntries.Remove(entryToRemove);
        await context.SaveChangesAsync();

        StateHasChanged();
    }
}
