<?php
/**
 * Credorax Payments For WooCommerce
 * https://www.credorax.com/
 *
 * @category Credorax
 * @package  WC_Credorax
 * @author   Girit-Interactive (https://www.girit-tech.com/)
 */

 if (! defined('ABSPATH')) {
     exit; // Exit if accessed directly.
 }

/**
 * Credorax Credorax abstract response model.
 */
abstract class WC_Credorax_Model_AbstractResponse extends WC_Credorax_Model_AbstractApi
{
    /**
     * Response result const.
     */
    const STATUS_SUCCESS = 1;
    const STATUS_FAILED = 2;

    const RESPONSE_TYPE_GATEWAY = 'response_type_gateway';
    const RESPONSE_TYPE_PAYMENT = 'response_type_payment';

    /**
     * @var array
     */
    protected $_curlResponse = [];

    /**
     * @var int
     */
    protected $_status;

    /**
     * @var array
     */
    protected $_headers;

    /**
     * @var array
     */
    protected $_body;

    /**
     * @method __construct
     * @param  array       $curlResponse
     */
    public function __construct(
        array $curlResponse
    ) {
        parent::__construct();
        $this->_curlResponse = $curlResponse;
    }

    /**
     * @return AbstractResponse
     * @throws Exception
     */
    public function process()
    {
        $requestStatus = $this->getRequestStatus();

        WC_Credorax_Model_Config::log('AbstractResponse::process() ', 'debug', [
            'response' => $this->prepareResponseData(),
            'status' => $requestStatus === true
                ? self::STATUS_SUCCESS
                : self::STATUS_FAILED,
        ]);

        if ($requestStatus === false) {
            throw new \Exception($this->getErrorMessage());
        }

        $this->validateResponseData();

        return $this;
    }

    /**
     * @return \Magento\Framework\Phrase
     */
    protected function getErrorMessage()
    {
        $errorReason = $this->getErrorReason();
        if ($errorReason !== false && WC_Credorax_Model_Config::isDebugEnabled()) {
            return __(sprintf('Request to payment gateway failed. Details: "%s".', $errorReason), 'woocommerce-gateway-credorax');
        }

        return __('Request to payment gateway failed.', 'woocommerce-gateway-credorax');
    }

    /**
     * @return bool
     */
    protected function getErrorReason()
    {
        $body = $this->getBody();
        if (is_array($body) && !empty($body['z3'])) {
            return $body['z3'];
        }
        return false;
    }

    /**
     * Determine if request succeed or failed.
     *
     * @return bool
     */
    protected function getRequestStatus()
    {
        $httpStatus = $this->getStatus();
        if (!in_array($httpStatus, [100, 200])) {
            return false;
        }

        return true;
    }

    /**
     * @return int
     */
    protected function getRequestId()
    {
        return $this->requestId;
    }

    /**
     * @return int
     */
    protected function getStatus()
    {
        if ($this->_status === null) {
            $this->_status = isset($this->_curlResponse['status'])? $this->_curlResponse['status'] : '';
        }

        return $this->_status;
    }

    /**
     * @return array
     */
    protected function getHeaders()
    {
        if ($this->_headers === null) {
            $this->_headers = isset($this->_curlResponse['headers'])? $this->_curlResponse['headers'] : '';
        }

        return $this->_headers;
    }

    /**
     * @return array
     */
    protected function getBody()
    {
        if ($this->_body === null) {
            $body = isset($this->_curlResponse['body'])? $this->_curlResponse['body'] : '';
            $this->_body = (is_array($body))? $body : json_decode($body, true);
            if ($body && !$this->_body) {
                parse_str($body, $this->_body);
            }
        }

        return $this->_body;
    }

    /**
     * @return array
     */
    protected function prepareResponseData()
    {
        return [
            'response_handler_type' => isset($this->_curlResponse['response_handler_type'])? $this->_curlResponse['response_handler_type'] : null,
            'status' => $this->getStatus(),
            'headers' => $this->getHeaders(),
            'body' => $this->getBody(),
            'error' => isset($this->_curlResponse['error'])? $this->_curlResponse['error'] : null,
        ];
    }

    /**
     * @return AbstractResponse
     * @throws Exception
     */
    protected function validateResponseData()
    {
        $requiredKeys = $this->getRequiredResponseDataKeys();
        $bodyKeys = array_keys($this->getBody());

        $diff = array_diff($requiredKeys, $bodyKeys);
        if (!empty($diff)) {
            throw new Exception(
                __(sprintf(
                    'Credorax required response data fields are missing: %s.',
                    implode(', ', $diff)
                ))
            );
        }

        return $this;
    }

    /**
     * @return array
     */
    protected function getRequiredResponseDataKeys()
    {
        return [];
    }


    public function getDataArray()
    {
        return (array) $this->getBody();
    }


    public function getResponseDataArray()
    {
        return $this->prepareResponseData();
    }

    /**
     * @return string
     */
    abstract public function getResponseType();
}
