using EvaPOS_API_FRAME.DTO.Intercambio;
using EvaPOS_API_FRAME.DTO;
using EvaPOS_API_FRAME.RespuestasXML;
using EvaPosSrvDTO;
using EvaPosSrvResp;
using Serilog;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SCOGateway.POSGk;
using RestSharp;
using gatewayGK.POSGk;
using System.Text.Json;
using Newtonsoft.Json.Linq;
using System.Transactions;
using GatewaySCO;

namespace gatewayGK.ComandosGk
{
    ///<summary>
    /// Procesa solicitudes del primer item agregado.
    /// </summary>
    // TODO - unificar uso de libreria json: using System.Text.Json OR using Newtonsoft.Json.Linq;
    //
    public class AddItemRequestCmdGk : IComando
    {
        public string Referencia { get; set; } = "scsns:AddItem";
        /// <summary>
        /// DTO con solicitud.
        /// </summary>
        public AddItemRequestDTO Request { get; private set; }

        /// <summary>
        /// Procesa y responde ReportStatusEventsRequest.
        /// </summary>
        /// 
        public const string UrlRegisterItem = ConstantesGK.UrlBaseMaquetaProd + "/com.gk_software.pos.api.service.transaction.LineItemService/registerLineItem";

        /// <summary>
        /// Procesa y responde el login.
        /// </summary>
        public Respuestas Ejecutar()
        {
            Log.Debug("Cmd AddItemRequestDTO ejecutado. AddItemRequest : {AddItemRequest}", Request.RequestID);
            //int requestIdGuardado = RequestIdGuardado();
            POSBCStatusEvent posbcStatus = null;
            TransactionStatusEvent transactionStatusEvent = null;
            POSReceiptEventHeaderResponse posReceiptEventHeader = null;
            POSReceiptEvent pOSReceiptEvent = null;
            TotalsEventResponse totalEvent = null;
            AddItemResponse itemResponse = null;
            //Variables para manejar las respuestas de error - (item con peso, no se encuentra el item,item requiere cantidad)
            AddItemResponseError addItemResponseError = null;
            Respuestas respuesta = null;
            Venta venta = null;
            //Variables del adaptador de entrada - addItem
            int requestId = Request.RequestID;
            long barCode = 0;
            int quantity = Request.ItemIdentifier.Quantity == 0 ? 1 : Request.ItemIdentifier.Quantity;
            bool cancelItem = Request.ItemIdentifier.VoidFlag;
            double peso = Request.ItemIdentifier.ScaleWeight;
            //Logica para validar el valor del codigo de barras
            //Si es un item de busqueda o imagen, trae el valor KeyedItemID, si es escaneado trae barcode
            if (Request.ItemIdentifier.BarCode != null)
                barCode = Request.ItemIdentifier.BarCode.ScanDataLabel;
            else
                barCode = Request.ItemIdentifier.KeyedItemID;


            // Contactar Smart POS Gk.
            var options = new RestClientOptions(UrlRegisterItem)
            {
                MaxTimeout = -1,
                RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
            };
            var client = new RestClient(options);
            var request = new RestRequest(UrlRegisterItem, Method.Post);

            request.AddHeader("Accept", "application/json;Format=GK-PLAIN-JSON");
            request.AddHeader("Content-Type", "application/json;Format=GK-PLAIN-JSON");
            request.AddHeader("_pos_session_", "189b387ad72170063af530dfe4a29c9ae.1004");
            request.AddHeader("Cookie", "sessionid=189b387ad72170063af530dfe4a29c9ae.1004; JSESSIONID=AAA543995E1D10B532197B96F0F107D7");

            var datosItem = new AddItemRequ
            {
                operationConfiguration = new OperationConfiguration
                {
                    forceQuantityInput = false,
                    pricePositionLimit = 10000,
                    pricePositionZeroAllowed = true,
                    priceTransactionLimit = -1,
                    priceDifferencePercentPositionLimit = 100,
                    priceDifferenceAbsolutePositionLimit = 999999,
                    priceDifferenceLimitExceedAction = "Warn",
                    priceNegDifferenceLimitExceedAction = "Warn",
                    closeCurrent = "Required",
                    closePrevious = "Required",
                    filterResult = true,
                    allowedWithWeight = true,
                    allowedWithLength  = true,
                    allowedWithArea = true,
                    allowedWithVolume = true,
                    allowedWithMeasure = true,
                    maximumQuantity = 999999,
                    minimumQuantity = 1,
                    quantityInputOrder = "BeforeOrAfter",
                    priceInputOrder = "BeforeOrAfter",
                    quantityLimitExceedAction = "Warn",
                    amountLimitExceedAction = "Warn",
                    weightUnitFactor = 0,
                    measureUnitFactor = 0,
                    priceDeviationType = "All",
                    priceNegDeviationType = "All",
                    xXCustom08 = "string",
                    xXCustom10 = "string",
                    xXCustom09 = "string",
                    xXCustom07 = "string",
                    xXCustom05 = "string",
                    xXCustom06 = "string",
                    xXCustom11 = "string",
                    xXCustom12 = "string",
                    xXCustom13 = "string",
                    xXCustom14 = "string",
                    xXCustom15 = "string",
                    xXCustom03 = "string",
                    xXCustom02 = "string",
                    xXCustom04 = "string",
                    xXCustom01 = "string"
                },
                barcode = barCode.ToString(),
                salesRestrictionsCheckNeeded = false,
                priceVariant = "Actual",
                itemEntryConfig = new ItemEntryConfig
                {
                    forceQuantityInput = true,
                    pricePositionLimit = 0,
                    pricePositionZeroAllowed = true,
                    priceTransactionLimit = 0,
                    priceDifferencePercentPositionLimit = 0,
                    priceDifferenceAbsolutePositionLimit = 0,
                    priceDifferenceLimitExceedAction = "Warn",
                    priceNegDifferenceLimitExceedAction = "Warn",
                    closeCurrent = "Required",
                    closePrevious = "Required",
                    filterResult = true,
                    allowedWithWeight = true,
                    allowedWithLength = true,
                    allowedWithArea = true,
                    allowedWithVolume = true,
                    allowedWithMeasure = true,
                    maximumQuantity = 0,
                    minimumQuantity = 0,
                    quantityInputOrder = "BeforeOrAfter",
                    priceInputOrder = "BeforeOrAfter",
                    quantityLimitExceedAction = "Warn",
                    weightUnitFactor = 0,
                    measureUnitFactor = 0,
                    priceDeviationType = "All",
                    priceNegDeviationType = "All",
                    xXCustom01 = "string",
                    xXCustom02 = "string",
                    xXCustom03 = "string",
                    xXCustom04 = "string",
                    xXCustom05 = "string",
                    xXCustom06 = "string",
                    xXCustom07 = "string",
                    xXCustom08 = "string",
                    xXCustom09 = "string",
                    xXCustom10 = "string",
                    xXCustom11 = "string",
                    xXCustom12 = "string",
                    xXCustom13 = "string",
                    xXCustom14 = "string",
                    xXCustom15 = "string"
                },
                entryMethodCode = "Keyed",
                keyedOnline = true
            };

            string json = JsonSerializer.Serialize(datosItem, new JsonSerializerOptions { WriteIndented = true });
            request.AddParameter("application/json", json, ParameterType.RequestBody);

            RestResponse response = client.Execute(request);

            try
            {
                if (response.IsSuccessful)
                {
                    var options2 = new JsonSerializerOptions
                    {
                        PropertyNameCaseInsensitive = true
                    };

                    var jObject = JObject.Parse(response.Content);
                    var jsonString = jObject["primaryEntry"].ToString();
                    var jsonObject = JsonSerializer.Deserialize<primaryEntry>(jsonString, options2);

                    var transactionId = jsonObject.transaction.key.transactionID;
                    var addedOrModifiedLineItems = jsonObject.addedOrModifiedLineItems;
                    var itemId = addedOrModifiedLineItems[0].saleReturnLineItemList[0].itemID;
                    var regularUnitPrice = addedOrModifiedLineItems[0].saleReturnLineItemList[0].regularUnitPrice;
                    var quantityService = addedOrModifiedLineItems[0].saleReturnLineItemList[0].quantity;
                    var units = addedOrModifiedLineItems[0].saleReturnLineItemList[0].units;
                    var textName = addedOrModifiedLineItems[0].saleReturnLineItemList[0].receiptText;

                    //Pasarlo a string
                    var regularUnitPriceTrans = regularUnitPrice.ToString();

                    Log.Debug($"Transaction ID: {transactionId} ");
                    Entorno<EntornoGK>.Instancia.get().TransactionID = transactionId;

                    string tomarNombreCorto = "";
                    //Valores que se mandan en chec
                    var date = DateTime.Now.ToString("dd/MM/yyyy");
                    CultureInfo culture = new CultureInfo("en-US");
                    culture.DateTimeFormat.AMDesignator = "AM";
                    culture.DateTimeFormat.PMDesignator = "PM";
                    var time = DateTime.Now.ToString("hh:mm tt", culture);

                    transactionStatusEvent = new TransactionStatusEvent(1, TipoMensaje.Event, requestId, "TRANSACTION_START", 1, "regularSale", "sales", date, time);
                    pOSReceiptEvent = new POSReceiptEvent(1, TipoMensaje.Event, requestId, "Customer", 0, "Body", requestId, 1, "center", "LineItem", "ItemSale", itemId + "   " + textName + "      " + quantityService + "      " + regularUnitPrice, "Add");
                    posReceiptEventHeader = new POSReceiptEventHeaderResponse(1, TipoMensaje.Event, requestId);
                    totalEvent = new TotalsEventResponse(1, TipoMensaje.Event, requestId, regularUnitPriceTrans, regularUnitPriceTrans, regularUnitPriceTrans, regularUnitPriceTrans, "0.00", "0.00", "0.00", "0.00", "0.00", 1, 0, "0.00", "0.00");
                    itemResponse = new AddItemResponse(1, TipoMensaje.Resp, requestId, tomarNombreCorto, "false", "false", "true", "1234", "ScannedItemCode", "3200", 1, "3200", 0, "0.00", 0, 1, 0, "unit", "false", 0, "false", "false", "true", "true");
                    respuesta = new Respuestas { transactionStatusEvent, posReceiptEventHeader, pOSReceiptEvent, totalEvent, itemResponse };
                }
                else
                {
                    addItemResponseError = new AddItemResponseError(1, TipoMensaje.Resp, requestId, "Articulo no encontrado", "ITEM_NOT_FOUND");
                    respuesta = new Respuestas { addItemResponseError };
                }
            }
            catch(Exception err)
            {
                Log.Error("Error al conectarse al servidor", err);
            }
            
            return respuesta;
        }
        public IComando CreaCopia()
        {
            return (AddItemRequestCmdGk)this.MemberwiseClone();
        }

        public void CargaDTO(DTOBase addItemRequestDTO)
        {
            Request = (AddItemRequestDTO)addItemRequestDTO;
        }
    }
}
