@page "/Users"
@attribute [Authorize]
@using salesbook.Shared.Components.Layout
@using salesbook.Shared.Core.Dto
@using salesbook.Shared.Core.Interface
@using salesbook.Shared.Components.SingleElements.BottomSheet
@using salesbook.Shared.Components.Layout.Spinner
@using salesbook.Shared.Components.SingleElements
@using salesbook.Shared.Core.Entity
@using salesbook.Shared.Core.Messages.Contact
@inject IManageDataService ManageData
@inject NewContactService NewContact
@inject FilterUserDTO Filter

<HeaderLayout Title="Contatti"/>

<div class="container search-box">
    <div class="input-card clearButton">
        <MudTextField T="string?" Placeholder="Cerca..." Variant="Variant.Text" @bind-Value="TextToFilter" OnDebounceIntervalElapsed="() => FilterUsers()" DebounceInterval="500"/>

        @if (!TextToFilter.IsNullOrEmpty())
        {
            <MudIconButton Class="closeIcon" Icon="@Icons.Material.Filled.Close" OnClick="() => FilterUsers(true)"/>
        }
        
        <MudIconButton Class="rounded-button" OnClick="ToggleFilter" Icon="@Icons.Material.Rounded.FilterList" Variant="Variant.Filled" Color="Color.Primary" Size="Size.Small" />
    </div>
    
    <MudChipSet Class="mt-2" T="string" @bind-SelectedValue="TypeUser" @bind-SelectedValue:after="FilterUsers" SelectionMode="SelectionMode.SingleSelection">
        <MudChip Color="Color.Primary" Variant="Variant.Text" Value="@("all")">Tutti</MudChip>
        <MudChip Color="Color.Primary" Variant="Variant.Text" Value="@("contact")">Clienti</MudChip>
        <MudChip Color="Color.Primary" Variant="Variant.Text" Value="@("prospect")">Prospect</MudChip>
    </MudChipSet>
</div>

<div class="container users">
    @if (IsLoading)
    {
        <SpinnerLayout FullScreen="false"/>
    }
    else if (GroupedUserList?.Count > 0)
    {
        <Virtualize OverscanCount="20" Items="FilteredGroupedUserList" Context="item">
            @if (item.ShowHeader)
            {
                <div class="letter-header">@item.HeaderLetter</div>
            }
            <UserCard User="item.User"/>
        </Virtualize>
    }
    else
    {
        <NoDataAvailable Text="Nessun contatto trovato"/>
    }
</div>

<FilterUsers @bind-IsSheetVisible="OpenFilter" @bind-Filter="Filter" @bind-Filter:after="FilterUsers"/>

