<?php
/**
  * Ahead WebSoft Technologies Pvt Ltd.
  * @copyright  Copyright 2006-2026 Ahead WebSoft Technologies Pvt Ltd.
  * @license    https://www.socialengine.com/policies
*/


include_once APPLICATION_PATH . "/application/libraries/Engine/Service/Coinpayment/vendor/autoload.php";
require_once APPLICATION_PATH . '/application/libraries/Engine/Service/Coinpayment/src/Helpers/ApiHelper.php';
require_once APPLICATION_PATH . '/application/libraries/Engine/Service/Coinpayment/src/Helpers/QrCodeHelper.php';

use CoinPaymentsApiExamples\Helpers\ApiHelper;
use CoinPaymentsApiExamples\Helpers\QrCodeHelper;
use Endroid\QrCode\Color\Color;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\Writer\PngWriter;

class Payment_Plugin_Gateway_Coinpayment extends Engine_Payment_Plugin_Abstract {

  protected $_gatewayInfo;
  protected $_gateway;
  
  // General

  /**
   * Constructor
   */
  public function __construct(Zend_Db_Table_Row_Abstract $gatewayInfo)
  {
      $this->_gatewayInfo = $gatewayInfo;
  }

  /**
   * Get the service API
   *
   * @return Engine_Service_PayPal
   */
  public function getService()
  {
    return $this->getGateway()->getService();
  }

  /**
   * Get the gateway object
   *
   * @return Engine_Payment_Gateway
   */
  public function getGateway()
  {
    // var_dump((array) $this->_gatewayInfo);die;
    if( null === $this->_gateway ) {
      $class = 'Engine_Payment_Gateway_Coinpayment';
      Engine_Loader::loadClass($class);
      $gateway = new $class(array(
        'config' => (array) $this->_gatewayInfo->config,
        'testMode' => $this->_gatewayInfo->test_mode,
        'currency' => Engine_Api::_()->getApi('settings', 'core')->getSetting('payment.currency', 'USD'),
      ));
      if( !($gateway instanceof Engine_Payment_Gateway) ) {
        throw new Engine_Exception('Plugin class not instance of Engine_Payment_Gateway');
      }
      $this->_gateway = $gateway;
    }

    return $this->_gateway;
  }

  // Actions
  /**
   * Create a transaction object from specified parameters
   *
   * @return Engine_Payment_Transaction
   */
  public function createTransaction(array $params)
  {
    $transaction = new Engine_Payment_Transaction($params);
    $transaction->process($this->getGateway());
    return $transaction;
  }

  /**
   * Create an ipn object from specified parameters
   *
   * @return Engine_Payment_Ipn
   */
  public function createIpn(array $params)
  {
    $ipn = new Engine_Payment_Ipn($params);
    $ipn->process($this->getGateway());
    return $ipn;
  }

  // SEv4 Specific
  
