using CMSMicroservice.Protobuf.Protos.Commission;
using Microsoft.AspNetCore.Components;
using MudBlazor;
using Google.Protobuf.WellKnownTypes;
using BackOffice.Pages.Commission.Components;
using Microsoft.JSInterop;
using System.Text;
using DateTimeConverterCL;
using GrpcWithdrawalRequestModel = CMSMicroservice.Protobuf.Protos.Commission.WithdrawalRequestModel;
using GrpcGetWithdrawalRequestsRequest = CMSMicroservice.Protobuf.Protos.Commission.GetWithdrawalRequestsRequest;

namespace BackOffice.Pages.Commission;

public partial class WithdrawalRequests
{
    [Inject] public CommissionContract.CommissionContractClient CommissionContract { get; set; }
    [Inject] public IJSRuntime JsRuntime { get; set; }

    private MudDataGrid<WithdrawalRequestModel> _gridData;
    private int? _filterStatus;
    private long? _filterUserId;
    private string? _filterIban;

    private async Task<GridData<WithdrawalRequestModel>> ServerReload(GridState<WithdrawalRequestModel> state)
    {
        try
        {
            var request = new GrpcGetWithdrawalRequestsRequest
            {
                PageIndex = state.Page + 1,
                PageSize = state.PageSize
            };

            if (_filterStatus.HasValue)
            {
                request.Status = _filterStatus.Value;
            }

            if (_filterUserId.HasValue && _filterUserId.Value > 0)
            {
                request.UserId = _filterUserId.Value;
            }

            if (!string.IsNullOrWhiteSpace(_filterIban))
            {
                request.IbanNumber = _filterIban;
            }

            var result = await CommissionContract.GetWithdrawalRequestsAsync(request);

            if (result?.Models != null && result.Models.Any())
            {
                var items = result.Models.Select(MapToViewModel).ToList();

                return new GridData<WithdrawalRequestModel>
                {
                    Items = items,
                    TotalItems = result.MetaData != null ? (int)result.MetaData.TotalCount : items.Count
                };
            }

            return new GridData<WithdrawalRequestModel>();
        }
        catch (Exception ex)
        {
            Snackbar.Add($"خطا در بارگذاری داده‌ها: {ex.Message}", Severity.Error);
            return new GridData<WithdrawalRequestModel>();
        }
    }

    private static WithdrawalRequestModel MapToViewModel(GrpcWithdrawalRequestModel grpcModel)
    {
        var requestedAt = grpcModel.RequestedAt ?? grpcModel.Created ?? new Timestamp();

        return new WithdrawalRequestModel
        {
            Id = grpcModel.Id,
            UserId = grpcModel.UserId,
            UserName = grpcModel.UserName,
            Amount = grpcModel.Amount,
            Status = grpcModel.Status,
            Method = MapMethod(grpcModel.WithdrawalMethod),
            RequestedAt = requestedAt,
            RequestDate = requestedAt.ToDateTime(),
            ProcessedDate = grpcModel.ProcessedAt?.ToDateTime(),
            AdminNote = grpcModel.Reason,
            BankReferenceId = grpcModel.BankReferenceId,
            BankTrackingCode = grpcModel.BankTrackingCode,
            PaymentFailureReason = grpcModel.PaymentFailureReason,
            IbanNumber = grpcModel.IbanNumber,
            PackageName = grpcModel.PackageName
        };
    }

    private static string MapMethod(int withdrawalMethod)
    {
        return withdrawalMethod switch
        {
            0 => "Cash",
            1 => "Diamond",
            _ => "Unknown"
        };
    }

    private async Task ApplyFilter()
    {
        if (_gridData != null)
        {
            await _gridData.ReloadServerData();
        }
    }

    private Color GetStatusColor(int status)
    {
        return status switch
        {
            0 => Color.Warning,    // Pending
            1 => Color.Info,       // Paid to wallet
            2 => Color.Warning,    // WithdrawRequested
            3 => Color.Success,    // Withdrawn
            4 => Color.Error,      // PaymentFailed
            5 => Color.Default,    // Cancelled
            _ => Color.Default
        };
    }

    private string GetStatusText(int status)
    {
        return status switch
        {
            0 => "در انتظار واریز",
            1 => "واریز شده",
            2 => "درخواست برداشت",
            3 => "برداشت شده",
            4 => "خطای پرداخت بانکی",
            5 => "لغو شده",
            _ => "نامشخص"
        };
    }

    private string GetMethodText(string method)
    {
        return method switch
        {
            "Cash" => "واریز بانکی/نقدی",
            "Diamond" => "الماس شبکه",
            _ => "نامشخص"
        };
    }

    private async Task ViewDetails(WithdrawalRequestModel request)
    {
        var parameters = new DialogParameters<WithdrawalDetailsDialog>
        {
            { x => x.Request, request },
            { x => x.StatusText, GetStatusText(request.Status) },
            { x => x.MethodText, GetMethodText(request.Method) }
        };
        var options = new DialogOptions { MaxWidth = MaxWidth.Small, FullWidth = true };
        await DialogService.ShowAsync<WithdrawalDetailsDialog>("جزئیات درخواست برداشت", parameters, options);
    }

