using CMSMicroservice.Protobuf.Protos.Products;
using CMSMicroservice.Protobuf.Protos;
using BackOffice.Common.BaseComponents;
using BackOffice.Common.Utilities;
using BackOffice.Pages.Tag.Components;
using BackOffice.Pages.Products.Components;
using Mapster;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using MudBlazor;
using System.Text;
using DataModel = CMSMicroservice.Protobuf.Protos.Products.GetAllProductsByFilterResponseModel;

namespace BackOffice.Pages.Products;

public partial class ProductsMainPage
{
    [Inject] public ProductsContract.ProductsContractClient ProductsContract { get; set; } = default!;
    [Inject] public IJSRuntime JsRuntime { get; set; } = default!;

    private bool _isLoading = true;
    private MudDataGrid<DataModel> _gridData;
    private BasePageComponent _basePage;
    private GetAllProductsByFilterRequest _request = new() { Filter = new() };
    private readonly HashSet<long> _selectedProductIds = new();

    private async Task<GridData<DataModel>> ServerReload(GridState<DataModel> state)
    {
        _selectedProductIds.Clear();

        _request.Filter ??= new();
        _request.PaginationState ??= new();
        _request.PaginationState.PageNumber = state.Page + 1;
        _request.PaginationState.PageSize = state.PageSize;

        var result = await ProductsContract.GetAllProductsByFilterAsync(_request);
        if (result != null && result.Models != null && result.Models.Any())
        {
            return new GridData<DataModel> { Items = result.Models.ToList(), TotalItems = (int)result.MetaData.TotalCount };
        }

        return new GridData<DataModel>();
    }

    private void ToggleSelection(long id, bool isSelected)
    {
        if (isSelected)
        {
            _selectedProductIds.Add(id);
        }
        else
        {
            _selectedProductIds.Remove(id);
        }
    }

    private async Task BulkDelete()
    {
        if (_selectedProductIds.Count == 0)
            return;

        var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Small };
        bool? result = await DialogService.ShowMessageBox(
            "اخطار",
            $"آیا از حذف { _selectedProductIds.Count } محصول انتخاب‌شده مطمئن هستید؟",
            yesText: "حذف", cancelText: "لغو",
            options: options);