  /**
   * Create a transaction for a subscription
   *
   * @param User_Model_User $user
   * @param Zend_Db_Table_Row_Abstract $subscription
   * @param Zend_Db_Table_Row_Abstract $package
   * @param array $params
   * @return Engine_Payment_Gateway_Transaction
   */
  public function createSubscriptionTransaction(User_Model_User $user, Zend_Db_Table_Row_Abstract $subscription, Payment_Model_Package $package, array $params = array()) {

		// Process description
    $desc = $package->getPackageDescription();
    if( strlen($desc) > 127 ) {
      $desc = substr($desc, 0, 124) . '...';
    } else if( !$desc || strlen($desc) <= 0 ) {
      $desc = 'N/A';
    }
    if( function_exists('iconv') && strlen($desc) != iconv_strlen($desc) ) {
      // PayPal requires that DESC be single-byte characters
      $desc = @iconv("UTF-8", "ISO-8859-1//TRANSLIT", $desc);
    }
    
    $currentCurrency = Engine_Api::_()->payment()->getCurrentCurrency();
    $defaultCurrency = Engine_Api::_()->payment()->defaultCurrency();
    $currencyChangeRate = 1;
    if ($currentCurrency != $defaultCurrency) {
      $currencyData = Engine_Api::_()->getDbTable('currencies', 'payment')->getCurrency($currentCurrency);
      $currencyChangeRate = $currencyData->change_rate;
    }
    $price = $amount = @round(($package->price * $currencyChangeRate), 2);

		// This is a one-time fee
    if( $package->isOneTime() ) {

			$cps_api = new CoinpaymentsAPI($this->_gatewayInfo->config['private_key'], $this->_gatewayInfo->config['public_key'], 'json');

			$buyer_email = $user->email;
			$address = "";
			$item_name = $desc;
			$item_number = "";
			$custom = '';
			$invoice = '';
			$currency2 = $params["currency"];
			$buyer_name = $user->getTitle();

			$view = Zend_Registry::isRegistered('Zend_View') ? Zend_Registry::get('Zend_View') : null;
			
			$ipn_url = 'https://' . $_SERVER['HTTP_HOST'] . Zend_Controller_Front::getInstance()->getRouter()->assemble(array('module' => 'coinpayments', 'controller' => 'ipn', 'action' => 'index', 'order_id' => $params["order_id"]), 'default', true);

			$success_url = 'https://' . $_SERVER['HTTP_HOST'] . Zend_Controller_Front::getInstance()->getRouter()->assemble(array(), 'default', true);

			$cancel_url = 'https://' . $_SERVER['HTTP_HOST'] . Zend_Controller_Front::getInstance()->getRouter()->assemble(array(), 'default', true);
	
			
      // Your keys (from config/db)
      $clientId = $this->_gatewayInfo->config['public_key'];
      $clientSecret = $this->_gatewayInfo->config['private_key'];

      // Init API
      $apiHelper = new ApiHelper($clientId, $clientSecret);
      $payload = [
        "invoiceId" => $params["order_id"],
        "ipn_url" => $ipn_url,
        "success_url" => $success_url,
        "cancel_url" => $cancel_url,
        "items" => [
          [
            "name" => $item_name,
            "quantity" => [
              "value" => 1,
              "type" => 2
            ],
            "originalAmount" => (string) $amount,
            "amount" => (string) $amount
          ]
        ],
        "amount" => [
          "total" => (string) $amount
        ],
        "currency" => $currentCurrency,
        "payment" => [
          "refundEmail" => $buyer_email
        ]
      ];


      try {
        $transaction_response = $apiHelper->sendApiRequest(
          'POST',
          '/api/v2/merchant/invoices',
          $payload
        );
      } catch (Exception $e) {
        throw $e;
      }
      if (!empty($transaction_response['invoices']) && !empty($transaction_response['invoices'][0]) &&  !empty($transaction_response['invoices'][0]['id'])) {
        // Success!
      } else {

        // Something went wrong!
        $errors = "";
        if (!empty($transaction_response['errors'])) {
          foreach ($transaction_response['errors'] as $error) {
            $errors .= "Error: " . $error[0] . "\n";
          }
        }
        throw new Engine_Payment_Plugin_Exception($errors);
      }

			return $transaction_response;
		}
  }
  
  /**
   * Process return of subscription transaction
   *
   * @param Payment_Model_Order $order
   * @param array $params
   */
  public function onSubscriptionTransactionReturn(Payment_Model_Order $order, array $params = array())
  {
  }
  
  /**
   * Process ipn of subscription transaction
   *
   * @param Payment_Model_Order $order
   * @param Engine_Payment_Ipn $ipn
   */
  public function onSubscriptionTransactionIpn(
  Payment_Model_Order $order, Engine_Payment_Ipn $ipn) {

  }
  

  /**
   * Cancel a subscription (i.e. disable the recurring payment profile)
   *
   * @params $transactionId
   * @return Engine_Payment_Plugin_Abstract
   */
  public function cancelSubscription($transactionId, $note = null)
  {
    return $this;
  }
  
  /**
   * Generate href to a page detailing the order
   *
   * @param string $transactionId
   * @return string
   */
  public function getOrderDetailLink($orderId)
  {
    return 'https://www.coinpayments.net/index.php?cmd=acct_pmt_details&id=' . $orderId;
  }

  /**
   * Generate href to a page detailing the transaction
   *
   * @param string $transactionId
   * @return string
   */
  public function getTransactionDetailLink($transactionId)
  {
    
    return 'https://www.coinpayments.net/index.php?cmd=acct_pmt_details&id=' . $transactionId;
  }

  /**
   * Get raw data about an order or recurring payment profile
   *
   * @param string $orderId
   * @return array
   */
  public function getOrderDetails($orderId)
  {
    try {
      return $this->getService()->detailRecurringPaymentsProfile($orderId);
    } catch( Exception $e ) {
      echo $e;
    }

    try {
      return $this->getTransactionDetails($orderId);
    } catch( Exception $e ) {
      echo $e;
    }

    return false;
  }

  /**
   * Get raw data about a transaction
   *
   * @param $transactionId
   * @return array
   */
  public function getTransactionDetails($transactionId)
  {
    return $this->getService()->detailTransaction($transactionId);
  }
  
  // Forms

  /**
   * Get the admin form for editing the gateway info
   *
   * @return Engine_Form
   */
  public function getAdminGatewayForm(){
    return new Coinpayments_Form_Admin_Gateway_Coinpayment();
  }

  public function processAdminGatewayForm(array $values){
    return $values;
  }
  
