@namespace OpenArchival.Blazor.AdminPages.Shared
@using Microsoft.AspNetCore.Components.Web
@using OpenArchival.DataAccess
@using System.ComponentModel.DataAnnotations
@using OpenArchival.Blazor.CustomComponents
@using MudBlazor

@inject ArtifactEntrySharedHelpers Helpers;
@inject IArtifactDefectProvider DefectsProvider;
@inject IArtifactStorageLocationProvider StorageLocationProvider;
@inject IArchiveEntryTagProvider TagsProvider;
@inject IArtifactTypeProvider TypesProvider;
@inject IListedNameProvider ListedNameProvider;

<MudPaper Class="pa-4 ma-2 rounded" Elevation="3">
    <MudGrid>
        <MudItem>
            @if (Model.Files.Count > 0) {
                <MudText Typo="Typo.h6">@(Model.Files[0].OriginalName)</MudText>
            }
        </MudItem>
        <MudItem>
            <MudButton 
                Variant="Variant.Filled" 
                StartIcon="@Icons.Material.Filled.Delete" 
                Color="Color.Error"
                OnClick="OnDeleteEntryClicked"
                >Delete</MudButton>

        </MudItem>
    </MudGrid>

    @foreach (var error in ValidationResults)
    {
        <MudAlert Severity="Severity.Error">
            @error.ErrorMessage
        </MudAlert>
    }

    <MudText Typo="Typo.h6" Color="Color.Primary" Class="pt-4 pb-0">Archive Item Title</MudText>
    <MudDivider DividerType="DividerType.Middle"></MudDivider>
    <MudTextField For="@(() => Model.Title)" Required=true Placeholder="Archive Item Title" T="string" Class="pl-4 pr-4" @bind-Value=Model.Title @bind-Value:after=OnInputsChanged></MudTextField>

    <MudText Typo="Typo.h6" Color="Color.Primary" Class="pt-4 pb-0">Archive Item Numbering</MudText>
    <MudText Typo="Typo.caption" Color="Color.Secondary" Class="pb-2">Enter a unique ID for this entry</MudText>
    <MudDivider DividerType="DividerType.Middle"></MudDivider>
    <MudTextField For="@(() => Model.ArtifactNumber)" Placeholder="Numbering" T="string" @bind-Value=Model.ArtifactNumber @bind-Value:after=OnInputsChanged/> 
    
    <MudText Typo="Typo.h6" Color="Color.Primary" Class="pt-4 pb-0">Item Description</MudText>
    <MudDivider DividerType="DividerType.Middle"></MudDivider>
    <MudTextField For="@(() => Model.Description)" Lines=8 Placeholder="Description" T="string" Class="pl-4 pr-4" @bind-Value=Model.Description @bind-Value:after=OnInputsChanged></MudTextField>

    <MudText Typo="Typo.h6" Color="Color.Primary" Class="pt-4 pb-0">Item Quantity</MudText>
    <MudDivider DividerType="DividerType.Middle"></MudDivider>
    <MudNumericField Min="0" @bind-Value=Model.Quantity></MudNumericField>


    <MudText Typo="Typo.h6" Color="Color.Primary" Class="pt-4 pb-0">Storage Location</MudText>
    <MudDivider DividerType="DividerType.Middle"></MudDivider>
    <MudAutocomplete For="@(() => Model.StorageLocation)" T="string" Label="Storage Location" Class="pt-0 mt-0 pl-2 pr-2" @bind-Value=Model.StorageLocation @bind-Value:after=OnInputsChanged SearchFunc="Helpers.SearchStorageLocation" CoerceValue=true></MudAutocomplete>

    <MudText Typo="Typo.h6" Color="Color.Primary" Class="pt-4 pb-0">Artifact Type</MudText>
    <MudDivider DividerType="DividerType.Middle"></MudDivider>
    <MudAutocomplete For="@(() => Model.Type)" T="string" Label="Artifact Type" Class="pt-0 mt-0 pl-2 pr-2" @bind-Value=Model.Type @bind-Value:after=OnInputsChanged SearchFunc="Helpers.SearchItemTypes" CoerceValue=true Clearable="true"></MudAutocomplete>

    @* Tags entry *@ 
    <MudText Typo="Typo.h6" Color="Color.Primary" Class="pt-4 pb-0">Tags</MudText>
    <MudDivider DividerType="DividerType.Middle"></MudDivider>
    <ChipContainer T="string" @ref="@_tagsChipContainer" @bind-Items="Model.Tags">
        <InputContent>
            <MudAutocomplete T="string"
                             OnInternalInputChanged="OnInputsChanged"
                             SearchFunc="Helpers.SearchTags"
                             Value="_tagsInputValue"
                             ValueChanged="OnTagsInputTextChanged"
                             OnKeyDown="@(ev => HandleChipContainerEnter<string>(ev, _tagsChipContainer, _tagsInputValue, () => _tagsInputValue = string.Empty))"
                             CoerceValue=true
                             Placeholder="Add Tags..."
                             ShowProgressIndicator="true"
                             >
            </MudAutocomplete>
        </InputContent>
    </ChipContainer>

    <MudText Typo="Typo.h6" Color="Color.Primary" Class="pt-4 pb-0">Listed Names</MudText>
    <MudText Typo="Typo.caption" Color="Color.Secondary" Class="pb-2">Enter any names of the people associated with this entry.</MudText>
    <MudDivider DividerType="DividerType.Middle"></MudDivider>
    <ChipContainer T="string" @ref=_listedNamesChipContainer @bind-Items="Model.ListedNames">
        <InputContent>
            <MudAutocomplete T="string"
                             SearchFunc="Helpers.SearchListedNames"
                             OnInternalInputChanged="OnInputsChanged"
                             Value="_listedNamesInputValue"
                             ValueChanged="OnListedNamesTextChanged"
                             OnKeyDown="@(ev=>HandleChipContainerEnter<string>(ev, _listedNamesChipContainer, _listedNamesInputValue, () => _listedNamesInputValue = string.Empty))"
                             CoerceValue=true
                             Placeholder="Add Listed Names..."
                             ShowProgressIndicator=true>
            </MudAutocomplete>
        </InputContent>
    </ChipContainer>

    <MudText Typo="Typo.h6" Color="Color.Primary" Class="pt-4 pb-0">Associated Dates</MudText>
    <MudDivider DividerType="DividerType.Middle"></MudDivider>
    <ChipContainer T="DateTime" @ref="_assocaitedDatesChipContainer" @bind-Items="Model.AssociatedDates" DisplayFunc="date => date.ToShortDateString()">
        <InputContent>
            <MudDatePicker @bind-Date=_associatedDateInputValue MinDate="new DateTime(1000, 1, 1)">
            </MudDatePicker>
        </InputContent>
        <SubmitButton>
            <MudButton Color="Color.Primary"
                       OnClick="HandleAssociatedDateChipContainerAdd">+</MudButton>
        </SubmitButton>
    </ChipContainer>

    <MudText Typo="Typo.h6" Color="Color.Primary" Class="pt-4 pb-0">Defects</MudText>
    <MudDivider DividerType="DividerType.Middle"></MudDivider>
    <ChipContainer T="string" @ref=_defectsChipContainer @bind-Items="Model.Defects">
        <InputContent>
            <MudAutocomplete T="string"
                             SearchFunc="Helpers.SearchDefects"
                             OnInternalInputChanged="OnInputsChanged"
                             Value="_defectsInputValue"
                             ValueChanged="OnDefectsValueChanged"
                             OnKeyDown="@(ev=>HandleChipContainerEnter<string>(ev, _defectsChipContainer, _defectsInputValue, () => _defectsInputValue = string.Empty))"
                             CoerceValue=true
                             Placeholder="Add Defects..."
                             ShowProgressIndicator=true>
            </MudAutocomplete>
        </InputContent>
    </ChipContainer>

    <MudText Typo="Typo.h6" Color="Color.Primary" Class="pt-4 pb-0">Related Artifacts</MudText>
    <MudText Typo="Typo.caption" Color="Color.Secondary" Class="pb-2">Tag this entry with the identifier of any other entry to link them.</MudText>
    <MudDivider DividerType="DividerType.Middle"></MudDivider>
    <ChipContainer T="ArtifactEntry" @ref="_assocaitedArtifactsChipContainer" @bind-Items="Model.RelatedArtifacts" DisplayFunc="artifact => artifact.ArtifactIdentifier">
        <InputContent>
            <MudAutocomplete T="ArtifactEntry"
                             OnInternalInputChanged="OnInputsChanged"
                             Value="_associatedArtifactValue"
                             ValueChanged="OnAssociatedArtifactChanged"
                             OnKeyDown="@(EventArgs=>HandleChipContainerEnter<ArtifactEntry>(EventArgs, _assocaitedArtifactsChipContainer, _associatedArtifactValue, () => _associatedArtifactValue = null))"
                             CoerceValue="false"
                             Placeholder="Link artifact groupings..."
                             ShowProgressIndicator=true>
            </MudAutocomplete>
        </InputContent>
    </ChipContainer>

    <MudText Typo="Typo.h6" Color="Color.Primary" Class="pt-4 pb-0">Artifact Text Contents</MudText>
    <MudText Typo="Typo.caption" Color="Color.Secondary" Class="pb-2">Input the text transcription of the words on the artifact if applicable to aid the search engine.</MudText>
    <MudDivider DividerType="DividerType.Middle"></MudDivider>
    <MudTextField T="string"
                  Value=Model.FileTextContent                  
                  ValueChanged="OnArtifactTextContentChanged"
                  Lines="5"
    For="@(() => Model.FileTextContent)"></MudTextField>

    <MudText Typo=Typo.h6 Color="Color.Primary">Additional files</MudText>
    <UploadDropBox @ref=_uploadDropBox FilesUploaded="OnFilesUploaded"></UploadDropBox>
