using CMSMicroservice.Protobuf.Protos.UserAddress;
using CMSMicroservice.Protobuf.Protos.UserOrder;
using FrontOffice.Main.Pages.Profile.Components;
using FrontOffice.Main.Shared;
using FrontOffice.Main.Utilities;
using Microsoft.AspNetCore.Components;
using MudBlazor;
using Messages = CMSMicroservice.Protobuf.Protos;

namespace FrontOffice.Main.Pages.Store;

public partial class CheckoutSummary : ComponentBase
{
    [Inject] private CartService Cart { get; set; } = default!;
    [Inject] private OrderService OrderService { get; set; } = default!;
    [Inject] private VATService VAT { get; set; } = default!;
    [Inject] private UserAddressContract.UserAddressContractClient UserAddressContract { get; set; } = default!;
    [Inject] private UserOrderContract.UserOrderContractClient UserOrderContract { get; set; } = default!;
    [Inject] private AuthDialogService AuthDialogService { get; set; } = default!;
    [Inject] private AuthService AuthService { get; set; } = default!;
    // Snackbar and Navigation are injected via _Imports.razor

    private List<CustomerAddressModel> _addresses = new();
    private CustomerAddressModel? _selectedAddress;
    private bool _loadingAddresses;
    private long walletBalance;

    private Messages.PaymentMethod _payment = Messages.PaymentMethod.Wallet;

    private bool CanPlaceOrder => Cart.Items.Count > 0 && _selectedAddress != null;

    protected override async Task OnInitializedAsync()
    {
        if (!await AuthService.IsAuthenticatedAsync())
        {
            await AuthDialogService.ShowAuthDialogAsync();
        }
        await Cart.EnsureInitializedAsync();
        var userInfo = await AuthService.GetUserAuthInfo();
        if (userInfo.HasAddress)
            await LoadAddresses();
        else
            _addresses = new();
        await LoadWalletBalance();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await VAT.LoadAsync();
        }
        await base.OnAfterRenderAsync(firstRender);
    }

    private async Task LoadWalletBalance()
    {
        var walletResult = await WalletService.GetBalancesAsync();
        walletBalance = walletResult.CreditBalance;
    }

    private async Task LoadAddresses()
    {
        _loadingAddresses = true;
        try
        {
            var response = await UserAddressContract.GetCustomerAddressesAsync(new());
            if (response?.Models?.Any() == true)
            {
                _addresses = response.Models.ToList();
                _selectedAddress = _addresses.FirstOrDefault(a => a.IsDefault) ?? _addresses.First();
            }
            else
            {
                _addresses = new();
                _selectedAddress = null;
            }
        }
        catch (Exception ex)
        {
            Snackbar.Add($"خطا در بارگذاری آدرس‌ها: {ex.Message}", Severity.Error);
            _addresses = new();
            _selectedAddress = null;
        }
        finally
        {
            _loadingAddresses = false;
            await InvokeAsync(StateHasChanged);
        }
    }

    private async Task OpenAddAddressDialog()
    {
        var dialog = await DialogService.ShowAsync<AddAddressDialog>("افزودن آدرس جدید");
        var result = await dialog.Result;
        if (result is { Canceled: false })
        {
            await AuthService.RefreshTokenAsync();
            await LoadAddresses();
        }
    }

    private async Task OpenEditAddressDialog(CustomerAddressModel address)
    {
        var dialog = await DialogService.ShowAsync<EditAddressDialog>("ویرایش آدرس", new DialogParameters<EditAddressDialog>
        {
            { x => x.Model, address }
        });
        var result = await dialog.Result;
        if (result is { Canceled: false })
        {
            await LoadAddresses();
        }
    }

    private async Task PlaceOrder()
    {
        if (!CanPlaceOrder || _selectedAddress is null)
        {
            Snackbar.Add("لطفاً آدرس را انتخاب کنید و سبد خرید را بررسی کنید.", Severity.Warning);
            return;
        }

        var totalRequired = VAT.AddVAT(Cart.Total);
        if (await TryHandleInsufficientBalanceAsync(totalRequired))
            return;

        try
        {
            var request = new SubmitShopBuyOrderRequest
            {
                TotalAmount = totalRequired
            };

            var response = await UserOrderContract.SubmitShopBuyOrderAsync(request);
            await Cart.Clear();
            Snackbar.Add("سفارش با موفقیت ثبت شد.", Severity.Success);
            Navigation.NavigateTo($"{RouteConstants.Store.OrderDetail}{response.Id}");
        }
        catch (Exception ex)
        {
            if (CreditChargeNavigation.IsInsufficientWalletBalance(ex))
            {
                await LoadWalletBalance();
                await TryHandleInsufficientBalanceAsync(totalRequired);
                return;
            }

            Snackbar.Add($"خطا در ثبت سفارش: {ex.Message}", Severity.Error);
        }
    }

    private async Task<bool> TryHandleInsufficientBalanceAsync(long totalRequired)
    {
        if (walletBalance >= totalRequired)
            return false;

        var shortfall = totalRequired - walletBalance;
        var allowCharge = false;
        var hasPurchasedPackage = false;
        var isMagicWallet = false;
        var magicCeilingFull = false;
        try
        {
            var userInfo = await AuthService.GetUserAuthInfo();
            allowCharge = userInfo.IsClubMemberActive;
            hasPurchasedPackage = userInfo.HasPurchasedPackage;
        }
        catch
        {
            allowCharge = false;
        }

        try
        {
            var magicStatus = await WalletService.GetMagicWalletStatusAsync();
            isMagicWallet = magicStatus.WalletMode == 1;
            magicCeilingFull = isMagicWallet && magicStatus.MagicRemainingDeposit <= 0;
        }
        catch
        {
            isMagicWallet = false;
            magicCeilingFull = false;
        }

        var parameters = new DialogParameters<InsufficientCreditDialog>
        {
            { x => x.CurrentBalance, walletBalance },
            { x => x.RequiredAmount, totalRequired },
            { x => x.ShortfallAmount, shortfall },
            { x => x.AllowChargeCredit, allowCharge },
            { x => x.HasPurchasedPackage, hasPurchasedPackage },
            { x => x.IsMagicWallet, isMagicWallet },
            { x => x.MagicCeilingFull, magicCeilingFull }
        };

        var dialog = await DialogService.ShowAsync<InsufficientCreditDialog>(
            "موجودی کافی نیست",
            parameters,
            new DialogOptions
            {
                CloseOnEscapeKey = true,
                MaxWidth = MaxWidth.Small,
                FullWidth = true
            });

        var result = await dialog.Result;
        if (allowCharge && result is { Canceled: false } && result.Data is long chargeShortfall)
        {
            var chargeAmount = CreditChargeNavigation.NormalizeChargeAmount(chargeShortfall);
            Navigation.NavigateTo(CreditChargeNavigation.BuildChargeUrl(
                chargeAmount,
                RouteConstants.Store.CheckoutSummary));
        }

        return true;
    }

    private static string FormatPrice(long price) => string.Format("{0:N0} تومان", price);

    private long CalculateVAT() => VAT.CalculateVAT(Cart.Total);

    private static string GetProductImageUrl(string? imageUrl)
        => string.IsNullOrWhiteSpace(imageUrl) ? "/images/product-placeholder.svg" : imageUrl.TrimStart('/');
}
