<?php

namespace frontend\controllers;

use Yii;
use yii\web\Controller;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use yii\helpers\Url;
use common\components\Sanitize;
use common\components\payment\provider\ToyyibPay;
use common\components\payment\PaymentProxy;
use backend\modules\payment\models\Payment;
use backend\modules\payment\models\PaymentCallback;
use backend\modules\subscription\models\Subscription;
use backend\modules\fruserdynav2\models\FrontendUser;

class PaymentController extends Controller {

    /**
     * @inheritdoc
     */
    public function beforeAction($action) {
        if ($action->id == 'pay-callback') {
            $this->enableCsrfValidation = false;
        }
        if ($action->id == 'pay') {
            $this->enableCsrfValidation = false;
        }
        return parent::beforeAction($action);
    }

    /**
     * @inheritdoc
     */
    public function behaviors() {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'payment-redirect' => ['POST'],
                    'pay' => ['POST']
                ],
            ],
        ];
    }

    public function actionPay() {

        try {
            $post = Yii::$app->request->post();

            $model = new Payment();
            $model->load($post);
            $model->payment_frontend_user_id = Yii::$app->user->id;
            $model->payment_status = 'pendingpay';

            $model->created_at = date("Y-m-d H:i:s");
            $model->created_by = Yii::$app->user->identity->id;
            $model->created_user_type = 'frontend_user';
            $model->updated_at = date("Y-m-d H:i:s");
            $model->updated_by = Yii::$app->user->identity->id;
            $model->updated_user_type = 'frontend_user';

            if (empty($model->payment_hash)) {
                Yii::$app->response->statusCode = 500;
                return '-- Error - Mising Required Parameter --';
            }

            // secret key
            $params = Yii::$app->params['payment_gateway'];
            $secret = $params['toyyibpay']['secret'];
            $category = $params['toyyibpay']['category']['GENERAL_FEE'];

            // check for hash
            $payload = Yii::$app->user->id . $model->payment_data_id . $model->payment_total . $model->payment_method . $model->payment_date;
            $hash = PaymentProxy::generateHash($payload, $secret);
            $check = PaymentProxy::checkHash($hash, $model->payment_hash);

            if (!$check) {
                Yii::$app->response->statusCode = 500;
                return '-- Error - Mismatch payment data --';
            }

            Yii::$app->db->transaction(function($db) use (&$model, &$secret, &$category, &$hash) {

                if (!$model->save()) {
                    throw new \Exception('Error when saving payment application');
                }

                // order id
                $order_id = PaymentProxy::shorten($hash, str_pad($model->payment_id, 10, 0, STR_PAD_LEFT));

                //user 
                $user = Yii::$app->user->identity;

                // toyyib pay
                $toyyib = new ToyyibPay($secret, $category);

                //set enviroment
                $toyyib->environment('dev');

                // params
                $toyyib->setPayParam('billName', 'Fee Payment');
                $toyyib->setPayParam('billDescription', 'Fee Payment for Renewal / Registration');
                $toyyib->setPayParam('billPriceSetting', '1');
                $toyyib->setPayParam('billPayorInfo', 1);
                $toyyib->setPayParam('billReturnUrl', Url::base(true) . '/portal-main/fpx-status');
                $toyyib->setPayParam('billCallbackUrl', Url::base(true) . '/payment/pay-callback');
                $toyyib->setPayParam('billExternalReferenceNo', $order_id);
                $toyyib->setPayParam('billTo', $user->fullname);
                $toyyib->setPayParam('billEmail', $user->email);
                $toyyib->setPayParam('billPhone', $user->mobile_no);
                $toyyib->setPayParam('billPaymentChannel', 2);

                if (empty($toyyib->getErrors())) {
                    $payment = new PaymentProxy($toyyib);
                    $response = $payment->pay($model->payment_total);
                    //$response = $payment->result_array();

                    if ($response) {
                        //success create bill
                        $pay = Payment::findOne($model->payment_id);
                        $pay->payment_gateway_code = $response['billCode'];
                        $pay->payment_gateway_order_id = $order_id;
                        $pay->save();

                        $url = $response['baseUrl'] . '/' . $response['billCode'];
                        $this->redirect($url);
                    } else {
                        throw new \Exception('Failed to process payment to the gateway');
                    }
                } else {
                    throw new \Exception('Error in validation');
                }
            });
        } catch (\Throwable $t) {
            Yii::$app->response->statusCode = 500;
            echo '-- THERE AN ERROR PROCCESING PAYMENT-- [' . $t->getMessage() . ']';
        }
    }

    public function actionPayCallback() {

        try {
            $post = Yii::$app->request->post();

            /** track * */
            $call = new PaymentCallback();
            $call->post = json_encode($post);
            $call->url = Url::to();
            $call->get = json_encode(Yii::$app->request->get());
            $call->save();

            $post = Sanitize::cast_arr($post, [
                        'refno' => 'string',
                        'status' => 'int',
                        'reason' => 'string',
                        'billcode' => 'string',
                        'order_id' => 'string',
                        'amount' => 'float',
                        'transaction_time' => 'string'
            ]);

            extract($post);

            if (!isset($order_id) || !isset($amount)) {
                throw new \Exception('Missing Required Parameter.');
            }

            // check is hash exist
            $pay = Payment::find()->where(['payment_gateway_order_id' => $order_id])->one();

            if (empty($pay)) {
                throw new \Exception('Order id supplied is not found.');
            }

            //chek if amount is the same
            if ((float) $pay->payment_total != (float) ($amount * 100)) {
                throw new \Exception('Invalid amount.');
            }

            /** receipt * */
            $receipt = PaymentProxy::generateReceiptNo($pay->payment_id, $pay->payment_frontend_user_id);
            $pay->payment_receipt_no = $receipt;

            // payment status

            if ((int) $status === 1) {
                $statuslabel = 'verified';
            } else if ((int) $status === 2) {
                $statuslabel = 'pending';
            } else if ((int) $status === 3) {
                $statuslabel = 'failed';
            } else {
                $statuslabel = 'pendingverified';
            }

            $pay->payment_gateway_refno = $refno;
            $pay->payment_gateway_status = $status;
            $pay->payment_gateway_reason = $reason;
            $pay->payment_gateway_code = $billcode;
            $pay->payment_gateway_callback = 1;
            $pay->payment_gateway_transaction_time = $transaction_time;
            $pay->payment_status = $statuslabel;

            if (!$pay->save()) {
                throw new \Exception('Cannot Update Payment information');
            }
        } catch (\Throwable $t) {
            Yii::$app->response->statusCode = 500;
            echo $t->getMessage();
        }
    }

}
