using CMSMicroservice.Application.Common.Authorization;
using CMSMicroservice.Protobuf.Protos.ManualPayment;
using CMSMicroservice.WebApi.Common.Services;
using CMSMicroservice.Application.ManualPaymentCQ.Commands.CreateManualPayment;
using CMSMicroservice.Application.ManualPaymentCQ.Commands.ApproveManualPayment;
using CMSMicroservice.Application.ManualPaymentCQ.Commands.RejectManualPayment;
using CMSMicroservice.Application.ManualPaymentCQ.Commands.ProcessManualMembershipPayment;
using CMSMicroservice.Application.ManualPaymentCQ.Queries.GetAllManualPayments;
using Grpc.Core;
using Mapster;
using MediatR;

namespace CMSMicroservice.WebApi.Services;

public class ManualPaymentService : ManualPaymentContract.ManualPaymentContractBase
{
    private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS;
    private readonly ISender _sender;

    public ManualPaymentService(
        IDispatchRequestToCQRS dispatchRequestToCQRS,
        ISender sender)
    {
        _dispatchRequestToCQRS = dispatchRequestToCQRS;
        _sender = sender;
    }

    [RequiresPermission(PermissionNames.ManualPaymentsCreate)]
    public override async Task<CreateManualPaymentResponse> CreateManualPayment(
        CreateManualPaymentRequest request,
        ServerCallContext context)
    {
        var command = request.Adapt<CreateManualPaymentCommand>();
        var id = await _sender.Send(command, context.CancellationToken);

        return new CreateManualPaymentResponse
        {
            Id = id
        };
    }

    [RequiresPermission(PermissionNames.ManualPaymentsApprove)]
    public override async Task<Google.Protobuf.WellKnownTypes.Empty> ApproveManualPayment(
        ApproveManualPaymentRequest request,
        ServerCallContext context)
    {
        return await _dispatchRequestToCQRS.Handle<ApproveManualPaymentRequest, ApproveManualPaymentCommand>(request, context);
    }

    [RequiresPermission(PermissionNames.ManualPaymentsApprove)]
    public override async Task<Google.Protobuf.WellKnownTypes.Empty> RejectManualPayment(
        RejectManualPaymentRequest request,
        ServerCallContext context)
    {
        return await _dispatchRequestToCQRS.Handle<RejectManualPaymentRequest, RejectManualPaymentCommand>(request, context);
    }

    [RequiresPermission(PermissionNames.ManualPaymentsView)]
    public override async Task<GetAllManualPaymentsResponse> GetAllManualPayments(
        GetAllManualPaymentsRequest request,
        ServerCallContext context)
    {
        return await _dispatchRequestToCQRS.Handle<GetAllManualPaymentsRequest, GetAllManualPaymentsQuery, GetAllManualPaymentsResponse>(request, context);
    }

    [RequiresPermission(PermissionNames.ManualPaymentsCreate)]
    public override async Task<ProcessManualMembershipPaymentResponse> ProcessManualMembershipPayment(
        ProcessManualMembershipPaymentRequest request,
        ServerCallContext context)
    {
        var command = new ProcessManualMembershipPaymentCommand
        {
            UserId = request.UserId,
            Amount = request.Amount,
            ReferenceNumber = request.ReferenceNumber,
            Description = request.Description
        };

        var result = await _sender.Send(command, context.CancellationToken);

        return new ProcessManualMembershipPaymentResponse
        {
            TransactionId = result.TransactionId,
            OrderId = result.OrderId,
            NewWalletBalance = result.NewWalletBalance,
            Message = result.Message
        };
    }
}
