<?php

namespace Modules\Wallet\App\Http\Controllers\api;
use Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;

use Modules\Wallet\App\Models\Wallet;
use Modules\Currency\App\Models\Currency;
use Modules\GlobalSetting\App\Models\GlobalSetting;
use Modules\Wallet\App\Models\WalletTransaction;
use Srmklive\PayPal\Services\PayPal as PayPalClient;
use Modules\PaymentGateway\App\Models\PaymentGateway;
use Stripe\Price;
use Stripe;
use Mollie\Laravel\Facades\Mollie;

use Razorpay\Api\Api;

class PaymentController extends Controller
{

    public $payment_setting;

    public function __construct()
    {
        $payment_data = PaymentGateway::all();


            $this->payment_setting = array();

            foreach($payment_data as $data_item){
                $payment_setting[$data_item->key] = $data_item->value;
            }

            $this->payment_setting  = (object) $payment_setting;
    }


    public function stripe_payment(){
        if(env('APP_MODE') == 'DEMO'){
            $notify_message = trans('translate.This Is Demo Version. You Can Not Change Anything');
            $notify_message=array('message'=>$notify_message,'alert-type'=>'error');
            return response()->json(['message' => $notify_message],403);
        }

        return response()->json(['payment_setting' => $this->payment_setting]);
    }

    public function stripe_payment_store(Request $request){
        if(env('APP_MODE') == 'DEMO'){
            $notify_message = trans('translate.This Is Demo Version. You Can Not Change Anything');
            $notify_message=array('message'=>$notify_message,'alert-type'=>'error');
            return response()->json(['message' => $notify_message],403);
        }

        $auth_user = Auth::guard('api')->user();

        $main_price = $request->amount;

        if($main_price == '0.00'){
            $notify_message = trans('translate.Minimum 1 USD is required for payment');
            $notify_message = array('message' => $notify_message, 'alert-type' => 'error');
            return response()->json(['message' => $notify_message],403);
        }
        $stripe_currency = Currency::findOrFail($this->payment_setting->stripe_currency_id);

        $payable_amount = round($main_price * $stripe_currency->currency_rate,2);

        Stripe\Stripe::setApiKey($this->payment_setting->stripe_secret);

        try{
            $token = Stripe\Token::create([
                'card' => [
                    'number' => $request->card_number,
                    'exp_month' => $request->month,
                    'exp_year' => $request->year,
                    'cvc' => $request->cvc,
                ],
            ]);
        }catch (\Exception $ex) {
            Log::info($ex->getMessage());
            return response()->json(['message' => 'Please provide valid card information'],403);
        }

        if (!isset($token['id'])) {
            return response()->json(['message' => 'Payment faild'],403);
        }
        try{
            $result = Stripe\Charge::create([
                'card' => $token['id'],
                'currency' => $stripe_currency->currency_code,
                'amount' => $payable_amount * 100,
                'description' => env('APP_NAME'),
            ]);
            if($result['status'] != 'succeeded') {
                return response()->json(['message' => 'Payment faild'],403);
            }

        }catch(\Exception $ex){
            Log::info($ex->getMessage());
            $notify_message = trans('translate.Something went wrong, please try again');
            return response()->json(['message' => $notify_message],403);
        }

        $order = $this->create_wallet_balance($auth_user, $request->amount, 'Stripe', 'success', $result->balance_transaction);

        $notify_message = trans('translate.Your payment has been made successful. Thanks for your new purchase');
        $notify_message = array('message'=>$notify_message,'alert-type'=>'success');
        return response()->json(['message' => $notify_message],200);

    }

    public function bank_payment(Request $request){

        $request->validate([
            'tnx_info' => 'required|max:255'
        ],[
            'tnx_info.required' => trans('translate.Transaction field is required')
        ]);

        $auth_user = Auth::guard('api')->user();

        $amount = $request->amount;
        
        if($amount == '0.00'){
            $notify_message = trans('translate.Minimum 1 USD is required for payment');
            $notify_message = array('message' => $notify_message, 'alert-type' => 'error');
            return response()->json(['message' => $notify_message],403);
        }

        $order = $this->create_wallet_balance($auth_user, $amount, 'Bank Payment', 'success', $request->tnx_info);

            $notify_message = trans('translate.Your payment has been made. please wait for admin payment approval');
            return response()->json(['message' => $notify_message]);
    }

