<?php

namespace App\Services\Payment\Gateway;

use App\Services\Payment\PaymentInterface;

class NmiPayment implements PaymentInterface
{
// Initial Setting Functions

    private string $base_url = "https://secure.nmi.com/api/transact.php";

    private array $login = [];
    private array $responses = [];
    private array $recurringData = [];

    private array $preparePaymentData = [];

    private array $shipping = [];

    private array $billing = [];

    private array $order = [];
    private bool $isRecurring = false;
    private string $pay_log_id="";
    private array $logData = [];
    private array $data=[];

    function setLogin($security_key) {
        $this->login['security_key'] = $security_key;
        $this->pay_log_id = "LOG_".getSecurityKey();
    }

    function setOrder($orderid,
                      $orderdescription,
                      $tax,
                      $shipping,
                      $ponumber,
                      $ipaddress) {
        $this->order['orderid']          = $orderid;
        $this->order['orderdescription'] = $orderdescription;
        $this->order['tax']              = $tax;
        $this->order['shipping']         = $shipping;
        $this->order['ponumber']         = $ponumber;
        $this->order['ipaddress']        = $ipaddress;
    }

    function setBilling($firstname,
                        $lastname,
                        $company,
                        $address1,
                        $address2,
                        $city,
                        $state,
                        $zip,
                        $country,
                        $phone,
                        $fax,
                        $email,
                        $website) {
        $this->billing['firstname'] = $firstname;
        $this->billing['lastname']  = $lastname;
        $this->billing['company']   = $company;
        $this->billing['address1']  = $address1;
        $this->billing['address2']  = $address2;
        $this->billing['city']      = $city;
        $this->billing['state']     = $state;
        $this->billing['zip']       = $zip;
        $this->billing['country']   = $country;
        $this->billing['phone']     = $phone;
        $this->billing['fax']       = $fax;
        $this->billing['email']     = $email;
        $this->billing['website']   = $website;
    }

    function setShipping($firstname,
                         $lastname,
                         $company,
                         $address1,
                         $address2,
                         $city,
                         $state,
                         $zip,
                         $country,
                         $email) {
        $this->shipping['firstname'] = $firstname;
        $this->shipping['lastname']  = $lastname;
        $this->shipping['company']   = $company;
        $this->shipping['address1']  = $address1;
        $this->shipping['address2']  = $address2;
        $this->shipping['city']      = $city;
        $this->shipping['state']     = $state;
        $this->shipping['zip']       = $zip;
        $this->shipping['country']   = $country;
        $this->shipping['email']     = $email;
    }

    public static function nmiAmountValueFormat($value){
        return number_format($value,2,".","");
    }

   private function preparePaymentData($inputData)
    {

        $this->preparePaymentData['type'] = "sale";
        $this->preparePaymentData['ccnumber'] = $inputData['card_number'];
        $this->preparePaymentData['ccexp'] = $inputData['expiry'];
        $this->preparePaymentData['amount'] = self::nmiAmountValueFormat($inputData['amount']);
        $this->preparePaymentData['cvv'] = $inputData['cvv'] ?? "";

        $this->preparePaymentData['orderid']          = $inputData['order_id'];
        $this->preparePaymentData['orderdescription'] = $inputData['order_description'];
        $this->preparePaymentData['tax']              = number_format($inputData['tax'],2,".","") ;
        $this->preparePaymentData['shipping']         = number_format($inputData['shipping'],2,".","");
        $this->preparePaymentData['ponumber']         = $inputData['ponumber'];
        $this->preparePaymentData['ipaddress']        = $inputData['ip'];

        $this->preparePaymentData['firstname'] = $inputData['first_name'];
        $this->preparePaymentData['lastname']  = $inputData['last_name'];
        $this->preparePaymentData['company']   = $inputData['company'];
        $this->preparePaymentData['address1']  = $inputData['address1'];
        $this->preparePaymentData['address2']  = $inputData['address2'];
        $this->preparePaymentData['city']      = $inputData['city'];
        $this->preparePaymentData['state']     = $inputData['state'];
        $this->preparePaymentData['zip']       = $inputData['zip'];
        $this->preparePaymentData['country']   = $inputData['country'];
        $this->preparePaymentData['email']     = $inputData['email'];
        $this->preparePaymentData['phone']     = $inputData['phone'];
        $this->preparePaymentData['fax']       = $inputData['fax'];
        $this->preparePaymentData['website']   = $inputData['website'];

        $this->preparePaymentData['shipping_firstname'] = $inputData['first_name'];
        $this->preparePaymentData['shipping_lastname']  = $inputData['last_name'];
        $this->preparePaymentData['shipping_company']   = $inputData['company'];
        $this->preparePaymentData['shipping_address1']  = $inputData['address1'];
        $this->preparePaymentData['shipping_address2']  = $inputData['address2'];
        $this->preparePaymentData['shipping_city']      = $inputData['city'];
        $this->preparePaymentData['shipping_state']     = $inputData['state'];
        $this->preparePaymentData['shipping_zip']       = $inputData['zip'];
        $this->preparePaymentData['shipping_country']   = $inputData['country'];
        $this->preparePaymentData['shipping_email']     = $inputData['email'];
    }

