using LiteCharms.Features.MidrandBooks.Payments;
using LiteCharms.Features.MidrandBooks.Payments.Models;

namespace MidrandBookshop.Components.Layout;

public partial class MainLayout(CartService cartService) : IDisposable
{
    [Inject]
    private AuthenticationStateProvider AuthStateProvider { get; set; } = default!;

    private Cart ShoppingCart => cartService.ShoppingCart;

    private AuthenticationState? AuthState { get; set; }
    private System.Security.Claims.ClaimsPrincipal? User { get; set; }
    private bool IsAuthenticated => User?.Identity?.IsAuthenticated ?? false;

    private string SearchInputBuffer { get; set; } = string.Empty;
    private string GlobalSearchQuery { get; set; } = string.Empty;
    private bool IsSearchActive { get; set; } = false;
    private bool IsCartOpen { get; set; } = false;

    protected override async Task OnInitializedAsync()
    {
        AuthState = await AuthStateProvider.GetAuthenticationStateAsync();
        User = AuthState!.User;

        Navigation.LocationChanged += OnLocationChanged;
        cartService.OnCartChanged += CartService_OnCartChanged;

        await cartService.LoadCartFromStorageAsync();

        SyncSearchQueryFromUrl();
    }

    private async void CartService_OnCartChanged() => await InvokeAsync(StateHasChanged);

    private void OnLocationChanged(object? sender, LocationChangedEventArgs e)
    {
        SyncSearchQueryFromUrl();
        StateHasChanged();
    }

    private void SyncSearchQueryFromUrl()
    {
        var uri = Navigation.ToAbsoluteUri(Navigation.Uri);
        var queryParameters = QueryHelpers.ParseQuery(uri.Query);

        if (queryParameters.TryGetValue("q", out var queryVal) && !string.IsNullOrWhiteSpace(queryVal))
        {
            GlobalSearchQuery = queryVal.ToString();
            SearchInputBuffer = GlobalSearchQuery;
            IsSearchActive = true;
        }
        else
        {
            GlobalSearchQuery = string.Empty;
            SearchInputBuffer = string.Empty;
            IsSearchActive = false;
        }
    }

    private void ToggleGlobalSearch()
    {
        if (!IsSearchActive)
            IsSearchActive = true;
        else
            CommitSearchNavigation();
    }

    private void HandleSearchKeyDown(KeyboardEventArgs e)
    {
        if (e.Key == "Enter") CommitSearchNavigation();
    }

    private void CommitSearchNavigation()
    {
        var uri = Navigation.ToAbsoluteUri(Navigation.Uri);
        var queryParameters = QueryHelpers.ParseQuery(uri.Query);

        var newRouteParams = new Dictionary<string, object?>();

        foreach (var param in queryParameters)
        {
            if (param.Key != "q")
            {
                newRouteParams[param.Key] = param.Value.ToString();
            }
        }

        if (!string.IsNullOrWhiteSpace(SearchInputBuffer))
            newRouteParams["q"] = SearchInputBuffer.Trim();
        else
            newRouteParams["q"] = null;

        var baseRoute = uri.AbsolutePath.StartsWith("/product/", StringComparison.OrdinalIgnoreCase) ? "/" : uri.AbsolutePath;
        var updatedUri = Navigation.GetUriWithQueryParameters(baseRoute, newRouteParams);

        Navigation.NavigateTo(updatedUri);
    }

    private void ToggleCart() => IsCartOpen = !IsCartOpen;

    private async Task ChangeQuantity(CartItem item, int delta)
    {
        var peekQuantity = item.Quantity + delta;

        if (peekQuantity < 1) return;

        cartService.UpdateQuantity(item.Price!.Id, delta);

        await cartService.SaveCartToStorageAsync();
    }

    private async Task RemoveFromCart(CartItem item)
    {
        cartService.RemoveOneItem(item.Price!.Id);

        await cartService.SaveCartToStorageAsync();
    }

    private decimal GetCartTotal() => ShoppingCart?.TotalAmount ?? 0.00m;

    private void RedirectToCart()
    {
        IsCartOpen = false;
        Navigation.NavigateTo("/cart");
    }

    private void RedirectToCheckout()
    {
        IsCartOpen = false;
        Navigation.NavigateTo("/checkout");
    }

    public void Dispose()
    {
        Navigation.LocationChanged -= OnLocationChanged;
        cartService.OnCartChanged -= CartService_OnCartChanged;

        GC.SuppressFinalize(this);
    }
}