using EvaPOS_API_FRAME.DTO;
using EvaPOS_API_FRAME.RespuestasXML.TerminateLane;
using EvaPosSrvDTO;
using EvaPosSrvResp;
using Serilog;
using GatewaySCO;
using RestSharp;
using SCOGateway.POSGk;
using System.Text.Json;

namespace gatewayGK.ComandosGk
{
    /// <summary>
    /// Comando para cerrar la lane   
    /// </summary>
    public class TerminateRequestCmdGk : IComando
    {
        public string Referencia { get; set; } = "scsns:Terminate";
        /// <summary>
        /// DTO con solicitud.
        /// </summary>
        public TerminateRequestDTO Destroy { get; private set; }
        private string _urlLogout = Entorno<EntornoGK>.Instancia.get().UrlBase
            + "/com.gk_software.pos.api.service.session.PosSessionService/logout";

        /// <summary>
        /// Procesa y responde el evento Terminar.
        /// </summary>
        public Respuestas Ejecutar()
        {
            Log.Debug("Cmd TerminateRequestDTO ejecutado. TerminateRequest : {TerminateRequest}", Destroy.DestroySession);
            var requestId = Destroy.DestroySession;

            // --- cliente rest.
            string sessionId = Entorno<EntornoGK>.Instancia.get().posSessionId;
            var options = new RestClientOptions()
            {
                // TODO manejar el timeout como un parámetro de configuración.
                MaxTimeout = -1,
                RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
            };
            string cookieValue = $"sessionid={sessionId}";
            var request = new RestRequest(_urlLogout, Method.Post);
            request.AddHeader("Accept", "application/json;Format=GK-PLAIN-JSON");
            request.AddHeader("Content-Type", "application/json");
            request.AddHeader("_pos_session_", sessionId);

            var logoutReq = new LogoutReq
            {
                PosSessionId = new PosSessionId
                {
                    id = sessionId
                }
            };

            string json = JsonSerializer.Serialize(logoutReq);
            Log.Verbose(">> GK logout - body {json}", json);
            request.AddJsonBody(json);
            var client = new RestClient(options);
            Log.Information(">> GK logout - posSessionId {posSessionId}", sessionId);
            var response = client.Execute(request);
            Log.Debug("<< GK Logout - StatusCode {StatusCode}", response.StatusCode);
            Log.Verbose("<< GK Logout - Headers {Headers}", response.Headers);
            Log.Verbose("<< GK Logout - Content {Content}", response.Content);

            if (response.IsSuccessful == false)
            {
                // TODO - interpretar la respuesta par amostrar el mensaje de error, ejemplo:
                // {"errorCode":{"errorCode":"GKR-POS-000001","message":"Invalid session","messageKey":"com.gk_software.pos.utils.error.ErrorCodeMessages.MSG_INVALID_SESSION","arguments":[]},"timestamp":"2023-08-04T07:16:57.066","additionalContextInfoMap":{}}
                Log.Error("<< GK logout failed: StatusCode {StatusCode}, Content {Content}",
                    response.StatusCode, response.Content);
                throw new ApplicationException("Servicio POST 'Logout' en error.");
            }

            // var logoutResp = JsonSerializer.Deserialize<LogoutResp>(response.Content
            //     ?? throw new ApplicationException("Null content in response to POST method."))
            //     ?? throw new ApplicationException("logoutResp object not found in response POST method.");

            // var success = logoutResp.success;

            // ---- Usando JsonElement
            var jsonElement = System.Text.Json.JsonSerializer.Deserialize<JsonElement>(response.Content
                ?? throw new ApplicationException("Null content in response to POST method."));

            var transactionID = jsonElement
                    .GetProperty("primaryEntry")
                    .GetProperty("transaction")
                    .GetProperty("key")
                    .GetProperty("transactionID")
                    .GetString();
            var success = jsonElement
                    .GetProperty("success")
                    .GetBoolean();

            if (success)
                Entorno<EntornoGK>.Instancia.get().posSessionId = "";
           
            Log.Information("<< GK logout - success {success}, transactionID {transactionID}", 
                    success, transactionID);

            TerminateResponse terminateResponse = new TerminateResponse(1, TipoMensaje.Resp, requestId);
            return (new Respuestas { terminateResponse });
        }

        public IComando CreaCopia()
        {
            return (TerminateRequestCmdGk)this.MemberwiseClone();
        }

        public void CargaDTO(DTOBase terminateRequest)
        {
            Destroy = (TerminateRequestDTO)terminateRequest;
        }

    }
}