    // Transaction Functions

    private function doSale() {

        if(empty($this->preparePaymentData)){
            throw new \Exception('You must have to set payment data by calling preparePaymentData method.');
        }

        /*
        $query  = "";
        // Login Information
        $query .= "security_key=" . urlencode($this->login['security_key']) . "&";
        // Sales Information
        $query .= "ccnumber=" . urlencode($ccnumber) . "&";
        $query .= "ccexp=" . urlencode($ccexp) . "&";
        $query .= "amount=" . urlencode(number_format($amount,2,".","")) . "&";
        $query .= "cvv=" . urlencode($cvv) . "&";
        // Order Information
        $query .= "ipaddress=" . urlencode($this->order['ipaddress']) . "&";
        $query .= "orderid=" . urlencode($this->order['orderid']) . "&";
        $query .= "orderdescription=" . urlencode($this->order['orderdescription']) . "&";
        $query .= "tax=" . urlencode(number_format($this->order['tax'],2,".","")) . "&";
        $query .= "shipping=" . urlencode(number_format($this->order['shipping'],2,".","")) . "&";
        $query .= "ponumber=" . urlencode($this->order['ponumber']) . "&";
        // Billing Information
        $query .= "firstname=" . urlencode($this->billing['firstname']) . "&";
        $query .= "lastname=" . urlencode($this->billing['lastname']) . "&";
        $query .= "company=" . urlencode($this->billing['company']) . "&";
        $query .= "address1=" . urlencode($this->billing['address1']) . "&";
        $query .= "address2=" . urlencode($this->billing['address2']) . "&";
        $query .= "city=" . urlencode($this->billing['city']) . "&";
        $query .= "state=" . urlencode($this->billing['state']) . "&";
        $query .= "zip=" . urlencode($this->billing['zip']) . "&";
        $query .= "country=" . urlencode($this->billing['country']) . "&";
        $query .= "phone=" . urlencode($this->billing['phone']) . "&";
        $query .= "fax=" . urlencode($this->billing['fax']) . "&";
        $query .= "email=" . urlencode($this->billing['email']) . "&";
        $query .= "website=" . urlencode($this->billing['website']) . "&";
        // Shipping Information
        $query .= "shipping_firstname=" . urlencode($this->shipping['firstname']) . "&";
        $query .= "shipping_lastname=" . urlencode($this->shipping['lastname']) . "&";
        $query .= "shipping_company=" . urlencode($this->shipping['company']) . "&";
        $query .= "shipping_address1=" . urlencode($this->shipping['address1']) . "&";
        $query .= "shipping_address2=" . urlencode($this->shipping['address2']) . "&";
        $query .= "shipping_city=" . urlencode($this->shipping['city']) . "&";
        $query .= "shipping_state=" . urlencode($this->shipping['state']) . "&";
        $query .= "shipping_zip=" . urlencode($this->shipping['zip']) . "&";
        $query .= "shipping_country=" . urlencode($this->shipping['country']) . "&";
        $query .= "shipping_email=" . urlencode($this->shipping['email']) . "&";

        $query .= "type=sale";

        return $this->_doPost($query);
*/
        $query  = "";
        // Login Information

        if(!empty($this->preparePaymentData)) {
            $query .= "security_key=" . urlencode($this->login['security_key']) . "&";

            foreach ($this->preparePaymentData as $key => $value) {
                $query .= "&{$key}=" . urlencode($value);
            }
        }

        if(!empty($query)){
            return $this->_doPost($query);
        }

        return false;
    }

