using Hcs.Client.Api.Payload.Payments;
using Hcs.Client.Api.Request.Exception;
using Hcs.Client.Internal;
using Hcs.Service.Async.Payments;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Hcs.Client.Api.Request.Payments
{
    internal class ImportSupplierNotificationsOfOrderExecutionRequest(ClientBase client) : PaymentsRequestBase(client)
    {
        protected override bool CanBeRestarted => false;

        internal async Task<bool> ExecuteAsync(ImportSupplierNotificationsOfOrderExecutionPayload payload, CancellationToken token)
        {
            ThrowIfPayloadIncorrect(payload);

            // http://open-gkh.ru/Payment/importSupplierNotificationsOfOrderExecutionRequest.html
            var request = new importSupplierNotificationsOfOrderExecutionRequest
            {
                Id = Constants.SIGNED_XML_ELEMENT_ID,
                version = "10.0.1.1",
                SupplierNotificationOfOrderExecution = [GetNotificationFromPayload(payload)]
            };

            var result = await SendAndWaitResultAsync(request, async asyncClient =>
            {
                var response = await asyncClient.importSupplierNotificationsOfOrderExecutionAsync(CreateRequestHeader(), request);
                return response.AckRequest.Ack;
            }, token);

            result.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
            {
                throw RemoteException.CreateNew(error.ErrorCode, error.Description);
            });

            result.Items.OfType<CommonResultType>().ToList().ForEach(commonResult =>
            {
                commonResult.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
                {
                    throw RemoteException.CreateNew(error.ErrorCode, error.Description);
                });
            });

            return true;
        }

        private void ThrowIfPayloadIncorrect(ImportSupplierNotificationsOfOrderExecutionPayload payload)
        {
            if (payload.month.HasValue && !payload.year.HasValue)
            {
                throw new ArgumentException($"{nameof(payload.month)} has value but {nameof(payload.year)} has not");
            }

            if (!payload.month.HasValue && payload.year.HasValue)
            {
                throw new ArgumentException($"{nameof(payload.year)} has value but {nameof(payload.month)} has not");
            }

            if (string.IsNullOrEmpty(payload.paymentDocumentId))
            {
                throw new ArgumentException($"{nameof(payload.paymentDocumentId)} is empty");
            }
        }

        private importSupplierNotificationsOfOrderExecutionRequestSupplierNotificationOfOrderExecution GetNotificationFromPayload(ImportSupplierNotificationsOfOrderExecutionPayload payload)
        {
            var notification = new importSupplierNotificationsOfOrderExecutionRequestSupplierNotificationOfOrderExecution()
            {
                TransportGUID = Guid.NewGuid().ToString(),
                OrderDate = payload.orderDate,
                Item = payload.paymentDocumentId,
                ItemElementName = ItemChoiceType1.PaymentDocumentID,
                Amount = payload.amount
            };

            if (payload.month.HasValue)
            {
                notification.OrderPeriod = new SupplierNotificationOfOrderExecutionTypeOrderPeriod()
                {
                    Month = payload.month.Value,
                    Year = payload.year.Value
                };
            }

            if (payload.onlinePayment.HasValue && payload.onlinePayment.Value)
            {
                notification.OnlinePayment = true;
                notification.OnlinePaymentSpecified = true;
            }

            return notification;
        }
    }
}