  // IPN
  /**
   * Process an IPN
   *
   * @param Engine_Payment_Ipn $ipn
   * @return Engine_Payment_Plugin_Abstract
   */
  public function onIpn(Engine_Payment_Ipn $ipn) {}
  
  
  // IPN
  /**
   * Process an IPN
   *
   * @param Payment_Model_Order $order
   * @return Engine_Payment_Plugin_Abstract
   */
  public function onTransactionIpn(Payment_Model_Order $order,  $rawData) {

		// Check that gateways match
		if( $order->gateway_id != $this->_gatewayInfo->gateway_id ) {
			throw new Engine_Payment_Plugin_Exception('Gateways do not match');
		}

		// Get related info
		$user = $order->getUser();
		$subscription = $order->getSource();
		$package = $subscription->getPackage();

		// Process description
		$desc = $package->getPackageDescription();
		if( strlen($desc) > 127 ) {
			$desc = substr($desc, 0, 124) . '...';
		} else if( !$desc || strlen($desc) <= 0 ) {
			$desc = 'N/A';
		}
		if( function_exists('iconv') && strlen($desc) != iconv_strlen($desc) ) {
			// PayPal requires that DESC be single-byte characters
			$desc = @iconv("UTF-8", "ISO-8859-1//TRANSLIT", $desc);
		}

		$current_currency = strtoupper($rawData['currency1']);
    $currencyChangeRate = 1;
    $defaultCurrency = Engine_Api::_()->payment()->defaultCurrency();
    if ($current_currency != $defaultCurrency) {
      $currencyData = Engine_Api::_()->getDbTable('currencies', 'payment')->getCurrency($current_currency);
      $currencyChangeRate = $currencyData->change_rate;
    }
    $price = @round(($rawData["amount1"] / $currencyChangeRate), 2);

		$paymentStatus = 'okay';
		$orderStatus = 'complete';

		if($package->isOneTime()) {

			// Update order with profile info and complete status?
			$order->state = $orderStatus;
			$order->gateway_transaction_id = $rawData['txn_id'];
			$order->save();

			// Insert transaction
			$transactionsTable = Engine_Api::_()->getDbtable('transactions', 'payment');
			$transactionsTable->insert(array(
				'user_id' => $order->user_id,
				'gateway_id' => $this->_gatewayInfo->gateway_id,
				'timestamp' => new Zend_Db_Expr('NOW()'),
				'order_id' => $order->order_id,
				'type' => 'payment',
				'state' => $paymentStatus,
				'gateway_transaction_id' => $rawData['txn_id'],
				'amount' => $package->price, // @todo use this or gross (-fee)?
				'currency' => Engine_Api::_()->payment()->defaultCurrency(),
				'change_rate' => $currencyChangeRate, //currency change rate according to default currency
				'current_currency' => strtoupper($rawData["currency1"]), //currency which is user paid
			));
			$transaction_id = $transactionsTable->getAdapter()->lastInsertId();
			$transaction = Engine_Api::_()->getItem('payment_transaction', $transaction_id);
			
			// Get benefit setting
			$giveBenefit = Engine_Api::_()->getDbtable('transactions', 'payment')
					->getBenefitStatus($user);

			// Check payment status
			if( $paymentStatus == 'okay' ||
					($paymentStatus == 'pending' && $giveBenefit) ) {
			
				// Update subscription info
				$subscription->gateway_id = $this->_gatewayInfo->gateway_id;
				// $subscription->gateway_profile_id = $transaction->id;

				// Payment success
				$subscription->onPaymentSuccess();

				//Save subscription id in transaction id
				$transaction->expiration_date = $subscription->expiration_date;
				$transaction->subscription_id = $subscription->subscription_id;
				$transaction->save();
				
				//save in subscription table table
				if($order) {
					$subscription->order_id = $order->order_id;
					$subscription->resource_type = $order->source_type;
					$subscription->resource_id = $order->source_id;
					$subscription->save();
				}

				// send notification
				//if( $subscription->didStatusChange() ) {
					Engine_Api::_()->getApi('mail', 'core')->sendSystem($user, 'payment_subscription_active', array(
						'subscription_title' => $package->title,
						'subscription_description' => $package->description,
						'subscription_terms' => $package->getPackageDescription(),
						'object_link' => 'http://' . $_SERVER['HTTP_HOST'] .
								Zend_Controller_Front::getInstance()->getRouter()->assemble(array(), 'user_login', true),
					));
				//}
				return 'active';
			}
			else if( $paymentStatus == 'pending' ) {

				// Update subscription info
				$subscription->gateway_id = $this->_gatewayInfo->gateway_id;
				$subscription->gateway_profile_id = $transaction->id;
				
				// Payment pending
				$subscription->onPaymentPending();
				
				// send notification
				//if( $subscription->didStatusChange() ) {
					Engine_Api::_()->getApi('mail', 'core')->sendSystem($user, 'payment_subscription_pending', array(
						'subscription_title' => $package->title,
						'subscription_description' => $package->description,
						'subscription_terms' => $package->getPackageDescription(),
						'object_link' => 'http://' . $_SERVER['HTTP_HOST'] .
								Zend_Controller_Front::getInstance()->getRouter()->assemble(array(), 'user_login', true),
					));
				//}

				return 'pending';
			}
		}
  }
  
  function setConfig($params) {
    
  }
  
  function test() {
  
  }
}
