<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Models\Transaction;
use App\Models\User;
use App\PaymentGateways\OnlinePaymentGateway;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Session;

class PaymentController extends Controller
{

    /**
     * @param Request $request
     * @param $platform
     */
    public function onlineCallBack(Request $request, $platform)
    {
        $trandata = $request->trandata; //2 methods
        $paymentid = $request->paymentid; //2 methods
        $trackid = $request->trackid; // payment_tokens_id //Only in Merchant Hosted
        $transaction = [];

        if ($trandata && ($trackid || $paymentid)) {
            $paymentGateway = new OnlinePaymentGateway();
            $result = $paymentGateway->getResult($trandata);
            $resultSuccess = $result['success'];
            $resultData = $result['data'];
            if ($trackid) {
                $transaction = Transaction::where(['id' => $trackid, 'pay_done' => 'no'])->first();//Merchant Hosted
            } elseif ($paymentid) {
                $transaction = Transaction::where(['payment_id' => $paymentid, 'pay_done' => 'no'])->first();//Bank Hosted
            }

            if (isset($transaction['id'])) {
                $meta = ['post_data' => $_POST, 'response_data' => $resultData];
                $transaction->update(['response' => $meta, 'payment_id' => $paymentid]);

                DB::table('transaction_logs')->insert([
                    'transaction_id' => $transaction->id,
                    'payment_id' => $paymentid,
                    'meta' => json_encode($meta),
                    'created_at' => now(),
                    'updated_at' => now(),
                ]);

                //restore session
                $session = $transaction->meta['session'] ?? null;
                if (!auth()->check() && $transaction->user_id){
                    Auth::login(User::find($transaction->user_id));
                }
                if ($session){
                    Session::put($session);
                }
            } //end if $transaction

            if ($resultSuccess && $transaction && $resultData[0]['amt'] == $transaction->total) {
                $ifSuccessResult = $this->ifSuccess($transaction);
                $transaction->order = $ifSuccessResult['order'];
                return $this->afterSuccess($transaction);
            } else {
                return $this->throwError($platform);
            }
        } else {
            return $this->throwError($platform);
        }
    } //end of method

    /**
     * @param $transaction
     * @return array
     */
    private function ifSuccess($transaction): array
    {
        $meta = $transaction->meta;
        $order_id = $meta['order_id'] ?? null;
        $order = Order::find($order_id);
        //if ($transaction->type == 'order'){}
        if ($order) {
            $order->payment()->update(['user_status_paid' => 'paid']);
        }
        $transactionData = ['token' => null, 'pay_done' => 'yes'];
        /*if (!$transaction->item_id && $order){
            $transactionData['item_id'] = $order->id;
        }*/
        $transaction->update($transactionData);
        return [
            'transaction' => $transaction,
            'order' => $order,
        ];
    }

    /**
     * @param $transaction
     * @param string $msg
     * @return Application|\Illuminate\Foundation\Application|RedirectResponse|Redirector
     */
    public function afterSuccess($transaction, string $msg = ''): \Illuminate\Foundation\Application|Redirector|RedirectResponse|Application
    {
        //$meta = $transaction->meta;
        //$order = $meta['order'] ?? null;
        $order = $transaction->order ?? null;
        if (!$msg) {
            $msg = __('main.pay_completed');
        }

        if ($transaction->platform == 'mobile') {
            return redirect()->route('payment_success');
        } else { //web
            if (auth()->check() && ($order->token ?? null)) {
                return redirect()->route('order.details', $order->token)->with('success_alert', $msg);
            } else {
                return redirect('/')->with('success_alert', $msg);
            }
        }
    }

    /**
     * @param string $platform
     * @param string $msg
     * @return Application|\Illuminate\Foundation\Application|RedirectResponse|Redirector
     */
    private function throwError(string $platform = 'web', string $msg = ''): \Illuminate\Foundation\Application|Redirector|RedirectResponse|Application
    {
        if (!$msg) {
            $msg = __('main.pay_problem');
        }
        if ($platform == 'mobile') {
            return redirect()->route('payment_error');
        } else { //web
            return redirect('/')->with('error_alert', $msg);
        }
    }

    ################################# START TAMARA ##########################################
    public function initiateTamaraPayment($token='', $jsonRes=0){
        $paymentInfo = $this->system_library->getPaymentToken(['token'=>$token]);
        $userInfo  = $this->user->get_user($paymentInfo['user_id']);
        $orderData = json_decode($paymentInfo['orderData'], true);
        $pay = $paymentInfo['payMethod'];
        if(!$paymentInfo || !$orderData || empty($orderData['cart']) || !$token || $pay!=17){
            $this->throwError($jsonRes);
        }

        $result = $this->tamara_library->createCheckoutSession($paymentInfo, $jsonRes);

        //echo"<pre>";var_dump($result);echo"</pre>";
        if($result['order_id'] && $result['checkout_url']){
            $tamara_order_id = $result['order_id'];
            $tamara_checkout_id = $result['checkout_id'];
            $tamara_checkout_url = $result['checkout_url'];

            //update payment_tokens
            $params = array(
                'tamara_order_id' => $tamara_order_id,
                'tamara_checkout_id' => $tamara_checkout_id,
                //'tamara_checkout_url' => $tamara_checkout_url,
            );
            $this->system_library->updatePaymentTokens($token, $params);

            //redirect to tamara url
            redirect($tamara_checkout_url);
        }else{
            $this->throwError($jsonRes);
        }
    }