    public function paypal_webview(Request $request){

        $auth_user = Auth::guard('api')->user();
        Session::put('auth_user', $auth_user);
        $main_price = $request->amount;

        $paypal_currency = Currency::findOrFail($this->payment_setting->paypal_currency_id);

        $payable_amount = round($main_price * $paypal_currency->currency_rate);

        config(['paypal.mode' => $this->payment_setting->paypal_account_mode]);

        if($this->payment_setting->paypal_account_mode == 'sandbox'){
            config(['paypal.sandbox.client_id' => $this->payment_setting->paypal_client_id]);
            config(['paypal.sandbox.client_secret' => $this->payment_setting->paypal_secret_key]);
        }else{
            config(['paypal.live.client_id' => $this->payment_setting->paypal_client_id]);
            config(['paypal.live.client_secret' => $this->payment_setting->paypal_secret_key]);
            config(['paypal.live.app_id' => 'APP-80W284485P519543T']);
        }

        $provider = new PayPalClient;
        $provider->setApiCredentials(config('paypal'));
        $paypalToken = $provider->getAccessToken();
        $response = $provider->createOrder([
            "intent" => "CAPTURE",
            "application_context" => [
                "return_url" => route('wallet-api-payment.paypal-webview-success'),
                "cancel_url" => route('wallet-api-payment.paypal-webview-faild'),
            ],
            "purchase_units" => [
                0 => [
                    "amount" => [
                        "currency_code" => $paypal_currency->currency_code,
                        "value" => $payable_amount
                    ]
                ]
            ]
        ]);
        Session::put('wallet_amount', $request->amount);

        if (isset($response['id']) && $response['id'] != null) {
            
            // redirect to approve href
            foreach ($response['links'] as $links) {
                if ($links['rel'] == 'approve') {
                    return redirect()->away($links['href']);
                }
            }
            
            $notification = trans('translate.Something went wrong, please try again');
            return response()->json(['status' => 'faild' , 'message' => $notification]);
            
        } else {
            $notification = trans('translate.Something went wrong, please try again');
            return response()->json(['status' => 'faild' , 'message' => $notification]);
        }

    }

    public function paypal_webview_success(Request $request){    

        $paypal_currency = Currency::findOrFail($this->payment_setting->paypal_currency_id);

        config(['paypal.mode' => $this->payment_setting->paypal_account_mode]);

        if($this->payment_setting->paypal_account_mode == 'sandbox'){
            config(['paypal.sandbox.client_id' => $this->payment_setting->paypal_client_id]);
            config(['paypal.sandbox.client_secret' => $this->payment_setting->paypal_secret_key]);
        }else{
            config(['paypal.live.client_id' => $this->payment_setting->paypal_client_id]);
            config(['paypal.live.client_secret' => $this->payment_setting->paypal_secret_key]);
            config(['paypal.live.app_id' => 'APP-80W284485P519543T']);
        }

        $provider = new PayPalClient;
        $provider->setApiCredentials(config('paypal'));
        $provider->getAccessToken();
        $response = $provider->capturePaymentOrder($request['token']);
        if (isset($response['status']) && $response['status'] == 'COMPLETED') {


            $auth_user = Session::get('auth_user');
            $wallet_amount = Session::get('wallet_amount');

            $main_price = $wallet_amount;
    
            if($main_price == '0.00'){
                $notify_message = trans('translate.Minimum 1 USD is required for payment');
                $notify_message = array('message' => $notify_message, 'alert-type' => 'error');
                return response()->json(['message' => $notify_message]);
            }
            $order = $this->create_wallet_balance($auth_user, $wallet_amount, 'Paypal', 'success', $request->PayerID);

            $notification = trans('translate.Your payment has been made successful. Thanks for your new purchase');
            return response()->json(['status' => 'success' , 'message' => $notification]);

        } else {
            $notification = trans('translate.Something went wrong, please try again');
            return response()->json(['status' => 'faild' , 'message' => $notification]);
        }

    }