        if (result == true)
        {
            foreach (var id in _selectedProductIds.ToList())
            {
                await ProductsContract.DeleteProductsAsync(new DeleteProductsRequest { Id = id });
            }

            _selectedProductIds.Clear();
            ReLoadData();
            Snackbar.Add("محصولات انتخاب‌شده حذف شدند", Severity.Success);
        }
    }

    private async Task BulkToggleStatus(bool enable)
    {
        if (_selectedProductIds.Count == 0)
            return;

        var actionTitle = enable ? "فعال‌سازی" : "غیرفعال‌سازی";
        var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Small };
        bool? result = await DialogService.ShowMessageBox(
            actionTitle,
            $"آیا از {actionTitle} { _selectedProductIds.Count } محصول انتخاب‌شده مطمئن هستید؟",
            yesText: actionTitle, cancelText: "لغو",
            options: options);

        if (result == true)
        {
            var request = new ToggleProductStatusRequest
            {
                Enable = enable,
                DefaultStock = 0
            };
            request.ProductIds.AddRange(_selectedProductIds);

            var response = await ProductsContract.ToggleProductStatusAsync(request);

            Snackbar.Add(
                $"عملیات {actionTitle} انجام شد. موفق: {response.Succeeded} / ناموفق: {response.Failed}",
                response.Failed > 0 ? Severity.Warning : Severity.Success);

            _selectedProductIds.Clear();
            ReLoadData();
        }
    }

    private async Task ExportToExcel()
    {
        try
        {
            var exportRequest = new GetAllProductsByFilterRequest
            {
                Filter = _request.Filter ?? new GetAllProductsByFilterFilter(),
                PaginationState = new PaginationState
                {
                    PageNumber = 1,
                    PageSize = 1000
                }
            };

            var result = await ProductsContract.GetAllProductsByFilterAsync(exportRequest);

            if (result?.Models == null || !result.Models.Any())
            {
                Snackbar.Add("داده‌ای برای خروجی وجود ندارد.", Severity.Info);
                return;
            }

            var sb = new StringBuilder();
            sb.AppendLine("Id,Title,Price,Discount,RemainingCount,SaleCount,ViewCount");

            foreach (var p in result.Models)
            {
                sb.AppendLine(string.Join(",",
                    p.Id,
                    EscapeCsv(p.Title),
                    p.Price,
                    p.Discount,
                    p.RemainingCount,
                    p.SaleCount,
                    p.ViewCount));
            }

            var bytes = Encoding.UTF8.GetBytes(sb.ToString());
            var base64 = Convert.ToBase64String(bytes);
            var filename = $"products-{DateTime.Now:yyyyMMddHHmmss}.csv";

            await JsRuntime.InvokeVoidAsync("jsSaveAsFile", filename, base64);
            Snackbar.Add("خروجی Excel (CSV) آماده شد.", Severity.Success);
        }
        catch (Exception ex)
        {
            Snackbar.Add($"خطا در خروجی Excel: {ex.Message}", Severity.Error);
        }
    }

    public async Task Update(DataModel model)
    {
        var parameters = new DialogParameters<UpdateDialog> { { x => x.Model, model.Adapt<UpdateProductsRequest>() } };

        var dialog = await DialogService.ShowAsync<UpdateDialog>("ویرایش محصول", parameters, new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Small });
        var result = await dialog.Result;

        if (!result.Canceled)
        {
            ReLoadData();
            Snackbar.Add("عملیات با موفقیت انجام شد", Severity.Success);
        }
    }

    private async Task OnDelete(DataModel model)
    {
        var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Small };
        bool? result = await DialogService.ShowMessageBox(
            "اخطار",
            $"آیا از حذف محصول «{model.Title}» مطمئن هستید؟",
            yesText: "حذف", cancelText: "لغو",
            options: options);
        if (result == true)
        {
            await ProductsContract.DeleteProductsAsync(new DeleteProductsRequest { Id = model.Id });
            ReLoadData();
        }
        StateHasChanged();
    }

    public async void ReLoadData()
    {
        if (_gridData != null)
            await _gridData.ReloadServerData();
    }

    public async Task CreateNew()
    {
        var dialog = await DialogService.ShowAsync<CreateDialog>("افزودن محصول", new DialogParameters<CreateDialog> { { x => x.Model, new CreateNewProductsRequest() } }, new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Small });
        var result = await dialog.Result;
        if (!result.Canceled)
        {
            ReLoadData();
            Snackbar.Add("عملیات با موفقیت انجام شد", Severity.Success);
        }
    }

    public async Task OnFilterSubmit()
    {
        _basePage.IsFiltered = true;
        StateHasChanged();
        ReLoadData();
    }

    public async Task OnFilterCleared()
    {
        _basePage.IsFiltered = false;
        StateHasChanged();
        _request = new GetAllProductsByFilterRequest { Filter = new() };
        ReLoadData();
    }

    // TODO: Enable when GalleryDialog is working (needs AddProductImageAsync/RemoveProductImageAsync in proto)
    public async Task OpenGallery(DataModel model)
    {
        var parameters = new DialogParameters<GalleryDialog>
        {
            { x => x.ProductId, model.Id },
            { x => x.ProductTitle, model.Title }
        };
        await DialogService.ShowAsync<GalleryDialog>("گالری تصاویر", parameters,
            new DialogOptions { CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.Medium });
    }

    public void OpenCategoryMapping(DataModel model)
    {
        Navigation.NavigateTo($"{RouteConstance.ProductCategories}{model.Id}");
    }

    public async Task OpenTagAssignment(DataModel model)
    {
        var parameters = new DialogParameters<AssignTagsDialog>
        {
            { x => x.ProductId, model.Id },
            { x => x.ProductTitle, model.Title }
        };

        await DialogService.ShowAsync<AssignTagsDialog>("مدیریت تگ‌های محصول", parameters,
            new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small, FullWidth = true });
    }

    public async Task OpenImagePreview(string imagePath, string title)
    {
        if (string.IsNullOrWhiteSpace(imagePath))
            return;

        var parameters = new DialogParameters<ImagePreviewDialog>
        {
            { x => x.ImageUrl, imagePath },
            { x => x.Title, title }
        };

        await DialogService.ShowAsync<ImagePreviewDialog>("پیش‌نمایش تصویر محصول", parameters,
            new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Medium, FullWidth = true });
    }

    public void OpenBulkEdit()
    {
        Navigation.NavigateTo(RouteConstance.ProductsBulkEdit);
    }

    private static string EscapeCsv(string value)
    {
        if (string.IsNullOrEmpty(value))
            return "";

        var needsQuotes = value.Contains(',') || value.Contains('"') || value.Contains('\n');
        var escaped = value.Replace("\"", "\"\"");
        return needsQuotes ? $"\"{escaped}\"" : escaped;
    }
}