@code {
    private List<UserDisplayItem> GroupedUserList { get; set; } = [];
    private List<UserDisplayItem> FilteredGroupedUserList { get; set; } = [];

    private bool IsLoading { get; set; }

    //Filtri
    private string? TextToFilter { get; set; }
    private bool OpenFilter { get; set; }
    private string TypeUser { get; set; } = "all";

    protected override void OnInitialized()
    {
        NewContact.OnContactCreated += async response => await OnUserCreated(response);
        Console.WriteLine($"Filter HashCode: {Filter.GetHashCode()} - IsInitialized: {Filter.IsInitialized}");
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await LoadData();
        }
    }

    private async Task LoadData()
    {
        IsLoading = true;
        StateHasChanged();

        if (!Filter.IsInitialized)
        {
            var loggedUser = (await ManageData.GetTable<StbUser>(x => x.UserName.Equals(UserSession.User.Username))).Last();

            if (loggedUser.UserCode != null)
                Filter.Agenti = [loggedUser.UserCode];

            Filter.IsInitialized = true;
        }

        var users = await ManageData.GetContact();

        var sortedUsers = users
            .Where(u => !string.IsNullOrWhiteSpace(u.RagSoc))
            .OrderBy(u =>
            {
                var firstChar = char.ToUpper(u.RagSoc[0]);
                return char.IsLetter(firstChar) ? firstChar.ToString() : "ZZZ";
            })
            .ThenBy(u => u.RagSoc)
            .ToList();

        GroupedUserList = [];

        string? lastHeader = null;
        foreach (var user in sortedUsers)
        {
            var firstChar = char.ToUpper(user.RagSoc[0]);
            var currentLetter = char.IsLetter(firstChar) ? firstChar.ToString() : "#";

            var showHeader = currentLetter != lastHeader;
            lastHeader = currentLetter;

            GroupedUserList.Add(new UserDisplayItem
            {
                User = user,
                ShowHeader = showHeader,
                HeaderLetter = currentLetter
            });
        }

        FilterUsers();

        IsLoading = false;
        StateHasChanged();
    }


    private class UserDisplayItem
    {
        public required ContactDTO User { get; set; }
        public bool ShowHeader { get; set; }
        public string? HeaderLetter { get; set; }
    }

    private void FilterUsers() => FilterUsers(false);

    private void FilterUsers(bool clearFilter)
    {
        if (clearFilter || string.IsNullOrWhiteSpace(TextToFilter))
        {
            TextToFilter = null;
        }

        var result = new List<UserDisplayItem>();

        foreach (var item in GroupedUserList)
        {
            var user = item.User;

            switch (TypeUser)
            {
                case "contact" when !user.IsContact:
                case "prospect" when user.IsContact:
                    continue;
            }

            var matchesFilter =
                (Filter.Prov.IsNullOrEmpty() ||
                 (!string.IsNullOrEmpty(user.Prov) &&
                  user.Prov.Trim().Contains(Filter.Prov!.Trim(), StringComparison.OrdinalIgnoreCase))) &&
                (Filter.Citta.IsNullOrEmpty() ||
                 (!string.IsNullOrEmpty(user.Citta) &&
                  user.Citta.Trim().Contains(Filter.Citta!.Trim(), StringComparison.OrdinalIgnoreCase))) &&
                (Filter.Nazione.IsNullOrEmpty() ||
                 (!string.IsNullOrEmpty(user.Nazione) &&
                  user.Nazione.Trim().Contains(Filter.Nazione!.Trim(), StringComparison.OrdinalIgnoreCase))) &&
                (Filter.Indirizzo.IsNullOrEmpty() || 
                 (!string.IsNullOrEmpty(user.Indirizzo) &&
                  user.Indirizzo.Trim().Contains(Filter.Indirizzo!.Trim(), StringComparison.OrdinalIgnoreCase))) &&
                (!Filter.ConAgente || user.CodVage is not null) &&
                (!Filter.SenzaAgente || user.CodVage is null) &&
                (Filter.Agenti.IsNullOrEmpty() || (user.CodVage != null && Filter.Agenti!.Contains(user.CodVage)));

            if (!matchesFilter) continue;

            if (!string.IsNullOrWhiteSpace(TextToFilter))
            {
                var filter = TextToFilter.Trim();

                var matchesText =
                    (!string.IsNullOrEmpty(user.RagSoc) && user.RagSoc.Contains(filter, StringComparison.OrdinalIgnoreCase)) ||
                    (!string.IsNullOrEmpty(user.Indirizzo) && user.Indirizzo.Contains(filter, StringComparison.OrdinalIgnoreCase)) ||
                    (!string.IsNullOrEmpty(user.Telefono) && user.Telefono.Contains(filter, StringComparison.OrdinalIgnoreCase)) ||
                    (!string.IsNullOrEmpty(user.EMail) && user.EMail.Contains(filter, StringComparison.OrdinalIgnoreCase)) ||
                    (!string.IsNullOrEmpty(user.PartIva) && user.PartIva.Contains(filter, StringComparison.OrdinalIgnoreCase));

                if (matchesText)
                {
                    result.Add(item);
                }
            }
            else
            {
                result.Add(item);
            }
        }

        FilteredGroupedUserList = result;
    }

    private async Task OnUserCreated(CRMCreateContactResponseDTO response)
    {
        IsLoading = true;

        string codAnag;
        bool isContact;

        switch (response)
        {
            case null:
                return;
            case { AnagClie: null, PtbPros: not null }:
                await ManageData.InsertOrUpdate(response.PtbPros);
                isContact = false;
                codAnag = response.PtbPros.CodPpro!;
                break;
            case { AnagClie: not null, PtbPros: null }:
                await ManageData.InsertOrUpdate(response.AnagClie);
                isContact = true;
                codAnag = response.AnagClie.CodAnag!;
                break;
            default:
                return;
        }

        var contact = await ManageData.GetSpecificContact(codAnag, isContact);
        if (contact == null)
        {
            IsLoading = false;
            return;
        }

        var firstChar = char.ToUpper(contact.RagSoc![0]);
        var currentLetter = char.IsLetter(firstChar) ? firstChar.ToString() : "#";

        var insertIndex = -1;
        var foundHeader = false;

        for (var i = 0; i < GroupedUserList.Count; i++)
        {
            var current = GroupedUserList[i];

            if (!current.ShowHeader || current.HeaderLetter != currentLetter) continue;
            foundHeader = true;
            insertIndex = i + 1;

            while (insertIndex < GroupedUserList.Count &&
                   GroupedUserList[insertIndex].HeaderLetter == currentLetter &&
                   string.Compare(contact.RagSoc, GroupedUserList[insertIndex].User.RagSoc, StringComparison.OrdinalIgnoreCase) > 0)
            {
                insertIndex++;
            }

            break;
        }

        if (!foundHeader)
        {
            var headerItem = new UserDisplayItem
            {
                HeaderLetter = currentLetter,
                ShowHeader = true,
                User = contact
            };

            GroupedUserList.Add(headerItem);
        }
        else
        {
            var newItem = new UserDisplayItem
            {
                HeaderLetter = currentLetter,
                ShowHeader = false,
                User = contact
            };

            GroupedUserList.Insert(insertIndex, newItem);
        }

        FilterUsers();

        IsLoading = false;
    }


    private void ToggleFilter()
    {
        OpenFilter = !OpenFilter;
        StateHasChanged();
    }

}