// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PurchaseOrderService.svc.cs" company="BEL USA">
//   This product is property of BEL USA.
// </copyright>
// <summary>
//   Defines the PurchaseOrderService type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace bel.promostandards.wcf.api.Services
{
    using bel.promostandards.api.domain.Invoice;
    using bel.promostandards.business.Exceptions;
    using bel.promostandards.data.domain.Entities.Security;
    using bel.promostandards.interfaces.Services;
    using bel.promostandards.wcf.api.Helpers;
    using NLog;
    using System.ServiceModel;
    using System.ServiceModel.Activation;
    using System.ServiceModel.Channels;
    using System.Threading.Tasks;

    /// <summary>
    /// The order status service.
    /// </summary>
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class InvoiceService : IInvoiceService
    {
        /// <summary>
        /// The order status service.
        /// </summary>
        private readonly IInvoicesService invoiceService;


        /// <summary>
        /// The logger.
        /// </summary>
        private readonly Logger logger = LogManager.GetLogger("Invoice_Service");


        public InvoiceService(IInvoicesService _invoiceService)
        {
            invoiceService = _invoiceService;
        }

        public async Task<GetInvoiceResponse> GetInvoicesAsync(GetInvoicesRequest request)
        {
            GetInvoiceResponse response = new GetInvoiceResponse();
            string address = OperationContext.Current
                .IncomingMessageProperties[RemoteEndpointMessageProperty.Name] is RemoteEndpointMessageProperty msg ? msg.Address : "0.0.0.0";

            try
            {
                PreCheckInvoiceContent(request);
                Credentials credentials = new Credentials { CustomerId = request.Id, Password = request.Password };
                Invoice[] result = await invoiceService.GetInvoice(credentials, request.QueryType, request.ReferenceNumber, request.RequestedDate, request.AvailableTimeStamp);
                response.InvoiceArray = result;
            }
            catch (CredentialsException credentialsException)
            {
                logger.Error($"GetInvoiceError: Id: {request.Id} Error Code: {credentialsException.Code} Error message: {credentialsException.Message}");
                response.ServiceMessageArray = new ServiceMessage[]
                {
                    new ServiceMessage
                    {
                        Code = (int)credentialsException.Code,
                        Description = credentialsException.CustomMessage.Truncate(256),
                        Severity = SeverityTypeEnum.Error
                    }
                };
            }
            catch (GeneralException exception)
            {
                response.ServiceMessageArray = new ServiceMessage[]
                {
                    new ServiceMessage {
                        Code = exception.Code,
                        Description = exception.Message.Truncate(256),
                        Severity = SeverityTypeEnum.Error
                    }
                };
                logger.Error($"GetInvoiceError: Id: {request.Id} Error Code: {exception.Code} Error message: {exception.Message}");
            }

            return response;
        }

        public async Task<GetVoidedInvoiceResponse> GetVoidedInvoicesAsync(GetVoidedInvoicesRequest request)
        {
            GetVoidedInvoiceResponse response = new GetVoidedInvoiceResponse();
            string address = OperationContext.Current
                .IncomingMessageProperties[RemoteEndpointMessageProperty.Name] is RemoteEndpointMessageProperty msg ? msg.Address : "0.0.0.0";

            try
            {
                PreCheckVoidedInvoiceContent(request);
                Credentials credentials = new Credentials { CustomerId = request.Id, Password = request.Password };
                VoidedInvoice[] result = await invoiceService.GetVoidedInvoice(credentials, request.QueryType, request.ReferenceNumber, request.RequestedDate, request.AvailableTimeStamp);
                response.VoidedInvoiceArray = result;
            }
            catch (CredentialsException credentialsException)
            {
                logger.Error($"GetVoidedInvoiceError: Id: {request.Id} Error Code: {credentialsException.Code} Error message: {credentialsException.Message}");
                response.ServiceMessageArray = new ServiceMessage[]
                {
                    new ServiceMessage
                    {
                        Code = (int)credentialsException.Code,
                        Description = credentialsException.CustomMessage.Truncate(256),
                        Severity = SeverityTypeEnum.Error
                    }
                };
            }
            catch (GeneralException exception)
            {
                response.ServiceMessageArray = new ServiceMessage[]
                {
                    new ServiceMessage {
                        Code = exception.Code,
                        Description = exception.Message.Truncate(256),
                        Severity = SeverityTypeEnum.Error
                    }
                };
                logger.Error($"GetVoidedInvoiceError: Id: {request.Id} Error Code: {exception.Code} Error message: {exception.Message}");
            }

            return response;
        }

        #region Precheck...

        private void PreCheckInvoiceContent(GetInvoicesRequest request)
        {
            if (string.IsNullOrWhiteSpace(request.WsVersion) || request.WsVersion != "1.0.0")
            {
                throw new GeneralException(115, "wsVersion not found");
            }

            if (string.IsNullOrWhiteSpace(request.Id))
            {
                throw new GeneralException(120, "The following field(s) are required [Id]");
            }

            if (request.QueryType < 1 || request.QueryType > 4)
            {
                throw new GeneralException(902, "queryType not supported");
            }

            if (request.QueryType != 1 && request.QueryType != 2 && request.QueryType != 3 && request.QueryType != 4)
            {
                throw new GeneralException(901, "queryType not found");
            }

            if (((int)request.QueryType == 1 || (int)request.QueryType == 2) && string.IsNullOrWhiteSpace(request.ReferenceNumber))
            {
                throw new GeneralException(120, "The following field(s) are required [ReferenceNumber]");
            }

            if (((int)request.QueryType == 3) && request.RequestedDate == null)
            {
                throw new GeneralException(120, "The following field(s) are required [RequestedDate]");
            }

            if (((int)request.QueryType == 4) && request.AvailableTimeStamp == null)
            {
                throw new GeneralException(120, "The following field(s) are required [AvailableTimeStamp]");
            }
        }

        private void PreCheckVoidedInvoiceContent(GetVoidedInvoicesRequest request)
        {
            if (string.IsNullOrWhiteSpace(request.WsVersion) || request.WsVersion != "1.0.0")
            {
                throw new GeneralException(115, "wsVersion not found");
            }

            if (string.IsNullOrWhiteSpace(request.Id))
            {
                throw new GeneralException(120, "The following field(s) are required [Id]");
            }

            if (request.QueryType < 1 || request.QueryType > 4)
            {
                throw new GeneralException(902, "queryType not supported");
            }

            if (request.QueryType != 1 && request.QueryType != 2 && request.QueryType != 3 && request.QueryType != 4)
            {
                throw new GeneralException(901, "queryType not found");
            }

            if (((int)request.QueryType == 1 || (int)request.QueryType == 2) && string.IsNullOrWhiteSpace(request.ReferenceNumber))
            {
                throw new GeneralException(120, "The following field(s) are required [ReferenceNumber]");
            }

            if (((int)request.QueryType == 3) && request.RequestedDate == null)
            {
                throw new GeneralException(120, "The following field(s) are required [RequestedDate]");
            }

            if (((int)request.QueryType == 4) && request.AvailableTimeStamp == null)
            {
                throw new GeneralException(120, "The following field(s) are required [AvailableTimeStamp]");
            }
        }

        #endregion
    }
}