</MudPaper>


@code {
    [Parameter]
    public FilePathListing? MainFilePath { get; set; }

    [Parameter]
    public EventCallback<ArtifactEntryValidationModel> ModelChanged { get; set; }

    [Parameter]
    public EventCallback InputsChanged { get; set; }

    [Parameter]
    public required ArtifactEntryValidationModel Model { get; set; } = new() { StorageLocation = "hello", Title = "Hello" };

    [Parameter]
    public required int ArtifactEntryIndex {get; set;} 

    [Parameter] 
    public EventCallback<(int index, string filename)> OnEntryDeletedClicked { get; set; }

    private ChipContainer<string> _tagsChipContainer;

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

    private ChipContainer<DateTime> _assocaitedDatesChipContainer;

    private DateTime? _associatedDateInputValue { get; set; } = default;

    private ChipContainer<string> _listedNamesChipContainer;

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

    private ChipContainer<string> _defectsChipContainer;

    private string _defectsInputValue = "";

    private ChipContainer<ArtifactEntry> _assocaitedArtifactsChipContainer;

    private ArtifactEntry? _associatedArtifactValue = null;

    private string _artifactTextContent = "";

    public bool IsValid { get; set; }

    public List<ValidationResult> ValidationResults { get; private set; } = [];

    public UploadDropBox _uploadDropBox = default!;

    protected override Task OnParametersSetAsync()
    {
        if (_uploadDropBox is not null && Model is not null && Model.Files is not null)
        {
            if (Model.Files.Count > 1)
            {
                _uploadDropBox.ExistingFiles = Model.Files.GetRange(1, Model.Files.Count - 1);
            } else
            {
                _uploadDropBox.ExistingFiles = [];
            }
        }

        if (Model.Files is not null && Model.Files.Any())
        {
            MainFilePath = Model.Files[0];
        }

        return base.OnParametersSetAsync();
    }

    public async Task OnInputsChanged()
    {
        // 1. Clear previous validation errors
        ValidationResults.Clear();

        var validationContext = new ValidationContext(Model);

        // 2. Run the validator
        IsValid = Validator.TryValidateObject(Model, validationContext, ValidationResults, validateAllProperties: true);
        // 3. REMOVE this line. Let the parent's update trigger the re-render.
        // StateHasChanged();

        await InputsChanged.InvokeAsync();
    }

    private async Task OnFilesUploaded(List<FilePathListing> filePathListings)
    {
        if (MainFilePath is not null)
        {
            var oldFiles = Model.Files.Count > 1 ? Model.Files.GetRange(1, Model.Files.Count - 1) : new List<FilePathListing>();
            Model.Files = [MainFilePath];
            Model.Files.AddRange(oldFiles);
        } else
        {
            Model.Files = [];
        }

        Model.Files.AddRange(filePathListings);
        StateHasChanged();
    }

    private async Task OnFilesCleared()
    {
        if (MainFilePath is not null) {
            Model.Files = [MainFilePath];
        } else
        {
            Model.Files = [];
        }
    }

    private Task OnDefectsValueChanged(string text)
    {
        _defectsInputValue = text;
        return ModelChanged.InvokeAsync(Model);
    }

    private Task OnTagsInputTextChanged(string text)
    {
        _tagsInputValue = text;
        return ModelChanged.InvokeAsync(Model);
    }

    private Task OnListedNamesTextChanged(string text)
    {
        _listedNamesInputValue = text;
        return ModelChanged.InvokeAsync(Model);
    }

    private Task OnAssociatedArtifactChanged(ArtifactEntry grouping)
    {
        if (grouping is not null)
        {
            _associatedArtifactValue = grouping;
            return ModelChanged.InvokeAsync(Model);
        }

        return ModelChanged.InvokeAsync(Model);
    }

    private Task OnArtifactTextContentChanged(string value)
    {
        Model.FileTextContent = value;
        return ModelChanged.InvokeAsync(Model);
    }

    public async Task HandleChipContainerEnter<Type>(KeyboardEventArgs args, ChipContainer<Type> container, Type value, Action resetInputAction)
    {
        if (args.Key == "Enter")
        {
            await container.AddItem(value);
            resetInputAction?.Invoke();
            StateHasChanged();
            await ModelChanged.InvokeAsync(Model);
        }
    }

    public async Task HandleAssociatedDateChipContainerAdd(MouseEventArgs args)
    {
        if (_associatedDateInputValue is not null)
        {
            DateTime unspecifiedDate = (DateTime)_associatedDateInputValue;

            DateTime utcDate = DateTime.SpecifyKind(unspecifiedDate, DateTimeKind.Utc);

            await _assocaitedDatesChipContainer.AddItem(utcDate);

            _associatedDateInputValue = default;
        }
    }
    private async Task OnDeleteEntryClicked(MouseEventArgs args)
    {
        var filename = MainFilePath?.OriginalName ?? string.Empty;
        await OnEntryDeletedClicked.InvokeAsync((ArtifactEntryIndex, MainFilePath.OriginalName));
    } 
}