    function doAuth($amount, $ccnumber, $ccexp, $cvv="") {

        $query  = "";
        // Login Information
        $query .= "security_key=" . urlencode($this->login['security_key']) . "&";
        // Sales Information
        $query .= "ccnumber=" . urlencode($ccnumber) . "&";
        $query .= "ccexp=" . urlencode($ccexp) . "&";
        $query .= "amount=" . urlencode(number_format($amount,2,".","")) . "&";
        $query .= "cvv=" . urlencode($cvv) . "&";
        // Order Information
        $query .= "ipaddress=" . urlencode($this->order['ipaddress']) . "&";
        $query .= "orderid=" . urlencode($this->order['orderid']) . "&";
        $query .= "orderdescription=" . urlencode($this->order['orderdescription']) . "&";
        $query .= "tax=" . urlencode(number_format($this->order['tax'],2,".","")) . "&";
        $query .= "shipping=" . urlencode(number_format($this->order['shipping'],2,".","")) . "&";
        $query .= "ponumber=" . urlencode($this->order['ponumber']) . "&";
        // Billing Information
        $query .= "firstname=" . urlencode($this->billing['firstname']) . "&";
        $query .= "lastname=" . urlencode($this->billing['lastname']) . "&";
        $query .= "company=" . urlencode($this->billing['company']) . "&";
        $query .= "address1=" . urlencode($this->billing['address1']) . "&";
        $query .= "address2=" . urlencode($this->billing['address2']) . "&";
        $query .= "city=" . urlencode($this->billing['city']) . "&";
        $query .= "state=" . urlencode($this->billing['state']) . "&";
        $query .= "zip=" . urlencode($this->billing['zip']) . "&";
        $query .= "country=" . urlencode($this->billing['country']) . "&";
        $query .= "phone=" . urlencode($this->billing['phone']) . "&";
        $query .= "fax=" . urlencode($this->billing['fax']) . "&";
        $query .= "email=" . urlencode($this->billing['email']) . "&";
        $query .= "website=" . urlencode($this->billing['website']) . "&";
        // Shipping Information
        $query .= "shipping_firstname=" . urlencode($this->shipping['firstname']) . "&";
        $query .= "shipping_lastname=" . urlencode($this->shipping['lastname']) . "&";
        $query .= "shipping_company=" . urlencode($this->shipping['company']) . "&";
        $query .= "shipping_address1=" . urlencode($this->shipping['address1']) . "&";
        $query .= "shipping_address2=" . urlencode($this->shipping['address2']) . "&";
        $query .= "shipping_city=" . urlencode($this->shipping['city']) . "&";
        $query .= "shipping_state=" . urlencode($this->shipping['state']) . "&";
        $query .= "shipping_zip=" . urlencode($this->shipping['zip']) . "&";
        $query .= "shipping_country=" . urlencode($this->shipping['country']) . "&";
        $query .= "shipping_email=" . urlencode($this->shipping['email']) . "&";
        $query .= "type=auth";
        return $this->_doPost($query);
    }

