using Grand.Business.Core.Commands.Checkout.Orders;
using Grand.Business.Core.Events.Checkout.Orders;
using Grand.Business.Core.Interfaces.Common.Pdf;
using Grand.Business.Core.Interfaces.Customers;
using Grand.Business.Core.Interfaces.Messages;
using Grand.Business.Core.Queries.Checkout.Orders;
using Grand.Domain.Localization;
using Grand.Domain.Orders;
using MediatR;

namespace Grand.Business.Checkout.Commands.Handlers.Orders;

public class ProcessOrderPaidCommandHandler : IRequestHandler<ProcessOrderPaidCommand, bool>
{
    private readonly ICustomerService _customerService;
    private readonly LanguageSettings _languageSettings;
    private readonly IMediator _mediator;
    private readonly IMessageProviderService _messageProviderService;
    private readonly OrderSettings _orderSettings;
    private readonly IPdfService _pdfService;

    public ProcessOrderPaidCommandHandler(
        IMessageProviderService messageProviderService,
        ICustomerService customerService,
        IMediator mediator,
        IPdfService pdfService,
        OrderSettings orderSettings,
        LanguageSettings languageSettings)
    {
        _messageProviderService = messageProviderService;
        _customerService = customerService;
        _mediator = mediator;
        _pdfService = pdfService;
        _orderSettings = orderSettings;
        _languageSettings = languageSettings;
    }

    public async Task<bool> Handle(ProcessOrderPaidCommand request, CancellationToken cancellationToken)
    {
        await ProcessOrderPaid(request.Order);
        return true;
    }

    /// <summary>
    ///     Process order paid status
    /// </summary>
    /// <param name="order">Order</param>
    protected virtual async Task ProcessOrderPaid(Order order)
    {
        if (order == null)
            throw new ArgumentNullException(nameof(order));

        //raise event
        await _mediator.Publish(new OrderPaidEvent(order));

        //order paid email notification
        if (order.OrderTotal != 0)
        {
            var customer = await _customerService.GetCustomerById(order.CustomerId);

            var orderPaidAttachmentFilePath =
                _orderSettings.AttachPdfInvoiceToOrderPaidEmail && !_orderSettings.AttachPdfInvoiceToBinary
                    ? await _pdfService.PrintOrderToPdf(order, "")
                    : null;
            var orderPaidAttachmentFileName =
                _orderSettings.AttachPdfInvoiceToOrderPaidEmail && !_orderSettings.AttachPdfInvoiceToBinary
                    ? "order.pdf"
                    : null;

            var orderPaidAttachments =
                _orderSettings.AttachPdfInvoiceToOrderPaidEmail && _orderSettings.AttachPdfInvoiceToBinary
                    ? [
                        await _pdfService.SaveOrderToBinary(order, "")
                    ]
                    : new List<string>();

            await _messageProviderService.SendOrderPaidCustomerMessage(order, customer, order.CustomerLanguageId,
                orderPaidAttachmentFilePath, orderPaidAttachmentFileName, orderPaidAttachments);

            await _messageProviderService.SendOrderPaidStoreOwnerMessage(order, customer,
                _languageSettings.DefaultAdminLanguageId);
            if (order.OrderItems.Any(x => !string.IsNullOrEmpty(x.VendorId)))
            {
                var vendors = await _mediator.Send(new GetVendorsInOrderQuery { Order = order });
                foreach (var vendor in vendors)
                    await _messageProviderService.SendOrderPaidVendorMessage(order, vendor,
                        _languageSettings.DefaultAdminLanguageId);
            }
        }
    }
}