using System.Text;
using BackOffice.Common.Utilities;
using CMSMicroservice.Protobuf.Protos;
using CMSMicroservice.Protobuf.Protos.UserOrder;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using MudBlazor;
using DateTimeConverterCL;
using Google.Protobuf.WellKnownTypes;
using DataModel = CMSMicroservice.Protobuf.Protos.UserOrder.GetAllUserOrderByFilterResponseModel;

namespace BackOffice.Pages.UserOrder;

public partial class OrderSalesReports
{
    [Inject] public UserOrderContract.UserOrderContractClient UserOrderContract { get; set; } = default!;
    [Inject] public IJSRuntime JsRuntime { get; set; } = default!;

    protected readonly List<DataModel> _orders = new();
    protected bool _loading;

    protected DateTime? _fromDate = DateTime.Today.AddDays(-30);
    protected DateTime? _toDate = DateTime.Today;
    protected int? _deliveryStatusFilter;
    protected int? _paymentStatusFilter;

    protected int _totalOrders;
    protected long _totalSales;
    protected long _averageOrder;
    protected int _paidCount;

    protected string[] _salesLabels = Array.Empty<string>();
    protected List<ChartSeries> _salesSeries = new();

    protected string[] _statusChartLabels = Array.Empty<string>();
    protected List<ChartSeries> _statusChartSeries = new();

    protected string[] _topProductLabels = Array.Empty<string>();
    protected List<ChartSeries> _topProductSeries = new();

    protected override async Task OnInitializedAsync()
    {
        await LoadReports();
    }

    protected async Task LoadReports()
    {
        if (_fromDate.HasValue && _toDate.HasValue && _fromDate.Value.Date > _toDate.Value.Date)
        {
            Snackbar.Add("تاریخ شروع نباید بعد از تاریخ پایان باشد.", Severity.Warning);
            return;
        }

        _loading = true;
        _orders.Clear();

        try
        {
            var request = new GetAllUserOrderByFilterRequest
            {
                Filter = new GetAllUserOrderByFilterFilter(),
                PaginationState = new PaginationState
                {
                    PageNumber = 1,
                    PageSize = 200
                }
            };

            if (_fromDate.HasValue)
            {
                request.Filter.PaymentDate =
                    Timestamp.FromDateTime(DateTime.SpecifyKind(_fromDate.Value.Date, DateTimeKind.Utc));
            }

            if (_deliveryStatusFilter.HasValue)
            {
                request.Filter.DeliveryStatus = (DeliveryStatus)_deliveryStatusFilter.Value;
            }
            else
            {
                request.Filter.ClearDeliveryStatusItem();
            }

            if (_paymentStatusFilter.HasValue)
            {
                request.Filter.PaymentStatus = (PaymentStatus)_paymentStatusFilter.Value;
            }
            else
            {
                request.Filter.ClearPaymentStatusItem();
            }

            var result = await UserOrderContract.GetAllUserOrderByFilterAsync(request);

            if (result?.Models != null)
            {
                var items = result.Models.ToList();

                // Client-side date filtering for "toDate"
                if (_toDate.HasValue)
                {
                    items = items.Where(o =>
                        o.PaymentDate == null ||
                        o.PaymentDate.ToDateTime() <= _toDate.Value.Date.AddDays(1)).ToList();
                }

                _orders.AddRange(items);
            }

            BuildSummary();
            BuildSalesChart();
            BuildStatusChart();
            await BuildTopProductsChart();
        }
        catch (Exception ex)
        {
            Snackbar.Add($"خطا در بارگذاری گزارش فروش: {ex.Message}", Severity.Error);
            ClearData();
        }
        finally
        {
            _loading = false;
        }
    }

    private void ClearData()
    {
        _orders.Clear();
        _totalOrders = 0;
        _totalSales = 0;
        _averageOrder = 0;
        _paidCount = 0;
        _salesLabels = Array.Empty<string>();
        _salesSeries = new List<ChartSeries>();
        _statusChartLabels = Array.Empty<string>();
        _statusChartSeries = new List<ChartSeries>();
        _topProductLabels = Array.Empty<string>();
        _topProductSeries = new List<ChartSeries>();
    }

    private void BuildSummary()
    {
        _totalOrders = _orders.Count;
        _totalSales = _orders.Sum(o => o.Amount);
        _averageOrder = _totalOrders > 0 ? _totalSales / _totalOrders : 0;
        _paidCount = _orders.Count(o => o.PaymentStatus == PaymentStatus.Success);
    }

    private void BuildSalesChart()
    {
        if (_orders.Count == 0)
        {
            _salesLabels = Array.Empty<string>();
            _salesSeries = new List<ChartSeries>();
            return;
        }

        var grouped = _orders
            .Where(o => o.PaymentDate != null)
            .GroupBy(o => o.PaymentDate!.ToDateTime().Date)
            .OrderBy(g => g.Key)
            .ToList();

        _salesLabels = grouped
            .Select(g => g.Key.MiladiToJalali())
            .ToArray();

        var amountSeries = grouped
            .Select(g => (double)g.Sum(o => o.Amount))
            .ToArray();

        var countSeries = grouped
            .Select(g => (double)g.Count())
            .ToArray();

        _salesSeries = new List<ChartSeries>
        {
            new ChartSeries { Name = "مبلغ فروش", Data = amountSeries },
            new ChartSeries { Name = "تعداد سفارش", Data = countSeries }
        };
    }