    function doCredit($amount, $ccnumber, $ccexp) {

        $query  = "";
        // Login Information
        $query .= "security_key=" . urlencode($this->login['security_key']) . "&";
        // Sales Information
        $query .= "ccnumber=" . urlencode($ccnumber) . "&";
        $query .= "ccexp=" . urlencode($ccexp) . "&";
        $query .= "amount=" . urlencode(number_format($amount,2,".","")) . "&";
        // Order Information
        $query .= "ipaddress=" . urlencode($this->order['ipaddress']) . "&";
        $query .= "orderid=" . urlencode($this->order['orderid']) . "&";
        $query .= "orderdescription=" . urlencode($this->order['orderdescription']) . "&";
        $query .= "tax=" . urlencode(number_format($this->order['tax'],2,".","")) . "&";
        $query .= "shipping=" . urlencode(number_format($this->order['shipping'],2,".","")) . "&";
        $query .= "ponumber=" . urlencode($this->order['ponumber']) . "&";
        // Billing Information
        $query .= "firstname=" . urlencode($this->billing['firstname']) . "&";
        $query .= "lastname=" . urlencode($this->billing['lastname']) . "&";
        $query .= "company=" . urlencode($this->billing['company']) . "&";
        $query .= "address1=" . urlencode($this->billing['address1']) . "&";
        $query .= "address2=" . urlencode($this->billing['address2']) . "&";
        $query .= "city=" . urlencode($this->billing['city']) . "&";
        $query .= "state=" . urlencode($this->billing['state']) . "&";
        $query .= "zip=" . urlencode($this->billing['zip']) . "&";
        $query .= "country=" . urlencode($this->billing['country']) . "&";
        $query .= "phone=" . urlencode($this->billing['phone']) . "&";
        $query .= "fax=" . urlencode($this->billing['fax']) . "&";
        $query .= "email=" . urlencode($this->billing['email']) . "&";
        $query .= "website=" . urlencode($this->billing['website']) . "&";
        $query .= "type=credit";
        return $this->_doPost($query);
    }

    function doOffline($authorizationcode, $amount, $ccnumber, $ccexp) {

        $query  = "";
        // Login Information
        $query .= "security_key=" . urlencode($this->login['security_key']) . "&";
        // Sales Information
        $query .= "ccnumber=" . urlencode($ccnumber) . "&";
        $query .= "ccexp=" . urlencode($ccexp) . "&";
        $query .= "amount=" . urlencode(number_format($amount,2,".","")) . "&";
        $query .= "authorizationcode=" . urlencode($authorizationcode) . "&";
        // Order Information
        $query .= "ipaddress=" . urlencode($this->order['ipaddress']) . "&";
        $query .= "orderid=" . urlencode($this->order['orderid']) . "&";
        $query .= "orderdescription=" . urlencode($this->order['orderdescription']) . "&";
        $query .= "tax=" . urlencode(number_format($this->order['tax'],2,".","")) . "&";
        $query .= "shipping=" . urlencode(number_format($this->order['shipping'],2,".","")) . "&";
        $query .= "ponumber=" . urlencode($this->order['ponumber']) . "&";
        // Billing Information
        $query .= "firstname=" . urlencode($this->billing['firstname']) . "&";
        $query .= "lastname=" . urlencode($this->billing['lastname']) . "&";
        $query .= "company=" . urlencode($this->billing['company']) . "&";
        $query .= "address1=" . urlencode($this->billing['address1']) . "&";
        $query .= "address2=" . urlencode($this->billing['address2']) . "&";
        $query .= "city=" . urlencode($this->billing['city']) . "&";
        $query .= "state=" . urlencode($this->billing['state']) . "&";
        $query .= "zip=" . urlencode($this->billing['zip']) . "&";
        $query .= "country=" . urlencode($this->billing['country']) . "&";
        $query .= "phone=" . urlencode($this->billing['phone']) . "&";
        $query .= "fax=" . urlencode($this->billing['fax']) . "&";
        $query .= "email=" . urlencode($this->billing['email']) . "&";
        $query .= "website=" . urlencode($this->billing['website']) . "&";
        // Shipping Information
        $query .= "shipping_firstname=" . urlencode($this->shipping['firstname']) . "&";
        $query .= "shipping_lastname=" . urlencode($this->shipping['lastname']) . "&";
        $query .= "shipping_company=" . urlencode($this->shipping['company']) . "&";
        $query .= "shipping_address1=" . urlencode($this->shipping['address1']) . "&";
        $query .= "shipping_address2=" . urlencode($this->shipping['address2']) . "&";
        $query .= "shipping_city=" . urlencode($this->shipping['city']) . "&";
        $query .= "shipping_state=" . urlencode($this->shipping['state']) . "&";
        $query .= "shipping_zip=" . urlencode($this->shipping['zip']) . "&";
        $query .= "shipping_country=" . urlencode($this->shipping['country']) . "&";
        $query .= "shipping_email=" . urlencode($this->shipping['email']) . "&";
        $query .= "type=offline";
        return $this->_doPost($query);
    }

