@if (Title != null)
{
    <MudText Typo="Typo.h4">@Title</MudText>
}

<MudAutocomplete T="Student"
                 Label="@Label"
                 @bind-Value="_currentStudent"
                 SearchFunc="@SearchStudents"
                 ToStringFunc="@(s => ShowFullName ? s?.FirstNameLastName : s?.FirstName)"
                 Immediate="true"
                 ResetValueOnEmptyText="true"
                 CoerceText="false"
                 CoerceValue="false"
                 AdornmentIcon="@Icons.Material.Filled.Search"
                 Clearable="true">
    <ItemTemplate Context="student">
        @if (ShowFullName)
        {
            @student.FirstNameLastName
        }
        else
        {
            @student.FirstName
        }
        @if (ShowGrade)
        {
            <MudText Typo="Typo.caption" Color="Color.Secondary"> - Grade @student.Grade</MudText>
        }
    </ItemTemplate>
</MudAutocomplete>

@if (SelectedStudents.Any())
{
    <MudChipSet T="Student" AllClosable="true" Class="mt-2">
        @foreach (var student in SelectedStudents.OrderBy(s => s.FirstName))
        {
            <MudChip T="Student"
                     Value="@student"
                     Text="@(ShowFullName ? student.FirstNameLastName : student.FirstName)"
                     OnClose="@(() => RemoveStudent(student))" />
        }
    </MudChipSet>
}

@code {
    [Parameter]
    public IEnumerable<Student> Students { get; set; } = [];

    [Parameter]
    public IEnumerable<Student> SelectedStudents { get; set; } = [];

    [Parameter]
    public EventCallback<IEnumerable<Student>> SelectedStudentsChanged { get; set; }

    [Parameter]
    public string? Title { get; set; }

    [Parameter]
    public string Label { get; set; } = "Search Students";

    [Parameter]
    public bool ShowFullName { get; set; } = true;

    [Parameter]
    public bool ShowGrade { get; set; } = false;

    private Student? _currentStudent
    {
        get => _currentStudentValue;
        set
        {
            _currentStudentValue = value;
            if (value != null && !SelectedStudents.Contains(value))
            {
                var updatedList = SelectedStudents.Append(value).ToList();
                SelectedStudentsChanged.InvokeAsync(updatedList);
                _currentStudentValue = null;
            }
        }
    }

    private Student? _currentStudentValue;

    private async Task<IEnumerable<Student>> SearchStudents(string? searchText, CancellationToken cancellationToken)
    {
        if (string.IsNullOrWhiteSpace(searchText))
            return Students.Where(s => !SelectedStudents.Contains(s));

        var search = searchText.ToLower();
        return Students
            .Where(s => !SelectedStudents.Contains(s))
            .Where(s => s.FirstName.ToLower().Contains(search) ||
                       s.LastName.ToLower().Contains(search))
            .OrderBy(s => s.FirstName);
    }

    private void RemoveStudent(Student student)
    {
        var updatedList = SelectedStudents.Where(s => s.Id != student.Id).ToList();
        SelectedStudentsChanged.InvokeAsync(updatedList);
    }
}