    public function tamaraSuccess($jsonRes=0){
        $paymentStatus = $_GET['paymentStatus']; //approved
        $tamaraOrderId = $_GET['orderId'];

        $headers = $this->input->request_headers();
        $tamaraLogs = array(
            'json_res' => $jsonRes,
            'type' => 'success',
            'get_data' => json_encode($_GET),
            'post_data' => json_encode($_POST),
            'headers_data' => json_encode($headers),
            'tamara_order_id' => $tamaraOrderId,
        );
        $this->tamara_library->add_tamara_logs($tamaraLogs);

        //get order details [tamara]
        $tamaraOrder = $this->tamara_library->getOrderDetails($tamaraOrderId);

        $status = $tamaraOrder['status'];
        $order_id = $tamaraOrder['order_number'];//order_reference_id

        //Must be check here [because in commonTamaraAddOrder order_reference_id changed]
        if($status == 'authorised'){ //Pay Done
            //redirection
            $paymentInfo = $this->system_library->getPaymentTokenByCondition(['order_id'=>$order_id]);
            $this->afterSuccess($jsonRes, '', $paymentInfo);
        }else{
            $this->commonTamaraAddOrder([
                'tamaraOrderId' => $tamaraOrderId,
                'jsonRes' => $jsonRes,
                'paymentStatus' => $paymentStatus,
                'done_method' => 'tamaraSuccess',
            ]);
        }
    }

    private function commonTamaraAddOrder($params=[])
    {
        $tamaraOrderId = $params['tamaraOrderId'];
        $jsonRes = $params['jsonRes'];
        $paymentStatus = $params['paymentStatus']; //approved
        $done_method = $params['done_method'];

        //get order details [tamara]
        $tamaraOrder = $this->tamara_library->getOrderDetails($tamaraOrderId);

        if($tamaraOrder['order_id']){
            //add order to my database
            $order_reference_id = $tamaraOrder['order_reference_id'];
            $status = $tamaraOrder['status'];//approved
            /*
                getPaymentTokenByCondition(['id'=>$order_reference_id]):-
                may order refrence id updated by order id by (notification) and (success)
                git in commonTamaraAddOrder() then $paymentInfo will be empty.
                THE BEST:- getPaymentTokenByCondition(['tamara_order_id'=>$tamaraOrderId])
            */
            $paymentInfo = $this->system_library->getPaymentTokenByCondition(['tamara_order_id'=>$tamaraOrderId]);
            $this->db->insert('curl_log', ['result'=>json_encode(['done_method'=>$done_method, 'params'=>$params, 'paymentInfo'=>$paymentInfo, 'tamaraOrder'=>$tamaraOrder])]);//REMOVE_THIS
            // Must check $status=='approved' because notification may send after success (sent more than one time)
            if($paymentInfo && $paymentInfo['token'] && $status=='approved'){ //$paymentInfo['token'] :- not paid yet
                if($done_method){$paymentInfo['done_method']=$done_method;}
                $ifSuccessResults = $this->ifSuccess($paymentInfo);
                $updatedPaymentInfo = $ifSuccessResults['updatedPaymentInfo'];
                $order_id = $updatedPaymentInfo['order_id'];
                if(!$order_id){ $this->throwError($jsonRes); }

                //Update order reference id [must be next to authoriseOrder]
                $updateRefIdResult = $this->tamara_library->updateOrderReferenceId($tamaraOrderId, $order_id);

                //Authorise order
                $authoriseOrderResult = $this->tamara_library->authoriseOrder($tamaraOrderId);
                if($authoriseOrderResult['order_id']){
                    $status = $authoriseOrderResult['status'];//authorised
                }

                //update my order data
                $this->system_library->updateOrder($order_id, ['tamara_order_id' => $tamaraOrderId, 'tamara_status'=>$status]);//authorised
                //echo"<pre>";var_dump($paymentInfo);echo"</pre>";

                //redirection
                $this->afterSuccess($jsonRes, '', $updatedPaymentInfo);
            }elseif($paymentInfo && $paymentInfo['payDone']==1){ //&& $status=='authorised' (mybe payDone=1 and status still approved)
                $this->afterSuccess($jsonRes, '', $paymentInfo);
            }else{
                $this->throwError($jsonRes);
            }
        }else{
            $this->throwError($jsonRes);
        }
    }