    function doCapture($transactionid, $amount =0) {

        $query  = "";
        // Login Information
        $query .= "security_key=" . urlencode($this->login['security_key']) . "&";
        // Transaction Information
        $query .= "transactionid=" . urlencode($transactionid) . "&";
        if ($amount>0) {
            $query .= "amount=" . urlencode(number_format($amount,2,".","")) . "&";
        }
        $query .= "type=capture";
        return $this->_doPost($query);
    }

    function doVoid($transactionid) {

        $query  = "";
        // Login Information
        $query .= "security_key=" . urlencode($this->login['security_key']) . "&";
        // Transaction Information
        $query .= "transactionid=" . urlencode($transactionid) . "&";
        $query .= "type=void";
        return $this->_doPost($query);
    }

    function doRefund($transactionid, $amount = 0) {

        $query  = "";
        // Login Information
        $query .= "security_key=" . urlencode($this->login['security_key']) . "&";
        // Transaction Information
        $query .= "transactionid=" . urlencode($transactionid) . "&";
        if ($amount>0) {
            $query .= "amount=" . urlencode(number_format($amount,2,".","")) . "&";
        }
        $query .= "type=refund";
        return $this->_doPost($query);
    }


    function doRecurringUpdate()
    {
        $query  = "";
//        // Login Information
        $query .= "security_key=" . urlencode($this->login['security_key']) . "&";
        // update subscription
        $query .= "recurring=" . urlencode($this->recurringData['recurring']) . "&";
        $query .= "subscription_id=" . urlencode($this->recurringData['subscription_id']);

        return $this->_doPost($query);

    }
    function doTransactionInfo()
    {
        $query  = "";
//        // Login Information
        $query .= "security_key=" . urlencode($this->login['security_key']) . "&";
        // update subscription
        $query .= "transaction_id=" . urlencode($this->recurringData['transaction_id']) . "&";
        $query .= "subscription_id=" . urlencode($this->recurringData['subscription_id']);

        return $this->_doPost($query);

    }

