<?php

namespace Omnipay\AuthorizeNet\Message\Query;

use Omnipay\Common\Exception\InvalidResponseException;
use Omnipay\Common\Message\AbstractRequest;
use Omnipay\Omnipay;

/**
 * Authorize.Net AIM Response
 */
class QueryDetailResponse extends AbstractQueryResponse
{
    protected $planResponse;

    public function __construct(AbstractRequest $request, $data)
    {
        // Strip out the xmlns junk so that PHP can parse the XML
        $xml = preg_replace('/<getTransactionDetailsRequest[^>]+>/', '<getTransactionDetailsRequest>', (string)$data);

        try {
            $xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOWARNING);
        } catch (\Exception $e) {
            throw new InvalidResponseException();
        }

        if (!$xml) {
            throw new InvalidResponseException();
        }

        parent::__construct($request, $xml);
        $this->transaction = $this->xml2array($this->data->transaction, true);
    }

    public function isSuccessful()
    {
        return 1 == $this->getResultCode();
    }


    public function isRecurring()
    {
        return ($this->transaction['recurringBilling'] === 'true');
    }

    public function getClientIp()
    {
        return $this->transaction['customerIP'];
    }

    /**
     * TransactionReference is the reference generated by the payment gateway.
     *
     * @return mixed
     */
    public function getTransactionReference()
    {
        return $this->transaction['transId'];
    }

    /**
     * TransactionId is the reference set by the originating website.
     *
     * @return mixed
     */
    public function getTransactionId()
    {
        return $this->transaction['order'][0]['invoiceNumber'];
    }

    public function getAmount()
    {
        return $this->transaction['settleAmount'];
    }

    public function getDescription()
    {
        return $this->transaction['order'][0]['description'];
    }

    /**
     * Get email.
     *
     * @return string
     */
    public function getEmail()
    {
        return $this->transaction['customer'][0]['email'];
    }

    public function getResultCode()
    {
        return $this->transaction['responseCode'];
    }

    /**
     * Get the currency.
     *
     * Seems to onlys support USD.
     *
     * @return string
     */
    public function getCurrency()
    {
        return 'USD';
    }

    /**
     * Get first name.
     *
     * In practice this is billing first name.
     *
     * @return string
     */
    public function getFirstName()
    {
        return $this->transaction['billTo'][0]['firstName'];
    }

    /**
     * Get the gateway generated id for the recurring transaction.
     */
    public function getRecurringReference()
    {
        return $this->transaction['subscription'][0]['id'];
    }

    /**
     * Get the gateway generated id for the recurring transaction.
     */
    public function getCustomerReference()
    {
        if (!$this->isRecurring()) {
            return '';
        }
        if (!$this->planResponse) {
            /** @var \Omnipay\AuthorizeNet\AIMGateway $gateway */
            $gateway = Omnipay::create('AuthorizeNet_AIM');
            $gateway->setApiLoginId($this->request->getApiLoginId());
            $gateway->setHashSecret($this->request->getHashSecret());
            $gateway->setTransactionKey($this->request->getTransactionKey());
            $data = array('recurringReference' => $this->getRecurringReference());
            $this->planResponse = $gateway->paymentPlanQuery($data)->send();
        }
        return $this->planResponse->getContactReference();
    }

    /**
     * Get last name.
     *
     * In practice this is billing last name.
     *
     * @return string
     */
    public function getLastName()
    {
        return $this->transaction['billTo'][0]['lastName'];
    }

    /**
     * Get credit card number.
     *
     * This is masked. Is this the correct parameter name.
     */
    public function getNumber()
    {
        return $this->transaction['payment'][0]['creditCard'][0]['cardNumber'];
    }

    public function getType()
    {
        return $this->transaction['payment'][0]['creditCard'][0]['cardType'];
    }

    public function getBillingAddress1()
    {
        return $this->transaction['billTo'][0]['address'];
    }

    public function getBillingAddress2()
    {
        return '';
    }

    public function getBillingCity()
    {
        return $this->transaction['billTo'][0]['city'];
    }

    public function getBillingPostcode()
    {
        return $this->transaction['billTo'][0]['zip'];
    }

    /**
     * Get billing address State.
     *
     * @todo consider if there should be other variants for full vs abbreviation.
     *
     * @return mixed
     */
    public function getBillingState()
    {
        return $this->transaction['billTo'][0]['state'];
    }

    /**
     * Get billing address Country.
     *
     * @todo consider if there should be other variants for full vs abbreviation.
     *
     * @return mixed
     */
    public function getBillingCountry()
    {
        return $this->transaction['billTo'][0]['country'];
    }

    /**
     * Get transaction date in UTC.
     *
     * @return string
     */
    public function getSettlementDate()
    {
        return $this->transaction['batch'][0]['settlementTimeUTC'];
    }

    /**
     * Get settlement date in UTC.
     *
     * @return string
     */
    public function getTransactionDate()
    {
        return $this->transaction['submitTimeUTC'];
    }
}