    public function tamaraFailure($jsonRes=0){
        $headers = $this->input->request_headers();
        $tamaraLogs = array(
            'json_res' => $jsonRes,
            'type' => 'failure',
            'get_data' => json_encode($_GET),
            'post_data' => json_encode($_POST),
            'headers_data' => json_encode($headers),
        );
        $this->tamara_library->add_tamara_logs($tamaraLogs);

        $this->throwError($jsonRes);
        //echo"<pre>";var_dump("tamaraFailure", $_GET, $_POST);echo"</pre>";
    }

    public function tamaraCancel($jsonRes=0){
        $headers = $this->input->request_headers();
        $tamaraLogs = array(
            'json_res' => $jsonRes,
            'type' => 'cancel',
            'get_data' => json_encode($_GET),
            'post_data' => json_encode($_POST),
            'headers_data' => json_encode($headers),
        );
        $this->tamara_library->add_tamara_logs($tamaraLogs);

        $this->throwError($jsonRes);
        //echo"<pre>";var_dump("tamaraCancel", $_GET, $_POST);echo"</pre>";
    }

    public function tamaraNotification($jsonRes=0){
        $headers = $this->input->request_headers();// or [ apache_request_headers() ]
        $body = (file_get_contents("php://input"));//request payload
        $body_data = json_decode($body, true);
        $tamaraLogs = array(
            'json_res' => $jsonRes,
            'type' => 'notification',
            'get_data' => json_encode($_GET),
            'post_data' => json_encode($_POST),
            'headers_data' => json_encode($headers),
            'body_data' => json_encode($body_data),
            'tamara_order_id' => $body_data['order_id'],
        );
        $this->tamara_library->add_tamara_logs($tamaraLogs);

        //echo"<pre>";var_dump("tamaraNotification", $_GET, $_POST);echo"</pre>";

        $tamaraOrderId = $body_data['order_id'];
        $paymentStatus = $body_data['order_status'];
        $order_reference_id = $body_data['order_reference_id'];

        //get order details [tamara]
        $tamaraOrder = $this->tamara_library->getOrderDetails($tamaraOrderId);

        $paymentInfo = $this->system_library->getPaymentTokenByCondition(['id'=>$order_reference_id]);

        $tamaraToken = $_GET['tamaraToken'];
        $isRequestFromTamara = $this->tamara_library->isRequestFromTamara($tamaraToken);
        if ($isRequestFromTamara && $paymentStatus=='approved' && $tamaraOrder['order_id'] && $paymentInfo['token'] && $tamaraToken){
            $this->commonTamaraAddOrder([
                'tamaraOrderId' => $tamaraOrderId,
                'jsonRes' => $jsonRes,
                'paymentStatus' => $paymentStatus,
                'done_method' => 'tamaraNotification',
            ]);
        }else{
            $this->throwError($jsonRes);
        }
    }

    public function tamaraWebhooks(){
        $headers = $this->input->request_headers();
        $body = (file_get_contents("php://input"));//request payload
        $body_data = json_decode($body, true);
        $tamaraLogs = array(
            //'json_res' => $jsonRes,
            'type' => 'webhooks',
            'get_data' => json_encode($_GET),
            'post_data' => json_encode($_POST),
            'headers_data' => json_encode($headers),
            'body_data' => json_encode($body_data),
            'tamara_order_id' => $body_data['order_id'],
            'event_type' => $body_data['event_type'],
        );
        $tamara_logs_id = $this->tamara_library->add_tamara_logs($tamaraLogs);

        //echo"<pre>";var_dump("tamaraWebhooks", $_GET, $_POST);echo"</pre>";

        $tamaraOrderId = $body_data['order_id'];
        $order_reference_id = $body_data['order_reference_id'];//payment_token_id
        $order_number = $body_data['order_number'];//payment_token_id
        $event_type = $body_data['event_type'];

        //get order details [tamara]
        $tamaraOrder = $this->tamara_library->getOrderDetails($tamaraOrderId);

        $paymentInfo = $this->system_library->getPaymentTokenByCondition(['id'=>$order_reference_id]);

        $tamaraToken = $_GET['tamaraToken'];
        $isRequestFromTamara = $this->tamara_library->isRequestFromTamara($tamaraToken);

        $siteAuthorizationHeader = $this->tamara_library->getWebhookAuthorizationHeader();
        $sentAuthorizationHeader = $headers['Authorization'];

        if (
            $isRequestFromTamara && $event_type=='order_approved' &&
            $tamaraOrder['order_id'] && $paymentInfo['token'] && $tamaraToken &&
            $siteAuthorizationHeader==$sentAuthorizationHeader
        ){
            $jsonRes = $paymentInfo['jsonRes'];

            $this->tamara_library->update_tamara_logs($tamara_logs_id, ['json_res' => $jsonRes]);

            $this->commonTamaraAddOrder([
                'tamaraOrderId' => $tamaraOrderId,
                'jsonRes' => $jsonRes,
                'paymentStatus' => $tamaraOrder['status'],//approved
                'done_method' => 'tamaraWebhooks',
            ]);
        }else{
            $this->throwError();
        }
    }
    ################################# END TAMARA ############################################

} //end of class
