<?php

namespace PP\Controllers;

use Curl\Curl;
use PP\Loggers\LocalFileFactory;
use PP\Loggers\LogglyFactory;
use PP\Models\Donation;

/**
 * Interacts with the PandaPay API
 * Extend this class if you need additional functionality
 * or need to modify the internal \Curl\Curl object
 * @link http://docs.pandapay.io/getting-started-pandapay-api/api-reference
 *
 * @note: Be sure to read the security notes on
 * @link https://github.com/php-curl-class/php-curl-class
 * when interacting with CURL!
 *
 * @note: You should only use this API if your server is using HTTPS
 * It is possible to determine your secret API key if not
 *
 * @author  Elly Post <elly@ellytronic.media>
 * @link    https://ellytronic.media
 *
 * @TODO set up customer methods & model
 * @TODO consider breaking this class into a series of classes to avoid god object
 */
class PandaPay {

    const API_URLS = [
    	"DONATIONS" => "https://api.pandapay.io/v1/donations",
	    "CUSTOMERS" => "https://api.pandapay.io/v1/customers"
    ];
    const API_VERSION = "v1";

    protected $curl;
    protected $secretKey;
    protected $log;


    /**
     * Creates a new API wrapper
     * @param String $ppKey the PandaPay API secret key
     * @param [String $ppKey the Loggly API secret key, leave null for local file logging]
     */
    public function __construct(string $ppKey, string $logglyKey = null) {
	    $this->curl = new Curl;
	    if (empty($ppKey)) {
		    throw new \InvalidArgumentException ("No secret key provided");
	    }
	    $this->secretKey = $ppKey;

	    $this->curl->setBasicAuthentication($this->secretKey);

	    if ($logglyKey) {
		    $this->log = LogglyFactory::createStream("PandaPay", $logglyKey);
	    } else {
		    $this->log = LocalFileFactory::createDefault();
	    }

    }

	/**
	 * Sends a donation request to PandaPay
	 * @param Donation $donation the donation object
	 * @throws \Exception on failure
	 * @return Object the JSON response as a PHP object
	 */
	public function sendDonation(Donation $donation) {
		if ($this->log)
			$this->log->info("sendDonation", ["donation" => $donation]);

		$this->curl->post(static::API_URLS["DONATIONS"], [
			'amount'    => $donation->getAmount(),
			'currency'  => $donation->getCurrency(),
			'source'    => $donation->getSource(),
			'receipt_email'      => $donation->getReceiptEmail(),
			'platform_fee'      => $donation->getPlatformFee(),
		]);

		if ($this->curl->error){
			if ($this->log)
				$this->log->error("sendDonation()", [
					"grant" => $donation,
					"error" => $this->getLastError()
				]);

			throw new \Exception($this->getLastError());
		}

		return $this->curl->response;
	}

    /**
     * Sends a grant request to PandaPay
     * @param Donation $donation the donation object
     * @throws \Exception on failure
     * @return Object the JSON response as a PHP object
     */
    public function sendGrant(Donation $donation) {
	    if ($this->log)
		    $this->log->info("sendGrant()", ["grant" => $donation]);

        $this->curl->post(static::API_URLS["DONATIONS"], [
            'amount'    => $donation->getAmount(),
            'currency'  => $donation->getCurrency(),
            'source'    => $donation->getSource(),
            'receipt_email'      => $donation->getReceiptEmail(),
            'platform_fee'      => $donation->getPlatformFee(),

            // Per PandaPay API Docs:
            // Note: If for some reason destination_ein
            // fails to produce the intended behaviour,
            // try using the parameter destination in your request.
//            'destination_ein'   => $donation->getDestinationEIN(),
            'destination'  => $donation->getDestinationEIN() 
        ]);

	    if ($this->curl->error){
		    if ($this->log)
			    $this->log->error("sendGrant()", [
				    "grant" => $donation,
				    "error" => $this->getLastError()
			    ]);

		    throw new \Exception($this->getLastError());
	    }

        return $this->curl->response;
    }

    /**
     * Gets the request headers
     * @return String[] responseHeaders[data, keys]
     */
    public function getRequestHeaders()
    {
        return $this->curl->requestHeaders;
    }

    /**
     * Gets the response headers
     * @return String[] responseHeaders[data, keys]
     */
    public function getResponseHeaders()
    {
        return $this->curl->responseHeaders;
    }

	/**
	 * Gets the response status code
	 * @return int the status code
	 */
	public function getResponseStatusCode()
	{
		return $this->curl->httpStatusCode;
	}

    /**
     * Gets the last curl error
     * @return String the error
     */
    public function getLastError()
    {
        return 'Error: ' . $this->curl->errorCode . ': ' . $this->curl->errorMessage;
    }
}