    public function paypal_webview_faild(Request $request){

        $notify_message = trans('translate.Something went wrong, please try again');
        $notify_message = array('message'=>$notify_message,'alert-type'=>'error');
        return response()->json([
            'status' => 'faild' ,
             'message' => $notify_message,
            ]);
    }



    public function mollie_payment(Request $request){

        if(env('APP_MODE') == 'DEMO'){
            $notify_message = trans('translate.This Is Demo Version. You Can Not Change Anything');
            $notify_message=array('message'=>$notify_message,'alert-type'=>'error');
             return response()->json(['message' => $notify_message]);
        }

        $auth_user = Auth::guard('api')->user();
        Session::put('auth_user', $auth_user);
        $wallet_amount = Session::get('wallet_amount');


        try{
            $mollie_currency = Currency::findOrFail($this->payment_setting->mollie_currency_id);

            $price = $request->amount * $mollie_currency->currency_rate;
            // $price = $wallet_amount * $mollie_currency->currency_rate;
            $price = sprintf('%0.2f', $price);

            $mollie_api_key = $this->payment_setting->mollie_key;

            $currency = strtoupper($mollie_currency->currency_code);

            Mollie::api()->setApiKey($mollie_api_key);

            $payment = Mollie::api()->payments()->create([
                'amount' => [
                    'currency' => $currency,
                    'value' => ''.$price.'',
                ],
                'description' => env('APP_NAME'),
                'redirectUrl' => route('wallet-api-payment.mollie-callback'),
            ]);

            $payment = Mollie::api()->payments()->get($payment->id);

            Session::put('payment_id', $payment->id);

            return redirect($payment->getCheckoutUrl(), 303);

        }catch (\Exception $e) {
            $notify_message = trans('translate.Please provide valid mollie api key');
            $notify_message = array('message'=>$notify_message,'alert-type'=>'error');
            return response()->json(['message' => $notify_message],403);
        }

    }

    public function mollie_callback(Request $request){

        $mollie_api_key = $this->payment_setting->mollie_key;
        Mollie::api()->setApiKey($mollie_api_key);
        $payment = Mollie::api()->payments->get(session()->get('payment_id'));
        if ($payment){

            $auth_user = Session::get('auth_user');
            $wallet_amount = Session::get('wallet_amount');

            $order = $this->create_wallet_balance($auth_user, $wallet_amount, 'Mollie', 'success', session()->get('payment_id'));

            $notify_message = trans('translate.The payment has been added to your wallet');
            $notify_message = array('message'=>$notify_message,'alert-type'=>'success');
            return response()->json(['message' => $notify_message]);

        }else{
            $notify_message = trans('translate.Something went wrong, please try again');
            $notify_message = array('message'=>$notify_message,'alert-type'=>'error');
            return response()->json(['message' => $notify_message]);
        }


    }


    public function razorpay_webview(Request $request){

        if(env('APP_MODE') == 'DEMO'){
            $notification = trans('user_validation.This Is Demo Version. You Can Not Change Anything');
            return response()->json(['message' => $notification],403);
        }

       $user = Auth::guard('api')->user();
       if(!$user){
           return response()->json(['message' => 'User Not Found'],403);
         }

         $payable_amount = $request->amount;
 
        $razorpay_currency = Currency::findOrFail($this->payment_setting->razorpay_currency_id);
  
        Session::put('auth_user', $user);
        $payment_setting = $this->payment_setting;
        $setting = GlobalSetting::first();

        return view('wallet::webview.razorpay_webview', compact('user', 'payable_amount','setting','payment_setting','razorpay_currency'));
    }

