using System.Diagnostics;
using System.Text;
using Serilog;
using GatewaySCO;
using gatewayGK.ComandosGk;
using SCOGateway.POSGk;
using EvaPosSrvDTO;
using EvaPOS_API_FRAME.DTO;
using EvaPOS_API_FRAME.RespuestasXML;
using EvaPosSrvResp;

namespace pruebas
{
    public class Program
    {
        static void Main(string[] args)
        {
            // Instancia Serilog según parámetros en archivo de configuración.
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Verbose()
                .WriteTo.File("./logs/log-.txt", rollingInterval: RollingInterval.Day)
                .WriteTo.Console()
                .CreateLogger();

            Log.Information("*** Inicio pruebas GatewayGK ***");
            Program p = new Program();
            p.Inicia(args);
            p.Ejecutar();
        }

        public void Ejecutar()
        {
            Respuestas? resp = null;

            Login();

            resp = AddItemCodbar(7703100270009); // Cheerios
            Log.Debug(RespuestasTextoAddItem(resp));

            resp = AddItemCodbar(7123456000677); // Desodorante Spray
            Log.Debug(RespuestasTextoAddItem(resp));

            // resp = AddItemCodbar(7500110000035); // Vino blanco casa madero
            // Log.Debug(RespuestasTextoAddItem(resp));

            // resp = AddItemCodbar(7500110000042); // Vino blanco de bla
            // Log.Debug(RespuestasTextoAddItem(resp));

            resp = AddItemCodbar(4005800095498); // Galletas Oreo
            Log.Debug(RespuestasTextoAddItem(resp));

            resp = AddItemCodbar(7703100280008); // yogurt
            Log.Debug(RespuestasTextoAddItem(resp));

            // resp = AddItemCodbar(7703101570009); // Apple
            // Log.Debug(RespuestasTextoAddItem(resp));

            // resp = AddItemCodbar(7703118330009); // Toothbrush
            // Log.Debug(RespuestasTextoAddItem(resp));

            // resp = AddItemCodbar(7703111560007); // Wrapping Paper
            // Log.Debug(RespuestasTextoAddItem(resp));

            // resp = AddItemCodbar(7700000000000); // no existe
            // Log.Debug(RespuestasTextoAddItem(resp));

            resp = Subtotal();

            resp = Pago();

            Logout();
        }

        string RespuestasTextoAddItem(Respuestas resp)
        {
            StringBuilder str = new StringBuilder();
            foreach (var r in resp)
            {
                if (r is AddItemResponseError)
                {
                    str.Append(((AddItemResponseError)r).ToString() + '\n');
                }
                else if (r is TransactionStatusEvent)
                {
                    str.Append(((TransactionStatusEvent)r).ToString() + '\n');
                }
                else
                {
                    str.Append(r.ToString() + '\n');
                }

            }
            return str.ToString();
        }

        public void Inicia(string[] args)
        {
            var p = new GatewaySCO.Program();
            // Esto inicializa el entorno.
            var config = p.LeeConfiguracion(args);
            Log.Debug("config {contig}", config);
        }

        public void Login()
        {
            Log.Debug("-- Login");
            var request = new InitializeRequestDTO(0, new TipoMensaje());
            request.TerminalNumber = 1;
            request.OperatorID = "";
            request.Recovery = false;

            var cmd = new InitializeRequestCmdGk();
            cmd.CargaDTO(request);
            cmd.Ejecutar();

            // Ejecutado el comando, el entorno debe estar inicializado con el id de sesión GK.
            string sessionId = Entorno<EntornoGK>.Instancia.get().posSessionId;
            Log.Debug("-- sessionId {sessionId}", sessionId);
            Debug.Assert(sessionId.Length > 0);
        }

        public Respuestas AddItemCodbar(long codbarItem)
        {
            Log.Debug($"-- AddItem {codbarItem}");

            var request = new AddItemRequestDTO(0, new TipoMensaje());
            var barcode = new BarCode();
            barcode.ScanDataLabel = codbarItem;
            barcode.ScanDataType = null; // TODO cuel es este?
            var itemIdentifier = new ItemIdentifier();
            itemIdentifier.Quantity = 1;
            itemIdentifier.VoidFlag = false;
            itemIdentifier.ScaleWeight = 0;
            itemIdentifier.BarCode = barcode;
            itemIdentifier.KeyedItemID = 0;
            request.ItemIdentifier = itemIdentifier;

            var cmd = new AddItemRequestCmdGk3();
            cmd.CargaDTO(request);
            Respuestas resps = cmd.Ejecutar();
            return resps;
        }

        public Respuestas Subtotal()
        {
            Log.Debug($"-- SubtotalCalculation");
            var request = new AddItemRequestDTO(0, new TipoMensaje());
            var cmd = new SubtotalCalculationCmdGk();

            cmd.CargaDTO(request);
            Respuestas resps = cmd.Ejecutar();
            return resps;
        }

        public Respuestas Pago()
        {
            Log.Debug($"-- UpdateTerminalTenderAuthorization");
            var request = new AddItemRequestDTO(0, new TipoMensaje());
            var cmd = new UpdateTerminalTenderAuthorizationCmdGk();

            cmd.CargaDTO(request);
            Respuestas resps = cmd.Ejecutar();
            return resps;
        }

        public void Logout()
        {
            Log.Debug("-- Logout");
            var request = new TerminateRequestDTO(0, new TipoMensaje());
            request.DestroySession = true;

            var cmd = new TerminateRequestCmdGk();
            cmd.CargaDTO(request);
            cmd.Ejecutar();

            // Ejecutado el comando, el entorno debe tener el sessionId vacio.
            string sessionId = Entorno<EntornoGK>.Instancia.get().posSessionId;
            Log.Debug("-- sessionId {sessionId}", sessionId);
            Debug.Assert(sessionId == "", "sessionId no tiene valor vacío ''.");
        }
    }
}