using EvaPOS_API_FRAME.RespuestasXML;
using EvaPosSrvDTO;
using EvaPosSrvResp;
using GatewaySCO;
using RestSharp;
using SCOGateway.POSGk;
using Serilog;
using System.Text.Json;
using Microsoft.Extensions.Configuration;


namespace gatewayGK.ComandosGk
{
    public class InitializeRequestCmdGk : IComando
    {
        public string Referencia { get; set; } = "scsns:Initialize";
        /// <summary>
        /// DTO con solicitud.
        /// </summary>
        public InitializeRequestDTO Request { get; private set; }

        /// <summary>
        /// Url servicio autenticación Gk.
        /// </summary>
        private string _urlLogin = Entorno<EntornoGK>.Instancia.get().UrlBase 
            + "/com.gk_software.pos.api.service.session.PosSessionService/login";

        /// <summary>
        /// Procesa y responde el login.
        /// </summary>
        /// 

        public Respuestas Ejecutar()
        {
            string cookieValue = $"JSESSIONID=";

            string banner = 
            """
            
                 _____  _    _ ______  ____             _____ _                                   _____ _  __  _____                       _     _____   ____   _____ 
                / ____ | |  | |  ____/ ____|           / ____| |                                 / ____| |/ / / ____|                     | |   |  __ \ / __ \ / ____|
                | |    | |__| | |__ | |       ______  | |  __| |___      ____ _ _   _   ______  | |  __| ' /  | (___  _ __ ___   __ _ _ __| |_  | |__) | |  | | (___  
                | |    |  __  |  __|| |      |______| | | |_ | __\ \ /\ / / _` | | | | |______| | | |_ |  <    \___ \| '_ ` _ \ / _` | '__| __| |  ___/| |  | |\___ \ 
                | |___ | |  | | |___| |____           | |__| | |_ \ V  V / (_| | |_| |          | |__| | . \   ____) | | | | | | (_| | |  | |_  | |    | |__| |____) |
                \_____ |_|  |_|______\_____|           \_____|\__| \_/\_/ \__,_|\__, |           \_____|_|\_\ |_____/|_| |_| |_|\__,_|_|   \__| |_|     \____/|_____/ 
                                                                                __/ |                                                                                
                                                                                |___/                                                                                 
                
            """;

            Log.Information(banner);

            int terminalNumber = Request.TerminalNumber;
            Log.Debug("Cmd InitializeRequestCmd ejecutado: OperatorID {OperatorID}, TerminalNumber {TerminalNumber}, Recovery {Recovery}", Request.OperatorID, Request.TerminalNumber, Request.Recovery);
            // Contactar Smart POS Gk.

            var options = new RestClientOptions()
            {
                // TODO manejar el timeout como un parámetro de configuración.
                MaxTimeout = -1,
                RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
            };

            var client = new RestClient(options);
            var request = new RestRequest(_urlLogin, Method.Post);
            request.AddHeader("Accept", "application/json;Format=GK-PLAIN-JSON");
            request.AddHeader("Content-Type", "application/json");
            request.AddHeader("Cookie", cookieValue);

            var datosAutenticacion = new AutenticationReq
            {
                RetailStoreId = Entorno<EntornoGK>.Instancia.get().ConfigGk.RetailStoreId,
                WorkstationId = Entorno<EntornoGK>.Instancia.get().ConfigGk.WorkstationId,
                WorkstationAddress = Entorno<EntornoGK>.Instancia.get().ConfigGk.WorkstationAddress,
                WorkstationTypeCode = Entorno<EntornoGK>.Instancia.get().ConfigGk.WorkstationTypeCode,
                LoginName = Entorno<EntornoGK>.Instancia.get().ConfigGk.LoginName,
                Password = Entorno<EntornoGK>.Instancia.get().ConfigGk.Password,
                TrainingMode = false,
                FinalizeControlTransactionFlag = false,
                UseLoginTypeTechnicalForLoginManager = false,
                TillId = new Till
                {
                    TillDoKey = new TillDoKey
                    {
                        BusinessUnitGroupID = Entorno<EntornoGK>.Instancia.get().ConfigGk.BusinessUnitGroupID,
                        TillID = Entorno<EntornoGK>.Instancia.get().ConfigGk.TillID
                    }
                }
            };

            var loginRequestWrapper = new LoginRequestWrapper
            {
                LoginRequest = datosAutenticacion
            };

            string json = JsonSerializer.Serialize(loginRequestWrapper);

            request.AddJsonBody(json);
            Log.Information(">> GK login: LoginName {LoginName}, RetailStoreId {RetailStoreId}, WorkstationId {WorkstationId}",
                datosAutenticacion.LoginName, datosAutenticacion.RetailStoreId, datosAutenticacion.WorkstationId);
            var response = client.Execute(request);

            if (response.IsSuccessful == false)
            {
                // TODO mejorar manejo como en Logout
                Log.Error("<< GK login failed: StatusCode {StatusCode}, Content {Content}", 
                    response.StatusCode, response.Content);
                throw new ApplicationException("Servicio POST 'Login' en error.");
            }

            Log.Debug("<< GK login - StatusCode {StatusCode}", response.StatusCode);
            Log.Verbose("<< GK login - Headers {Headers}", response.Headers);
            Log.Verbose("<< GK login - Content {Content}", response.Content);

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

            var transactionId = autenticacionResp.primaryEntry.transaction.key.transactionID;
            var operatorID = autenticacionResp.primaryEntry.transaction.operatorID;
            var posSessionId = autenticacionResp.posSessionId.id;
            // Salvar Transaccion y id de la session.
            Entorno<EntornoGK>.Instancia.get().posSessionId = posSessionId;
            Log.Information("<< GK login:operatorID {operatorID}, transactionId {transactionId}, posSessionId {posSessionId}",
                operatorID, transactionId, Entorno<EntornoGK>.Instancia.get().posSessionId);

            // Respuestas a SCO.
            var posbcStatus1 = new POSBCStatusEvent(1, TipoMensaje.Event, "INFO", "CONNECTING_TO_POS", "Connecting to POS system");
            var posbcStatus2 = new POSBCStatusEvent(1, TipoMensaje.Event, "INFO", "CONNECTED_TO_POS", "Connected to POS system");
            var posbcStatus3 = new POSBCStatusEvent(1, TipoMensaje.Event, "INFO", "POS_RESOURCES_INITIALIZED", "POS Resources Initialized");
            var inicializacionOk = new InitializeResponse(1, TipoMensaje.Resp, terminalNumber);
            Respuestas respuestaChec = new Respuestas { posbcStatus1, posbcStatus2, posbcStatus3, inicializacionOk };
            return respuestaChec;
        }

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

        public void CargaDTO(DTOBase initializeRequestDTO)
        {
            Request = (InitializeRequestDTO)initializeRequestDTO;
        }
    }
}



