/// <summary>
        /// The Payment Method executes the payment Authorisation
        /// for the received transaction payment amount from the kiosk
        /// Sends socket inputs to smartpay
        /// Sends the Authorisation response value out
        /// if Authorisation is successful waits for an order number
        /// if Order number is valid from a transaction thats goes through
        /// run the settlement process or if transaction result not valid
        /// void the transaction.
        /// sends out the transaction reciepts to the payment service
        /// </summary>
        /// <param name="amount"></param>
        /// <param name="transactionRef"></param>
        /// <param name="transactionReceipts"></param>
        /// <returns></returns>
        public DiagnosticErrMsg Pay(int amount, string transactionRef, out TransactionReceipts transactionReceipts)
        {
            XDocument paymentXml                 = null;
            XDocument procTranXML                = null;
            XDocument customerSuccessXML         = null;
            XDocument processTransRespSuccessXML = null;
            XDocument finaliseXml                = null;
            XDocument voidXml              = null;
            XDocument finaliseSettleXml    = null;
            XDocument paymentSettlementXml = null;
            XDocument procSettleTranXML    = null;

            int intAmount;

            isSuccessful        = DiagnosticErrMsg.OK;
            transactionReceipts = new TransactionReceipts();

            //check for a success or failure string from smartpay
            string submitPaymentResult       = string.Empty;
            string finaliseResult            = string.Empty;
            string finaliseSettleResult      = string.Empty;
            string submitSettlePaymentResult = string.Empty;
            string description = transactionRef;

            // increment transaction number
            number++;
            transNum = number.ToString().PadLeft(6, '0');

            //check for transNum max value
            if (transNum == transactionLimit)
            {
                //reset back to beginning
                number   = 1;
                transNum = number.ToString().PadLeft(6, '0');
            }

            //check amount is valid
            intAmount = Utils.GetNumericAmountValue(amount);

            if (intAmount == 0)
            {
                throw new Exception("Error in Amount value...");
            }

            Log.Info($"Valid payment amount: {intAmount}");
            Log.Info("Transaction Number : " + transNum);
            Log.Info("Transaction Ref (Description) : " + transactionRef);


            /*********************** AUTHORISATION SECTION ***************************
            *
            * Submittal – Submitting data to Smartpay Connect ready for processing.
            * SUBMIT PAYMENT Process
            *
            *************************************************************************/

            //process Payment XML
            paymentXml = smartpayOps.Payment(amount, transNum, description, sourceId, currency, country);

            Socket paymentSocket = CreateSocket();

            Log.Info("paymentSocket Open: " + SocketConnected(paymentSocket));

            //send submitpayment to smartpay - check response
            string paymentResponseStr = sendToSmartPay(paymentSocket, paymentXml, "SUBMITPAYMENT");

            //check response from Smartpay is not Null or Empty
            if (CheckIsNullOrEmpty(paymentResponseStr, "Submit Authorisation Payment"))
            {
                isSuccessful = DiagnosticErrMsg.NOTOK;
            }
            else
            {
                //check response outcome
                submitPaymentResult = CheckResult(paymentResponseStr);

                if (submitPaymentResult.ToLower() == "success")
                {
                    Log.Info("Successful payment submitted");
                }
                else
                {
                    Log.Error("Payment failed");
                    isSuccessful = DiagnosticErrMsg.NOTOK;
                }
            }

            //checkSocket closed
            Log.Info("paymentSocket Open: " + SocketConnected(paymentSocket));

            /************************************************************************************
             *                                                                                   *
             * Transactional – Processing of a transaction submitted during the submittal phase. *
             * PROCESSTRANSACTION process   - gets the Merchant receipt                          *
             *                                                                                   *
             *************************************************************************************/

            //create processtransaction socket
            Socket processSocket = CreateSocket();

            Log.Info("ProcessTransaction Socket Open: " + SocketConnected(processSocket));

            //Process Transaction XML
            procTranXML = smartpayOps.ProcessTransaction(transNum);

            //send processTransaction - check response
            string processTranReturnStr = sendToSmartPay(processSocket, procTranXML, "PROCESSTRANSACTION");

            //check response from Smartpay is not NULL or Empty
            if (CheckIsNullOrEmpty(processTranReturnStr, "Process Transaction"))
            {
                isSuccessful = DiagnosticErrMsg.NOTOK;
            }
            else
            {
                //check that the response contains a Receipt or is not NULL this is the Merchant receipt
                transactionReceipts.MerchantReturnedReceipt = ExtractXMLReceiptDetails(processTranReturnStr);

                //Check the merchant receipt is populated
                if (CheckIsNullOrEmpty(transactionReceipts.MerchantReturnedReceipt, "Merchant Receipt populated"))
                {
                    isSuccessful = DiagnosticErrMsg.NOTOK;
                }
                else
                {
                    //check if reciept has a successful transaction
                    if (transactionReceipts.MerchantReturnedReceipt.Contains("DECLINED"))
                    {
                        Log.Error("Merchant Receipt has Declined Transaction.");
                        isSuccessful = DiagnosticErrMsg.NOTOK;
                    }
                }
            }

            //check socket closed
            Log.Info("ProcessTransaction Socket Open: " + SocketConnected(processSocket));

            /******************************************************************************
             *                                                                             *
             * Interaction – Specific functionality for controlling POS and PED behaviour. *
             * gets the Customer receipt                                                   *
             *                                                                             *
             *******************************************************************************/

            //create customer socket
            Socket customerSuccessSocket = CreateSocket();

            Log.Info("customerSuccess Socket Open: " + SocketConnected(customerSuccessSocket));

            //process customerSuccess XML
            customerSuccessXML = smartpayOps.PrintReciptResponse(transNum);

            string customerResultStr = sendToSmartPay(customerSuccessSocket, customerSuccessXML, "CUSTOMERECEIPT");

            //Check response from Smartpay is not Null or Empty
            if (CheckIsNullOrEmpty(customerResultStr, "Customer Receipt process"))
            {
                isSuccessful = DiagnosticErrMsg.NOTOK;
            }
            else
            {
                transactionReceipts.CustomerReturnedReceipt = ExtractXMLReceiptDetails(customerResultStr);

                //check returned receipt is not Null or Empty
                if (CheckIsNullOrEmpty(transactionReceipts.CustomerReturnedReceipt, "Customer Receipt returned"))
                {
                    isSuccessful = DiagnosticErrMsg.NOTOK;
                }
                else
                {
                    //check if reciept has a successful transaction
                    if (transactionReceipts.CustomerReturnedReceipt.Contains("DECLINED"))
                    {
                        Log.Error("Customer Receipt has Declined Transaction.");
                        isSuccessful = DiagnosticErrMsg.NOTOK;
                    }
                }
            }

            Log.Info("customerSuccess Socket Open: " + SocketConnected(customerSuccessSocket));

            /***********************************************************************************************************
             * Interaction – Specific functionality for controlling PoS and PED behaviour. ( ProcessTransactionResponse)
             * PROCESSTRANSACTIONRESPONSE
             *************************************************************************************************************/

            Socket processTransactionRespSocket = CreateSocket();

            Log.Info("processTransactionRespSocket Socket Open: " + SocketConnected(processTransactionRespSocket));
            processTransRespSuccessXML = smartpayOps.PrintReciptResponse(transNum);

            string processTransRespStr = sendToSmartPay(processTransactionRespSocket, processTransRespSuccessXML, "PROCESSTRANSACTIONRESPONSE");

            //check response from Smartpay is not Null or Empty
            if (CheckIsNullOrEmpty(processTransRespStr, "Process Transaction Response"))
            {
                isSuccessful = DiagnosticErrMsg.NOTOK;
            }
            else
            {
                //get the reference value from the process Transaction Response
                // this is needed for the settlement process
                //
                reference = GetReferenceValue(processTransRespStr);

                Log.Info($"REFERENCE Number = {reference}");


                if (processTransRespStr.Contains("declined"))
                {
                    Log.Error("***** Auth Process Transaction Response has Declined Transaction. *****");
                    isSuccessful = DiagnosticErrMsg.NOTOK;
                }
            }

            Log.Info("processTransRespSuccessXML Socket Open: " + SocketConnected(processTransactionRespSocket));

            /*****************************************************************************************************************
             *
             * finalise Response message so that the transaction can be finalised and removed from Smartpay Connect's memory
             *
             *   FINALISE
             ******************************************************************************************************************/

            Socket finaliseSocket = CreateSocket();

            Log.Info("Finalise Socket Open: " + SocketConnected(finaliseSocket));

            finaliseXml = smartpayOps.Finalise(transNum);

            string finaliseStr = sendToSmartPay(finaliseSocket, finaliseXml, "FINALISE");

            //check response from Smartpay is not Null or Empty
            if (CheckIsNullOrEmpty(finaliseStr, "Finalise Authorisation"))
            {
                isSuccessful = DiagnosticErrMsg.NOTOK;
            }
            else
            {
                finaliseResult = CheckResult(finaliseStr);

                if (finaliseResult == "success")
                {
                    Log.Info("****** Authorisation Transaction Finalised Successfully******");
                }
                else
                {
                    Log.Info("***** Authorisation Transaction not Finalised *****");
                    isSuccessful = DiagnosticErrMsg.NOTOK;
                }
            }

            Log.Info("Finalise Socket Open: " + SocketConnected(finaliseSocket));

            /*****************************************************************************************************************
             *
             * check if the Authorisation has been successful
             *
             ******************************************************************************************************************/

            if (isSuccessful == DiagnosticErrMsg.OK)
            {
                authorisationFlag = true;
            }
            else
            {
                authorisationFlag = false;
                isSuccessful      = DiagnosticErrMsg.NOTOK;
            }


            /* **********************************************************************
             *
             * if Authorisation check successful carry on else
             * end Authorisation and close database connection
             *
             ******************************************************************/


            if (authorisationFlag == false)
            {
                //authoriation has failed return to paymentService
                //end payment process and  print out failure receipt.

                Log.Error("\n***** Authorisation Check has failed. *****\n");
                return(DiagnosticErrMsg.NOTOK);
            }
            else
            {
                Log.Info("\n\n***** Payment Authorisation Check has passed. Get Order Number. *****\n");
            }

            /*************************************************************************************************
             * AUTHORISATION check has passed run the APIS and get back the OrderNumber from the Flyt system
             *
             * Need to run the APIs MarkAsPaid and SendToPOS
             *
             **************************************************************************************************/

            using (SqlConnection con = new SqlConnection())
            {
                con.ConnectionString = connectionString;
                con.Open();
                CallStoredProcs storedProcs = new CallStoredProcs();

                Log.Info("RefInt = " + transactionRef);

                /**********************************************
                 * Get BasketID and OrderId using RefInt
                 * *********************************************/
                Log.Info("tableName = " + tableName);
                SqlCommand comm = new SqlCommand($"SELECT ID, APIOrderID from { tableName } where KioskRefInt = {Convert.ToInt32(transactionRef)}", con);
                using (SqlDataReader reader = comm.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        basketId = reader.GetInt32(0);
                        orderId  = reader.GetString(1);
                    }
                }

                Log.Info($"BasketId =  {basketId}");
                Log.Info($"OrderId =  {orderId}");


                //1)  call stored procedure OrderBasket_API_MarkAsPaid to get Payload for API Call
                payLoad = storedProcs.ExecuteOrderBasket_API_MarkAsPaid(con, basketId);

                //2) call MarkAsPaid API with the generated PayLoad
                //IRestResponse markAsPaidResp = storedProcs.MarkAsPaidAPI(orderId, payLoad);

                string url = orderURL + "/" + orderId + markAsPaidURL;

                IRestResponse markAsPaidResp = storedProcs.ApiPost(url,
                                                                   keyType2,
                                                                   aPIKey2,
                                                                   contentType,
                                                                   payLoad);

                if (markAsPaidResp.IsSuccessful)
                {
                    //3) call stored procedure OrderBasket_APIResponse_MarkAsPaid to check response of API Call
                    storedProcs.ExecuteOrderBasket_APIResponse_MarkAsPaid(con, basketId, markAsPaidResp.Content);

                    Log.Info($"MarkAsPaid return =  {markAsPaidResp.Content}");

                    //4) Call stored procedure OrderBasket_API_SendToPos to get PayLoad to use in API call
                    payLoad = string.Empty;
                    payLoad = storedProcs.ExecuteOrderBasket_API_SendToPos(con, basketId);

                    //5) Call SendToPos API with the generated PayLoad
                    //IRestResponse sendToPOSResp = storedProcs.SendToPOSAPI(payLoad);
                    //IRestResponse sendToPOSResp = storedProcs.SendToPOSAPI(orderId);

                    IRestResponse sendToPOSResp = storedProcs.ApiPost(sendToPOSURL,
                                                                      keyType1,
                                                                      aPIKey1,
                                                                      contentType,
                                                                      payLoad);

                    if (sendToPOSResp.IsSuccessful)
                    {
                        //6) call stored procedure OrderBasket_APIResponse_SendToPos to check response from API
                        storedProcs.ExecuteOrderBasket_APIResponse_SendToPos(con, basketId, sendToPOSResp.Content);
                        //get PosOrderNumber
                        //dynamic sendToPOS = JsonConvert.DeserializeObject<dynamic>(sendToPOSResp.Content);
                        //posOrderId = sendToPOS.Data.PosOrderID;
                        //Log.Info($"Order Number returned: {posOrderId}");


                        // Create and configure a command object to get the PosOrderID
                        SqlCommand com = con.CreateCommand();
                        com.CommandType = CommandType.StoredProcedure;
                        com.CommandText = "OrderBasket_APIPosOrderID_ByID";
                        com.Parameters.Add("@OrderBasketID", SqlDbType.VarChar).Value
                            = basketId;
                        var result = com.ExecuteScalar();
                        posOrderId = result.ToString();
                    }
                    else
                    {
                        posOrderId   = null;
                        isSuccessful = DiagnosticErrMsg.NOTOK;
                        Log.Error($"SendToPOS API Failed =  {markAsPaidResp.Content}");
                    }
                }
                else
                {
                    Log.Error("MarkAsPaid API Failed");
                    isSuccessful = DiagnosticErrMsg.NOTOK;
                }
            }

            /********************************************************************************
            *
            * Submittal using settlement Reference
            *
            * ******************************************************************************/

            if (string.IsNullOrEmpty(posOrderId))
            {
                Log.Error("\n*** No order number returned the Transaction will be voided **************\n");
            }


            /************************************************************************************
            *
            * Check the transaction returns an order number and settle the transaction
            * if not void the transaction
            *
            * **********************************************************************************/

            if ((isSuccessful == DiagnosticErrMsg.OK) && (authorisationFlag == true) && (!(string.IsNullOrEmpty(posOrderId))))
            {
                /****************************************************************************
                * Submittal using settlement Reference, amount , transNum
                * description which is the transaction reference
                *
                * Submit Settlement Payment
                ****************************************************************************/
                Log.Info("\n******Performing Settlement Payment ******\n");

                paymentSettlementXml = smartpayOps.PaymentSettle(amount, transNum, reference, description, currency, country);

                // open paymentXml socket connection
                Socket paymenSettlementSocket = CreateSocket();

                //check socket open
                Log.Info("Paymentsocket Open: " + SocketConnected(paymenSettlementSocket));

                //send submitpayment to smartpay - check response
                string paymentSettleResponseStr = sendToSmartPay(paymenSettlementSocket, paymentSettlementXml, "SUBMITPAYMENT");


                //check response from Smartpay is not Null or Empty
                if (CheckIsNullOrEmpty(paymentSettleResponseStr, "Settlement Payment"))
                {
                    isSuccessful = DiagnosticErrMsg.NOTOK;
                }
                else
                {
                    submitSettlePaymentResult = CheckResult(paymentSettleResponseStr);

                    if (submitSettlePaymentResult == "success")
                    {
                        Log.Info("******Successful Settlement Payment submitted******\n");
                    }
                    else
                    {
                        Log.Error("****** Settlement Payment failed******\n");
                        isSuccessful = DiagnosticErrMsg.NOTOK;
                    }
                }


                Log.Info("paymenSettlementSocket Open: " + SocketConnected(paymenSettlementSocket));

                /****************************************************************************
                 * Process the settlement transaction                                        *
                 *                                                                           *
                 *****************************************************************************/
                Socket processSettleSocket = CreateSocket();

                Log.Info("processSettleSocket Socket Open: " + SocketConnected(processSettleSocket));

                procSettleTranXML = smartpayOps.ProcessTransaction(transNum);
                //send processTransaction - check response

                string processSettleTranResponseStr = sendToSmartPay(processSettleSocket, procSettleTranXML, "PROCESSSETTLETRANSACTION");
                //check response from Smartpay is not Null or Empty
                if (CheckIsNullOrEmpty(processSettleTranResponseStr, "Process Settlement Transaction"))
                {
                    isSuccessful = DiagnosticErrMsg.NOTOK;
                }
                //No response needed

                Log.Info("processSettleSocket Socket Open: " + SocketConnected(processSettleSocket));

                /****************************************************************************
                 * Procees the Settlement finalise transaction                                        *
                 *                                                                           *
                 *****************************************************************************/
                Socket finaliseSettSocket = CreateSocket();

                Log.Info("Finalise Socket Open: " + SocketConnected(finaliseSettSocket));
                finaliseSettleXml = smartpayOps.Finalise(transNum);

                //check response
                string finaliseSettleStr = sendToSmartPay(finaliseSettSocket, finaliseSettleXml, "FINALISE");
                if (CheckIsNullOrEmpty(finaliseSettleStr, "Settlement Finalise"))
                {
                    isSuccessful = DiagnosticErrMsg.NOTOK;
                }
                else
                {
                    finaliseSettleResult = CheckResult(finaliseSettleStr);

                    if (finaliseSettleResult == "success")
                    {
                        Log.Info("******Transaction Settle Finalised successfully******\n");
                    }
                    else
                    {
                        Log.Error("****** Transaction Settle not Finalised ******\n");
                        isSuccessful = DiagnosticErrMsg.NOTOK;
                    }
                }

                Log.Info("Finalise Socket Open: " + SocketConnected(finaliseSettSocket));

                /*****************************************************************************
                *  Update the OrderBasket Table with the PosOrderID number                  *
                *                                                                           *
                *****************************************************************************/
                if (isSuccessful == DiagnosticErrMsg.OK)
                {
                    //add the order number and the VAT to the reciepts
                    //using (SqlConnection con = new SqlConnection())
                    //{
                    //    con.ConnectionString = connectionString;
                    //    con.Open();

                    //    // Create and configure a command object
                    //    SqlCommand com = con.CreateCommand();
                    //    com.CommandType = CommandType.StoredProcedure;
                    //    com.CommandText = "OrderBasket_APIPosOrderID_ByID";
                    //    com.Parameters.Add("@OrderBasketID", SqlDbType.VarChar).Value
                    //    = basketId;
                    //    var result = com.ExecuteScalar();
                    //    Int32 OrderBasketId = Int32.Parse(result.ToString());
                    //    posOrderId = Convert.ToString(OrderBasketId);

                    //}

                    int position = transactionReceipts.CustomerReturnedReceipt.IndexOf("Please");
                    if (position >= 0)
                    {
                        //Add TAX Values and order number
                        // transactionReceipts.CustomerReturnedReceipt = transactionReceipts.CustomerReturnedReceipt.Insert(position, taxValues);
                        transactionReceipts.CustomerReturnedReceipt = transactionReceipts.CustomerReturnedReceipt.Insert(0, "Order Number: " + posOrderId + "\n");
                    }
                }
            }
            else
            {
                ////////////////////////
                // void the transaction
                ////////////////////////

                Socket voidSocket = CreateSocket();
                Log.Info("void Socket Open: " + SocketConnected(voidSocket));

                voidXml = smartpayOps.VoidTransaction(transNum, sourceId, transactionRef);
                string voidResponseStr = sendToSmartPay(voidSocket, voidXml, "VOID");


                //success is not OK
                isSuccessful = DiagnosticErrMsg.NOTOK;
                Log.Info("void Socket Open: " + SocketConnected(voidSocket));
            }
            return(isSuccessful);
        }