    public function razorpay_webview_success(Request $request, $wallet_amount){

        $input = $request->all();
        $api = new Api($this->payment_setting->razorpay_key,$this->payment_setting->razorpay_secret);
        $payment = $api->payment->fetch($input['razorpay_payment_id']);
        if(count($input)  && !empty($input['razorpay_payment_id'])) {

            try {
                $response = $api->payment->fetch($input['razorpay_payment_id'])->capture(array('amount'=>$payment['amount']));
                $payId = $response->id;
                $auth_user = Session::get('auth_user');

                $main_price = $wallet_amount;

                $order = $this->create_wallet_balance($auth_user, $main_price, 'Razorpay', 'success', $payId);
                $notification = trans('translate.Your payment has been made successful. Thanks for your new purchase');
                return response()->json(['status' => 'success' , 'message' => $notification]);

            }catch (\Exception $e) {
                $notification = trans('translate.Something went wrong, please try again');
                return response()->json(['status' => 'faild' , 'message' => $notification]);
            }
        }else{
            $notification = trans('translate.Something went wrong, please try again');
            return response()->json(['status' => 'faild' , 'message' => $notification]);
        }
    }


    
    public function flutterwave_payment(Request $request){

        if(env('APP_MODE') == 'DEMO'){
            $notify_message = trans('translate.This Is Demo Version. You Can Not Change Anything');
            $notify_message=array('message'=>$notify_message,'alert-type'=>'error');
            return response()->json(['message' => $notify_message],403);
        }
        
        $user = Auth::guard('api')->user();
        if(!$user){
            return response()->json(['message' => 'User Not Found'],403);
        }
        
        $payable_amount = $request->amount;

         $flutterwave_currency = Currency::findOrFail($this->payment_setting->flutterwave_currency_id);
         Session::put('auth_user', $user);
         $payment_setting = $this->payment_setting;
         $setting = GlobalSetting::first();
 

        return view('wallet::webview.flutterwave', compact('user','payable_amount','setting','payment_setting','flutterwave_currency'));
    }

    

    public function flutterwave_payment_store(Request $request, $payable_amount){

        $curl = curl_init();
        $tnx_id = $request->tnx_id;
        $url = "https://api.flutterwave.com/v3/transactions/$tnx_id/verify";
        $token = $this->payment_setting->flutterwave_secret_key;
        curl_setopt_array($curl, array(
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING => "",
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 0,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST => "GET",
        CURLOPT_HTTPHEADER => array(
            "Content-Type: application/json",
            "Authorization: Bearer $token"
        ),
        ));

        $response = curl_exec($curl);

        curl_close($curl);
        $response = json_decode($response);

        if($response->status == 'success'){

            $auth_user = Session::get('auth_user');

            $order = $this->create_wallet_balance($auth_user, $payable_amount, 'Flutterwave', 'success', $tnx_id);

            $notify_message = trans('translate.Your payment has been made successful. Thanks for your new purchase');
            return response()->json(['status' => 'success' , 'message' => $notify_message]);
        }else{
            $notify_message = trans('translate.Something went wrong, please try again');
            return response()->json(['status' => 'faild' , 'message' => $notify_message]);
        }


    }


    public function paystack_payment(Request $request){

        if(env('APP_MODE') == 'DEMO'){
            $notify_message = trans('translate.This Is Demo Version. You Can Not Change Anything');
            $notify_message=array('message'=>$notify_message,'alert-type'=>'error');
            return response()->json(['message' => $notify_message],403);
        }

        $payable_amount = $request->amount;
        $payment_setting = $this->payment_setting;
        $setting = GlobalSetting::first();
        $paystack_currency = Currency::findOrFail($this->payment_setting->paystack_currency_id);
        $user = Auth::guard('api')->user();
        Session::put('auth_user', $user);

        return view('wallet::webview.paystack', compact('user','payable_amount','setting','payment_setting','paystack_currency'));
    }