    function _doPost($query) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->base_url);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

        curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
        curl_setopt($ch, CURLOPT_POST, 1);

        if (!($data = curl_exec($ch))) {
            return 3;
        }
        curl_close($ch);
        unset($ch);
       // print "\n$data\n";

        $data = explode("&",$data);
        for($i=0;$i<count($data);$i++) {
            $rdata = explode("=",$data[$i]);
            $this->responses[$rdata[0]] = $rdata[1];
        }
        return $this->responses['response'];
    }
    function doRecurring()
    {
        // Login Information
        $query_string = "";

        if(!empty($this->recurringData)){
            $query_string .= "security_key=" . urlencode($this->login['security_key']);
            foreach ($this->recurringData as $key => $value){
                $query_string .= "&{$key}=".urlencode($value);
            }
        }

        if(!empty($query_string)){
            return $this->_doPost($query_string);
        }

        return false;

    }

    /**
     * @throws \Exception
     */
    public function prepareData($inputData): array
    {
        if(empty($inputData['order_id'])){
            throw new \Exception('Order id missing');
        }

        if(empty($inputData['order_description'])){
            throw new \Exception('order description missing');
        }

        if(empty($inputData['ip'])){
            throw new \Exception('ip missing');
        }
        $prepareData['first_name'] = $inputData['first_name'];
        $prepareData['last_name'] = $inputData['last_name'];
        $prepareData['company'] = $inputData['company'] ?? config('app.name');
        $prepareData['address1'] = $inputData['street_no'];
        $prepareData['address2'] = $inputData['street_name'];
        $prepareData['city']= $inputData['city'];
        $prepareData['state']= $inputData['state'];
        $prepareData['zip']= $inputData['zip_code'];
        $prepareData['country']= $inputData['country'] ?? 'US';
        $prepareData['phone']= $inputData['phone'];
        $prepareData['fax']= $inputData['fax'] ?? "";
        $prepareData['email']= $inputData['email'];
        $prepareData['website'] = $inputData['website'] ?? "";

        $prepareData['order_id']= $inputData['order_id'];
        $prepareData['order_description']= $inputData['order_description'];
        $prepareData['tax']= 1;
        $prepareData['shipping']= 1;
        $prepareData['ponumber']= "PO1234";
        $prepareData['ip'] = $inputData['ip'];

        $prepareData['amount']= $inputData['amount'];
        $prepareData['card_number']= $inputData['card_number'];
        $prepareData['expiry'] = str_replace("/","",$inputData['expiry']);

        return $prepareData;
    }

    /**
     * @throws \Exception
     */
    public function makePayment($prepareData)
    {
        $result = [];
//        $logData['action'] = "NMI_PAYMENT";
        $this->setLogin(config('app.NMI_SECURITY_KEY'));
/*
        $this->setBilling(
            $prepareData['first_name'],
            $prepareData['last_name'],
            $prepareData['company'],
            $prepareData['address1'],
            $prepareData['address2'],
            $prepareData['city'],
            $prepareData['state'],
            $prepareData['zip'],
            $prepareData['country'],
            $prepareData['phone'],
            $prepareData['fax'],
            $prepareData['email'],
            $prepareData['website']
        );

        $this->setShipping(
            $prepareData['first_name'],
            $prepareData['last_name'],
            $prepareData['company'],
            $prepareData['address1'],
            $prepareData['address2'],
            $prepareData['city'],
            $prepareData['state'],
            $prepareData['zip'],
            $prepareData['country'],
            $prepareData['email']
        );

        $this->setOrder(
            $prepareData['order_id'],
            $prepareData['order_description'],
            $prepareData['tax'],
            $prepareData['shipping'],
            $prepareData['ponumber'], //"PO1234",
            $prepareData['ip']
        );
*/

        $this->preparePaymentData($prepareData);
        $this->doSale();
//        $this->responseDataSample();
        $result['status_code'] = config('constant.API_FAILED_CODE');

        $result['auth_code'] = $this->responses['authcode'] ?? "";
        $result['transaction_id'] = $this->responses['transactionid'] ?? "";
        $result['order_id'] = $this->responses['orderid'] ?? "";
        $result['message'] = $this->responses['responsetext'] ?? "";

        if(isset($this->responses['response_code']) && $this->responses['response_code'] == config('constant.API_SUCCESS_CODE')){
            $result['status_code'] = config('constant.API_SUCCESS_CODE');
        }

//        $logData['data'] = $this->responses;
        $this->logData['NMI_PAYMENT_API_LOG'][$this->pay_log_id]["MAKE_PAYMENT"]= $this->prepareLogData($this->base_url,'POST',$prepareData);

        appLog($this->logData);

        return $result;
    }
    public function makeRecurringPayment($inputData)
    {
        $result=[];
        $result['status'] = false;
        $this->setLogin(config('app.NMI_SECURITY_KEY'));
        $this->prepareRecurringData($inputData);
        $this->doRecurring();

        $result['status_code'] = config('constant.API_FAILED_CODE');

        $result['transaction_status'] = $this->responses['response'] ?? 0;
        $result['transaction_id'] = $this->responses['transactionid'] ?? "";
        $result['subscription_id'] = $this->responses['subscription_id'] ?? "";
        $result['message'] = $this->responses['responsetext'] ?? "";

        if(isset($this->responses['response_code']) && $this->responses['response_code'] == config('constant.API_SUCCESS_CODE'))
        {
            $result['status_code'] = config('constant.API_SUCCESS_CODE');
            $result['status'] = true;
        }

        $this->logData['NMI_RECURRING_API_LOG'][$this->pay_log_id]["MAKE_RECURRING"]= $this->prepareLogData($this->base_url,'POST',$inputData);

        appLog( $this->logData);

        return $result;
    }

    // prepare data for add subscription in existing plan
    public function prepareRecurringData($prepareData)
    {

        /*
           first_name	Cardholder's first name. Legacy variable includes: firstname
           last_name	Cardholder's last name. Legacy variable includes: lastname
           address1	Card billing address.
           city	    Card billing city
           state	    Card billing state.
           zip	        Card billing postal code.
           country	    Card billing country code.
           phone	    Billing phone number.
           email	    Billing email address.
           company	    Cardholder's company.
           address2	Card billing address, line 2.
           fax	Billing fax number.
        */

        // these are mandatory field for CZ

        $this->recurringData['recurring'] = 'add_subscription';
        $this->recurringData['plan_id'] = "creditzombiesplan";
        $this->recurringData['payment'] = "creditcard";
        $this->recurringData['company'] = "Creditzombies";
        $this->recurringData['country'] = "US";

        // these are mandatory field for CZ

        $this->recurringData['ccnumber'] = $prepareData['card_number'];
        $this->recurringData['ccexp'] = $prepareData['expiry'];
        $this->recurringData['first_name'] = $prepareData['first_name'];
        $this->recurringData['last_name'] = $prepareData['last_name'];
        $this->recurringData['address1'] = $prepareData['street_no'];
        $this->recurringData['address2'] = $prepareData['street_name'];
        $this->recurringData['city'] = $prepareData['city'];
        $this->recurringData['state'] = $prepareData['state'];
        $this->recurringData['zip'] = $prepareData['zip_code'];
        $this->recurringData['phone'] = $prepareData['phone'];
        $this->recurringData['email'] = $prepareData['email'];

    }

    private function prepareLogData($url,$method,$request_data){
        if(isset($request_data['ccnumber'])){
              $request_data['ccnumber'] = "*********";
        }
        if(isset($request_data['card_number'])){
            $request_data['card_number'] = "*********";
        }
        if(!empty($request_data['password'])){
            $request_data['password'] = "*********";
        }

        return [
            'request' => [
                'url' => $url,
                'method' => $method,
                'body'=> $request_data,
                'Header'=>[
                    'ContentType' => 'application/x-www-form-urlencoded'
                ]
            ],
            'response' => $this->responses
        ];
    }

    private function getRecurringBySubscriptionId($security_key,$constraints){
        // transactionFields has all of the fields we want to validate
        // in the transaction tag in the XML output
        $transactionFields = array(
            'transaction_id',
            'partial_payment_id',
            'partial_payment_balance',
            'platform_id',
            'transaction_type',
            'condition',
            'order_id',
            'authorization_code',
            'ponumber',
            'order_description',

            'first_name',
            'last_name',
            'address_1',
            'address_2',
            'company',
            'city',
            'state',
            'postal_code',
            'country',
            'email',
            'phone',
            'fax',
            'cell_phone',
            'customertaxid',
            'customerid',
            'website',

            'shipping_first_name',
            'shipping_last_name',
            'shipping_address_1',
            'shipping_address_2',
            'shipping_company',
            'shipping_city',
            'shipping_state',
            'shipping_postal_code',
            'shipping_country',
            'shipping_email',
            'shipping_carrier',
            'tracking_number',
            'shipping_date',
            'shipping',
            'shipping_phone',

            'cc_number',
            'cc_hash',
            'cc_exp',
            'cavv',
            'cavv_result',
            'xid',
            'eci',
            'avs_response',
            'csc_response',
            'cardholder_auth',
            'cc_start_date',
            'cc_issue_number',
            'check_account',
            'check_hash',
            'check_aba',
            'check_name',
            'account_holder_type',
            'account_type',
            'sec_code',
            'drivers_license_number',
            'drivers_license_state',
            'drivers_license_dob',
            'social_security_number',

            'processor_id',
            'tax',
            'currency',
            'surcharge',
            'tip',

            'card_balance',
            'card_available_balance',
            'entry_mode',
            'cc_bin',
            'cc_type'
        );

        // actionFields is used to validate the XML tags in the
        // action element
        $actionFields = array(
            'amount',
            'action_type',
            'date',
            'success',
            'ip_address',
            'source',
            'api_method',
            'username',
            'response_text',
            'batch_id',
            'processor_batch_id',
            'response_code',
            'processor_response_text',
            'processor_response_code',
            'device_license_number',
            'device_nickname'
        );

        $mycurl=curl_init();
        $postStr='security_key='.$security_key.$constraints;
        $url="https://secure.nmi.com/api/query.php?". $postStr;
        curl_setopt($mycurl, CURLOPT_URL, $url);
        curl_setopt($mycurl, CURLOPT_RETURNTRANSFER, 1);
        $responseXML=curl_exec($mycurl);
        curl_close($mycurl);

        $testXmlSimple= new \SimpleXMLElement($responseXML);

        if (!isset($testXmlSimple->transaction)) {
            throw new \Exception('No transactions returned');
        }

        $transNum = 1;
        foreach($testXmlSimple->transaction as $transaction) {
            foreach ($transactionFields as $xmlField) {
                if (!isset($transaction->{$xmlField}[0])){
                    throw new \Exception('Error in transaction_id:'. $transaction->transaction_id[0] .' id  Transaction tag is missing  field ' . $xmlField);
                }
            }
            if (!isset ($transaction->action)) {
                throw new \Exception('Error, Action tag is missing from transaction_id '. $transaction->transaction_id[0]);
            }

            $actionNum = 1;
            foreach ($transaction->action as $action){
                foreach ($actionFields as $xmlField){
                    if (!isset($action->{$xmlField}[0])){
                        throw new \Exception('Error with transaction_id'.$transaction->transaction_id[0].'
                                        Action number '. $actionNum . ' Action tag is missing field ' . $xmlField);
                    }
                }
                $actionNum++;
            }
            $transNum++;
        }

        return $testXmlSimple;
    }

    public function getRecurringInfoBySubscriptionId($inputData){
        $this->responses['data'] = [];
        try {
            $this->setLogin(config('app.NMI_SECURITY_KEY'));
//            $this->login['security_key'] = config('app.NMI_SECURITY_KEY');
            $this->pay_log_id = "LOG_".generateUniqueId();
            $constraints = "&subscription_id={$inputData['subscription_id']}&condition=complete&start_date={$inputData['start_date']}&end_date={$inputData['end_date']}";
            $result = $this->getRecurringBySubscriptionId($this->login['security_key'],$constraints);
            $result_json = json_encode($result);
            $result_json_array = json_decode($result_json,TRUE);
            $this->responses['data'] = $result_json_array['transaction'];
            $this->responses['status_code'] = config('constant.API_SUCCESS_CODE');
            $this->responses['message'] = "Successfully get data.";

        } catch (\Exception $e) {

            $this->responses['message'] = $e->getMessage();
            $this->responses['status_code'] = config('constant.API_FAILED_CODE');

        }
        $this->logData['NMI_PAYMENT_API_LOG'][$this->pay_log_id]["SUBSCRIPTION_UPDATE_FOR_RECURRING"]= $this->prepareLogData($this->base_url,'POST',$inputData);

        appLog( $this->logData);

        return  $this->responses;
    }

    private  function  responseDataSample()
    {
        $data = '{"response": "2","responsetext": "Issuer Declined MCC","authcode": "      ","transactionid": "8105207298",
                             "avsresponse": "Y","cvvresponse": "","orderid": "167760085077649","type": "sale","response_code": "204"
                            }';
        $this->responses = json_decode($data,true);
    }

    public function deleteRecurringPayment($inputData)
    {
        $result = [];
        $result['status'] = false;
        $this->setLogin(config('app.NMI_SECURITY_KEY'));
        $this->prepareDeleteRecurringData($inputData);
        $this->doRecurring();

        $result['status_code'] = config('constant.API_FAILED_CODE');

        $result['transaction_status'] = $this->responses['response'] ?? 0;
        $result['transaction_id'] = $this->responses['transactionid'] ?? "";
        $result['subscription_id'] = $this->responses['subscription_id'] ?? "";
        $result['message'] = $this->responses['responsetext'] ?? "";

        if(isset($this->responses['response_code']) && $this->responses['response_code'] == config('constant.API_SUCCESS_CODE'))
        {
            $result['status_code'] = config('constant.API_SUCCESS_CODE');
            $result['status'] = true;
        }

        $this->logData['NMI_RECURRING_API_LOG'][$this->pay_log_id]["DELETE_MAKE_RECURRING"]= $this->prepareLogData($this->base_url,'POST',$inputData);

        appLog( $this->logData);

        return $result;
    }

    private function prepareDeleteRecurringData($prepareData)
    {
        $this->recurringData['recurring'] = 'delete_subscription';
        $this->recurringData['subscription_id'] = $prepareData['subscription_id'];
    }

}
