<?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_Wallet_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()
  {
    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 createWalletTransaction(User_Model_User $user, array $params = array())
  {
    $recurrence = $params['recurrence'];
    $price = $params['price'];
    $desc = Engine_Api::_()->payment()->getPackageDescription(json_decode($recurrence), $price, 'wallet');
    if (strlen($desc) > 127) {
      $desc = substr($desc, 0, 124) . '...';
    } else if (!$desc || strlen($desc) <= 0) {
      $desc = 'N/A';
    }
    //Multiple currency
    $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;
    }
    $amount = @round(($price), 2);
    $buyer_email = $user->email;
    $item_name = $desc;
    $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;
  }

  // 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 return of subscription transaction
   *
   * @param Payment_Model_Order $order
   * @param array $params
   */
  public function onSubscriptionTransactionReturn(
    Payment_Model_Order $order,
    array $params = array()
  ) {}

  /**
   * Process return of subscription transaction
   *
   * @param Payment_Model_Order $order
   * @param array $params
   */
  public function onWalletTransactionReturn(Payment_Model_Order $order, array $params = array())
  {

    // 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();

    $subscriptionParams = json_decode($subscription->params);
    $recurrence = $subscriptionParams->recurrence;

    //Change rate according to default currency and selected currency by member

    $currencyChangeRate = 1;
    $current_currency = Engine_Api::_()->payment()->getCurrentCurrency();
    $defaultCurrency = Engine_Api::_()->payment()->defaultCurrency();
    if ($current_currency != $defaultCurrency) {
      $currencyData = Engine_Api::_()->getDbTable('currencies', 'payment')->getCurrency($current_currency);
      $currencyChangeRate = $currencyData->change_rate;
    }
    $price = @round((($subscriptionParams->price) / $currencyChangeRate), 2);

    // description
    $desc = Engine_Api::_()->payment()->getPackageDescription($recurrence, $subscriptionParams->price, 'wallet');
    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);
    }

    // expiration_date
    $expiration_date = date('Y-m-d H:i:s', Engine_Api::_()->payment()->getExpirationDate($recurrence));
    if ($expiration_date == '1970-01-01 00:00:00') {
      $expiration_date = '2099-12-30 00:00:00';
    }

    //Check subscription state
    $paymentStatus = 'okay';
    $orderStatus = 'complete';

    //     // Check subscription state
    //     if( $subscription->status == 'trial') {
    //       return 'active';
    //     } else if( $subscription->status == 'pending' ) {
    //       return 'pending';
    //     }
    // Check for cancel state - the user cancelled the transaction
    if ($params['state'] == 'cancel') {
      // Cancel order and subscription?
      $order->onCancel();
      $subscription->onPaymentFailure();
      // Error
      throw new Payment_Model_Exception('Your payment has been cancelled and ' .
        'not been charged. If this is not correct, please try again later.');
    }

    // One-time
    if (Engine_Api::_()->payment()->isOneTime($recurrence)) {


      // Update order with profile info and complete status?
      $order->state = $orderStatus;
      $order->gateway_transaction_id = $params['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' => 'wallet recharge',
        'state' => $paymentStatus,
        'gateway_transaction_id' => $params['txn_id'],
        'amount' => $price, // @todo use this or gross (-fee)?
        'currency' => Engine_Api::_()->payment()->defaultCurrency(), //strtoupper($transaction->currency),
        'change_rate' => $currencyChangeRate, //currency change rate according to default currency
        'current_currency' => strtoupper($transaction->currency), //currency which is user paid
      ));
      $transaction_id = $transactionsTable->getAdapter()->lastInsertId();

      // Check payment status
      if (
        $paymentStatus == 'okay' ||
        ($paymentStatus == 'pending')
      ) {

        // Update subscription info
        //$subscription->gateway_id = $this->_gatewayInfo->gateway_id;
        //$subscription->gateway_profile_id = $rdata['PAYMENTINFO'][0]['TRANSACTIONID'];

        $subscription->transaction_id = $transaction_id;
        $subscription->save();

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

        // send notification
        if ($subscription->didStatusChange()) {

          //Notification Work
          $translate = Zend_Registry::get('Zend_Translate');
          $walletlink = 'http://' . $_SERVER['HTTP_HOST'] . Zend_Controller_Front::getInstance()->getRouter()->assemble(array('module' => 'payment', 'controller' => 'settings', 'action' => 'wallet'), 'default', true);
          $walletlink = '<a href="' . $walletlink . '" >' . $translate->translate("wallet") . '</a>';

          Engine_Api::_()->getDbTable('notifications', 'activity')->addNotification($user, $user, $user, 'payment_wallet_active', array('payment_method' => 'Cryptocurrency Payment', 'walletlink' => $walletlink));

          //Email work
          Engine_Api::_()->getApi('mail', 'core')->sendSystem($user, 'payment_wallet_active', array(
            'wallet_terms' => $desc,
            'object_link' => 'https://' . $_SERVER['HTTP_HOST'] . Zend_Controller_Front::getInstance()->getRouter()->assemble(array("module" => 'payment', 'controller' => "settings", "action" => "wallet"), 'default', true),
          ));
        }
        return 'active';
      } else if ($paymentStatus == 'pending') {

        // Update subscription info
        $subscription->gateway_id = $this->_gatewayInfo->gateway_id;
        $subscription->gateway_profile_id = $params['txn_id'];

        // Payment pending
        $subscription->onPaymentPending();

        // send notification
        if ($subscription->didStatusChange()) {
          Engine_Api::_()->getApi('mail', 'core')->sendSystem($user, 'payment_wallet_pending', array(
            'wallet_terms' => $desc,
            'object_link' => 'https://' . $_SERVER['HTTP_HOST'] . Zend_Controller_Front::getInstance()->getRouter()->assemble(array("module" => 'payment', 'controller' => "settings", "action" => "wallet"), 'default', true),
          ));
        }

        return 'pending';
      } else if ($paymentStatus == 'failed') {
        // Cancel order and subscription?
        $order->onFailure();
        $subscription->onPaymentFailure();
        // Payment failed
        throw new Payment_Model_Exception('Your payment could not be ' .
          'completed. Please ensure there are sufficient available funds ' .
          'in your account.');
      } else {
        // This is a sanity error and cannot produce information a user could use
        // to correct the problem.
        throw new Payment_Model_Exception('There was an error processing your ' .
          'transaction. Please try again later.');
      }
    }
  }

  /**
   * Process ipn of subscription transaction
   *
   * @param Payment_Model_Order $order
   * @param Engine_Payment_Ipn $ipn
   */
  public function onWalletTransactionIpn(Payment_Model_Order $order, Engine_Payment_Ipn $ipn) {}

  /**
   * 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();

    $subscriptionParams = json_decode($subscription->params);
    $recurrence = $subscriptionParams->recurrence;
    $subscription_id = $subscriptionParams->subscription_id;


    $desc = Engine_Api::_()->payment()->getPackageDescription($recurrence, $subscriptionParams->price, 'wallet');
    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);
    }

    $paymentStatus = 'okay';
    $orderStatus = 'complete';
  
    $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);

    // 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' => 'wallet recharge',
      'state' => $paymentStatus,
      'gateway_transaction_id' => $rawData["txn_id"],
      'amount' => $price, // @todo use this or gross (-fee)?
      'currency' => Engine_Api::_()->payment()->defaultCurrency(), //strtoupper($transaction->currency),
      '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();

    $subscription->transaction_id = $transaction_id;
    $subscription->save();

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

    // Payment success
    $subscription->onPaymentSuccess();
    $walletSession = new Zend_Session_Namespace('Payment_Wallet');
    $walletSession->unsetAll();
    // send notification
    // if( $subscription->didStatusChange() ) {
    //Notification Work
    $translate = Zend_Registry::get('Zend_Translate');
    $walletlink = 'http://' . $_SERVER['HTTP_HOST'] . Zend_Controller_Front::getInstance()->getRouter()->assemble(array('module' => 'payment', 'controller' => 'settings', 'action' => 'wallet'), 'default', true);
    $walletlink = '<a href="' . $walletlink . '" >' . $translate->translate("wallet") . '</a>';

    Engine_Api::_()->getDbTable('notifications', 'activity')->addNotification($user, $user, $user, 'payment_wallet_active', array('payment_method' => 'Cryptocurrency Payment', 'walletlink' => $walletlink));

    //Email work
    Engine_Api::_()->getApi('mail', 'core')->sendSystem($user, 'payment_wallet_active', array(
      'wallet_terms' => $desc,
      'object_link' => 'https://' . $_SERVER['HTTP_HOST'] . Zend_Controller_Front::getInstance()->getRouter()->assemble(array("module" => 'payment', 'controller' => "settings", "action" => "wallet"), 'default', true),
    ));

    if(!empty($subscription_id)) {
      if($user) {
        Engine_Api::_()->payment()->firsttimeSignupSubscription($user);
      }
    }

    return 'active';
    // }

    return $this;
  }

  function setConfig($params) {}

  function test() {}
}