    public function paystack_payment_store(Request $request, $payable_amount){

        $reference = $request->reference;
        $transaction = $request->tnx_id;
        $secret_key = $this->payment_setting->paystack_secret_key;
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => "https://api.paystack.co/transaction/verify/$reference",
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => "",
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_SSL_VERIFYHOST =>0,
            CURLOPT_SSL_VERIFYPEER =>0,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "GET",
            CURLOPT_HTTPHEADER => array(
                "Authorization: Bearer $secret_key",
                "Cache-Control: no-cache",
            ),
        ));
        $response = curl_exec($curl);
        $err = curl_error($curl);
        curl_close($curl);
        $final_data = json_decode($response);
        if($final_data->status == true) {

                 $auth_user = Session::get('auth_user');

            $order = $this->create_wallet_balance($auth_user, $payable_amount, 'Paystack', 'success', $transaction);

            $notify_message = trans('translate.Your payment has been made successful. Thanks for your new purchase');
            return response()->json(['status' => 'success' , 'message' => $notify_message]);

        }else{
            $notify_message = trans('translate.Something went wrong, please try again');
            return response()->json(['status' => 'faild' , 'message' => $notify_message]);
        }


    }

    public function instamojo_payment(Request $request){
        if(env('APP_MODE') == 'DEMO'){
            $notify_message = trans('translate.This Is Demo Version. You Can Not Change Anything');
            $notify_message=array('message'=>$notify_message,'alert-type'=>'error');
            return redirect()->back()->with($notify_message);
        }

        $notify_message = trans('translate.Your payment has been made successful. Thanks for your new purchase');
        $notify_message = array('message'=>$notify_message,'alert-type'=>'success');
        return response()->json(['status' => 'success' , 'message' => $notify_message]);

    }

    public function instamojo_callback(Request $request){


        $input = $request->all();

        $environment = $this->payment_setting->instamojo_account_mode;
        $api_key = $this->payment_setting->instamojo_api_key;
        $auth_token = $this->payment_setting->instamojo_auth_token;

        if($environment == 'Sandbox') {
            $url = 'https://test.instamojo.com/api/1.1/';
        } else {
            $url = 'https://www.instamojo.com/api/1.1/';
        }

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url.'payments/'.$request->get('payment_id'));
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
        curl_setopt($ch, CURLOPT_HTTPHEADER,
            array("X-Api-Key:$api_key",
                "X-Auth-Token:$auth_token"));
        $response = curl_exec($ch);
        $err = curl_error($ch);
        curl_close($ch);

        if ($err) {

            $notify_message = trans('translate.Something went wrong, please try again');
            $notify_message = array('message'=>$notify_message,'alert-type'=>'error');
            return redirect()->route('buyer.wallet.create')->with($notify_message);

        } else {
            $data = json_decode($response);
        }

        if($data->success == true) {
            if($data->payment->status == 'Credit') {


                $auth_user = Auth::guard('api')->user();

                    
                $main_price = Session::get('wallet_amount');

                $instamojo_currency = Currency::findOrFail($this->payment_setting->instamojo_currency_id);

                $price = $main_price * $instamojo_currency->currency_rate;
                $price = round($price,2);
                $order = $this->create_wallet_balance($auth_user, $price, 'Instamojo', 'success', $request->get('payment_id'));

                $notify_message = trans('translate.Your payment has been made successful. Thanks for your new purchase');
                $notify_message = array('message'=>$notify_message,'alert-type'=>'success');
                return redirect()->route('buyer.wallet.index')->with($notify_message);
            }
        }else{
            $notify_message = trans('translate.Something went wrong, please try again');
            $notify_message = array('message'=>$notify_message,'alert-type'=>'error');
            return redirect()->route('buyer.wallet.create')->with($notify_message);
        }

    }



    public function create_wallet_balance($user, $wallet_amount, $payment_gateway, $payment_status, $transaction_id){

        $my_wallet = Wallet::where('buyer_id', $user->id)->first();
        if(!$my_wallet){
            $my_wallet = new Wallet();
            $my_wallet->buyer_id = $user->id;
            $my_wallet->balance = 0.00;
            $my_wallet->save();
        }

        $my_wallet->balance = $my_wallet->balance + $wallet_amount;
        $my_wallet->save();

        $wallet_transaction = new WalletTransaction();
        $wallet_transaction->buyer_id = $user->id;
        $wallet_transaction->amount = $wallet_amount;
        $wallet_transaction->payment_gateway = $payment_gateway;
        $wallet_transaction->transaction_id = $transaction_id;
        $wallet_transaction->payment_status = $payment_status;
        $wallet_transaction->payment_type = 'credit';
        $wallet_transaction->save();

    }
}