    private void BuildStatusChart()
    {
        if (_orders.Count == 0)
        {
            _statusChartLabels = Array.Empty<string>();
            _statusChartSeries = new List<ChartSeries>();
            return;
        }

        var groups = _orders
            .GroupBy(x => x.DeliveryStatus.GetHashCode())
            .OrderBy(g => g.Key)
            .ToList();

        _statusChartLabels = groups
            .Select(g => GetDeliveryStatusText(g.Key))
            .ToArray();

        _statusChartSeries = new List<ChartSeries>
        {
            new ChartSeries
            {
                Name = "تعداد سفارش‌ها",
                Data = groups.Select(g => (double)g.Count()).ToArray()
            }
        };
    }

    protected Color GetDeliveryStatusColor(int status)
    {
        return status switch
        {
            1 => Color.Warning,
            2 => Color.Info,
            3 => Color.Success,
            4 => Color.Error,
            5 => Color.Dark,
            6 => Color.Primary,
            _ => Color.Default
        };
    }

    protected string GetDeliveryStatusText(int status)
    {
        return status switch
        {
            1 => "در انتظار ارسال",
            2 => "تحویل پست",
            3 => "تحویل به مشتری",
            4 => "مرجوع شده",
            5 => "لغو شده",
            6 => "آماده تحویل در دفتر",
            _ => "بدون ارسال / نامشخص"
        };
    }

    protected async Task ExportToExcel()
    {
        if (_orders.Count == 0)
        {
            Snackbar.Add("داده‌ای برای خروجی وجود ندارد.", Severity.Info);
            return;
        }

        var headers = new[]
        {
            "شناسه", "کاربر", "نام مشتری", "مبلغ", "وضعیت پرداخت", "وضعیت ارسال", "تاریخ پرداخت"
        };

        var rows = _orders.Select(o => new object?[]
        {
            o.Id,
            o.UserId,
            CsvExportHelper.CustomerName(o.UserFullName, userId: o.UserId),
            o.Amount,
            o.PaymentStatus == PaymentStatus.Success ? "پرداخت شده" : "پرداخت نشده",
            GetDeliveryStatusText(o.DeliveryStatus.GetHashCode()),
            o.PaymentDate != null ? o.PaymentDate.ToDateTime().MiladiToJalaliWithTime() : "-"
        });

        var filename = $"store-sales-{DateTime.Now:yyyyMMddHHmmss}.xls";
        await JsRuntime.InvokeVoidAsync("jsSaveAsFile", filename,
            CsvExportHelper.ToExcelXmlBase64("گزارش فروش", headers, rows));
        Snackbar.Add("خروجی Excel آماده شد.", Severity.Success);
    }

    protected async Task ExportToPdf()
    {
        if (_orders.Count == 0)
        {
            Snackbar.Add("داده‌ای برای خروجی وجود ندارد.", Severity.Info);
            return;
        }

        var sb = new StringBuilder();
        sb.AppendLine("گزارش فروش فروشگاه");
        sb.AppendLine($"بازه: از {_fromDate?.MiladiToJalali() ?? "-"} تا {_toDate?.MiladiToJalali() ?? "-"}");
        sb.AppendLine();

        sb.AppendLine("خلاصه:");
        sb.AppendLine($"تعداد سفارش‌ها: {_totalOrders}");
        sb.AppendLine($"مجموع فروش: {_totalSales:N0} تومان");
        sb.AppendLine($"میانگین مبلغ سفارش: {_averageOrder:N0} تومان");
        sb.AppendLine($"پرداخت شده: {_paidCount}");
        sb.AppendLine();

        sb.AppendLine("جزئیات سفارش‌ها:");
        sb.AppendLine("شناسه | کاربر | مبلغ | وضعیت پرداخت | وضعیت ارسال | تاریخ");

        foreach (var o in _orders)
        {
            sb.AppendLine(
                $"{o.Id} | {CsvExportHelper.CustomerName(o.UserFullName, userId: o.UserId)} | {o.Amount:N0} | {(o.PaymentStatus == PaymentStatus.Success ? "پرداخت شده" : "پرداخت نشده")} | {GetDeliveryStatusText(o.DeliveryStatus.GetHashCode())} | {(o.PaymentDate != null ? o.PaymentDate.ToDateTime().MiladiToJalaliWithTime() : "-")}");
        }

        var bytes = Encoding.UTF8.GetPreamble().Concat(Encoding.UTF8.GetBytes(sb.ToString())).ToArray();
        var base64 = Convert.ToBase64String(bytes);
        var filename = $"store-sales-{DateTime.Now:yyyyMMddHHmmss}.txt";

        await JsRuntime.InvokeVoidAsync("jsSaveAsFile", filename, base64);
        Snackbar.Add("خروجی PDF (نسخه متنی) آماده شد.", Severity.Success);
    }

    private async Task BuildTopProductsChart()
    {
        _topProductLabels = Array.Empty<string>();
        _topProductSeries = new List<ChartSeries>();

        if (_orders.Count == 0)
            return;

        // استفاده از factor_details که در هر سفارش موجود هست
        var productTotals = new Dictionary<long, (string Name, long Amount)>();

        foreach (var order in _orders.Take(100))
        {
            if (order.FactorDetails == null)
                continue;

            foreach (var item in order.FactorDetails)
            {
                var amount = (item.UnitPrice ?? 0) * (item.Count ?? 1);
                if (!productTotals.TryGetValue(item.ProductId, out var existing))
                {
                    productTotals[item.ProductId] = (item.ProductTitle, amount);
                }
                else
                {
                    productTotals[item.ProductId] = (existing.Name, existing.Amount + amount);
                }
            }
        }

        if (productTotals.Count == 0)
            return;

        var top = productTotals.Values
            .OrderByDescending(x => x.Amount)
            .Take(5)
            .ToList();

        _topProductLabels = top.Select(x => x.Name).ToArray();
        _topProductSeries = new List<ChartSeries>
        {
            new ChartSeries
            {
                Name = "مبلغ فروش",
                Data = top.Select(x => (double)x.Amount).ToArray()
            }
        };
    }
}