    private async Task ApproveRequest(WithdrawalRequestModel request)
    {
        var confirmed = await DialogService.ShowMessageBox(
            "تایید درخواست",
            $"آیا از تایید درخواست برداشت {request.Amount:N0} تومان برای {request.UserName} مطمئن هستید؟",
            yesText: "تایید", cancelText: "لغو");

        if (confirmed == true)
        {
            try
            {
                var approveRequest = new ApproveWithdrawalRequest
                {
                    PayoutId = request.Id
                };

                await CommissionContract.ApproveWithdrawalAsync(approveRequest);
                Snackbar.Add("درخواست با موفقیت تایید شد", Severity.Success);
                await ApplyFilter();
            }
            catch (Exception ex)
            {
                Snackbar.Add($"خطا در تایید: {ex.Message}", Severity.Error);
            }
        }
    }

    private async Task RejectRequest(WithdrawalRequestModel request)
    {
        var parameters = new DialogParameters<RejectReasonDialog>
        {
            { x => x.UserName, request.UserName },
            { x => x.Amount, request.Amount }
        };
        var options = new DialogOptions { MaxWidth = MaxWidth.Small, FullWidth = true };
        var dialog = await DialogService.ShowAsync<RejectReasonDialog>("رد درخواست برداشت", parameters, options);
        var result = await dialog.Result;

        if (result is { Canceled: false, Data: string reason })
        {
            try
            {
                var rejectRequest = new RejectWithdrawalRequest
                {
                    PayoutId = request.Id,
                    Reason = reason
                };

                await CommissionContract.RejectWithdrawalAsync(rejectRequest);
                Snackbar.Add("درخواست رد شد", Severity.Warning);
                await ApplyFilter();
            }
            catch (Exception ex)
            {
                Snackbar.Add($"خطا در رد درخواست: {ex.Message}", Severity.Error);
            }
        }
    }

    private async Task ProcessRequest(WithdrawalRequestModel request)
    {
        var confirmed = await DialogService.ShowMessageBox(
            "پردازش پرداخت",
            $"آیا پرداخت {request.Amount:N0} تومان به {request.UserName} انجام شده است؟",
            yesText: "بله، پردازش شد", cancelText: "لغو");

        if (confirmed == true)
        {
            try
            {
                var processRequest = new ProcessWithdrawalRequest
                {
                    PayoutId = request.Id,
                    IsApproved = true
                };

                await CommissionContract.ProcessWithdrawalAsync(processRequest);
                Snackbar.Add("درخواست با موفقیت پردازش شد", Severity.Success);
                await ApplyFilter();
            }
            catch (Exception ex)
            {
                Snackbar.Add($"خطا در پردازش: {ex.Message}", Severity.Error);
            }
        }
    }

    private async Task ExportToExcel()
    {
        try
        {
            var request = new GrpcGetWithdrawalRequestsRequest
            {
                PageIndex = 1,
                PageSize = 1000
            };

            if (_filterStatus.HasValue) request.Status = _filterStatus.Value;
            if (_filterUserId.HasValue && _filterUserId.Value > 0) request.UserId = _filterUserId.Value;
            if (!string.IsNullOrWhiteSpace(_filterIban)) request.IbanNumber = _filterIban;

            var result = await CommissionContract.GetWithdrawalRequestsAsync(request);

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

            var sb = new StringBuilder();
            sb.AppendLine("شناسه,کاربر,نام کاربر,پکیج,مبلغ,وضعیت,روش,شماره شبا,تاریخ درخواست,تاریخ پردازش,شماره مرجع بانکی");

            foreach (var r in result.Models)
            {
                var mapped = MapToViewModel(r);
                sb.AppendLine(string.Join(",",
                    mapped.Id,
                    mapped.UserId,
                    EscapeCsv(mapped.UserName),
                    EscapeCsv(mapped.PackageName ?? "-"),
                    mapped.Amount,
                    EscapeCsv(GetStatusText(mapped.Status)),
                    EscapeCsv(GetMethodText(mapped.Method)),
                    EscapeCsv(mapped.IbanNumber ?? ""),
                    mapped.RequestedAt.ToDateTime().ToLocalTime().MiladiToJalaliWithTime(),
                    mapped.ProcessedDate?.MiladiToJalaliWithTime() ?? "-",
                    EscapeCsv(mapped.BankReferenceId ?? "")));
            }

            var bytes = Encoding.UTF8.GetPreamble().Concat(Encoding.UTF8.GetBytes(sb.ToString())).ToArray();
            var base64 = Convert.ToBase64String(bytes);
            var filename = $"withdrawal-requests-{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);
        }
    }

    private static string EscapeCsv(string value)
    {
        if (string.IsNullOrEmpty(value)) return "";
        if (value.Contains(',') || value.Contains('"') || value.Contains('\n'))
            return $"\"{value.Replace("\"", "\"\"")}\"";
        return value;
    }
}
