<?php

namespace Modules\Subscription\Http\Controllers\Seller\API;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\Currency\App\Models\Currency;

use Illuminate\Contracts\Support\Renderable;
use Illuminate\Log\Logger;
use Illuminate\Support\Facades\Log as FacadesLog;
use Modules\GlobalSetting\App\Models\GlobalSetting;
use Modules\Listing\App\Models\ListingPackage;
use Modules\Listing\Entities\Listing;
use Modules\Subscription\Entities\SubscriptionPlan;
use Modules\PaymentGateway\App\Models\PaymentGateway;
use Modules\Subscription\Entities\SubscriptionHistory;
use Modules\Subscription\Http\Requests\SubscriptionPlanRequest;

use Srmklive\PayPal\Services\PayPal as PayPalClient;
use Stripe\Checkout\Session as StripSession;
use Mollie\Laravel\Facades\Mollie;
use Razorpay\Api\Api;
use Stripe\Price;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use Stripe, Exception;



class SubscriptionPlanController 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 purchase_history()
    {
        $auth_user = Auth::guard('api')->user();

        $histories = SubscriptionHistory::orderBy('id','desc')->where('user_id', $auth_user->id)->paginate(20);

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



    public function index()
    {
        $plans = SubscriptionPlan::orderBy('serial', 'asc')->where('status', 'active')->get();

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

    public function payment($plan_id)
    {
        $auth_user = Auth::guard('api')->user();

        $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();

        $razorpay_currency = Currency::findOrFail($this->payment_setting->razorpay_currency_id);
        $flutterwave_currency = Currency::findOrFail($this->payment_setting->flutterwave_currency_id);
        $paystack_currency = Currency::findOrFail($this->payment_setting->paystack_currency_id);

        $payable_amount = $plan->plan_price;

        return response()->json([
            'user' => $auth_user,
            'plan' => $plan,
            'payable_amount' => $payable_amount,
            'payment_setting' => $this->payment_setting ,
            'razorpay_currency' => $razorpay_currency ,
            'flutterwave_currency' => $flutterwave_currency ,
            'paystack_currency' => $paystack_currency ,
        ]);

    }


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

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

        $free_exist = SubscriptionHistory::where('user_id', 2)->where(['payment_method' => 'Free'])->count();
        if($free_exist == 0){

            $plan = SubscriptionPlan::where('status', 'active')->where('id', $id)->firstOrFail();
            $this->create_order($user, $plan, $plan->plan_price, 'Free', 'success', 'free_enroll');

            $notify_message = trans('translate.Enrolled Successfully');
            $notify_message = array('message'=>$notify_message,'alert-type'=>'success');
            return response()->json(['message' => $notify_message]);

        }else{
            $notify_message = trans('translate.You have already enrolled trail version');

            $notify_message=array('message'=>$notify_message,'alert-type'=>'error');
         return response()->json(['message' => $notify_message]);
        }


    }


    public function stirpe_payment(Request $request, $plan_id){

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

        $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();

        if(!$plan){

            $notify_message = trans('translate.This Is Demo Version. Plan can not found');
            $notify_message=array('message'=>$notify_message,'alert-type'=>'error');
            return response()->json(['message' => $notify_message],403);
        }

        $package_main_price = $plan->plan_price;

        if($package_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($package_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_order($auth_user, $plan, $package_main_price, '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, $plan_id){

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

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

        $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();

        $package_main_price = $plan->plan_price;

        $order = $this->create_order($auth_user, $plan, $package_main_price, 'Bank Payment', 'pending', $request->tnx_info);

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

    }


    
    public function paypal_webview(Request $request, $plan_id){

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

        $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();

        $main_price = $plan->plan_price;

        $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('seller.subscription-api.payment.paypal-webview-success'),
                "cancel_url" => route('seller.subscription-api.payment.paypal-webview-faild'),
            ],
            "purchase_units" => [
                0 => [
                    "amount" => [
                        "currency_code" => $paypal_currency->currency_code,
                        "value" => $payable_amount
                    ]
                ]
            ]
        ]);
        Session::put('auth_user', $auth_user);
        Session::put('plan_id', $plan_id);

        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');
            $plan_id = Session::get('plan_id');

            $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();

            $main_price = $plan->plan_price;
    
            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_order($auth_user,  $plan, $main_price, '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){
        $plan_id = Session::get('plan_id');

        $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,
             'plan_id' => $plan_id
            ]);
    }



    public function razorpay_webview(Request $request, $plan_id){

        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);
         }

         $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();

         $payable_amount = $plan->plan_price;
 
        $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('subscription::subscription_webview.razorpay_webview', compact('user', 'payable_amount','setting','payment_setting','plan','razorpay_currency'));
    }

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

        $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');

                $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();

                $package_main_price = $plan->plan_price;
            
                $order = $this->create_order($auth_user, $plan, $package_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_webview(Request $request, $plan_id){

        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);
         }

         $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();

         $payable_amount = $plan->plan_price;

        $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('subscription::subscription_webview.flutterwave_webview', compact('user', 'payable_amount','setting','payment_setting','plan','flutterwave_currency'));
    }


    public function flutterwave_webview_payment(Request $request, $plan_id){

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

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

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

           
           $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();
           $package_main_price = $plan->plan_price;
            $order = $this->create_order($auth_user, $plan, $package_main_price, '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_webview(Request $request, $plan_id){
        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);
         }

         $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();

         $payable_amount = $plan->plan_price;
        $paystack_currency = Currency::findOrFail($this->payment_setting->paystack_currency_id);

        Session::put('auth_user', $user);
        Session::put('plan_id', $plan_id);
        $payment_setting = $this->payment_setting;
        $setting = GlobalSetting::first();

        return view('subscription::subscription_webview.paystack_webview', compact('user', 'payable_amount','setting','payment_setting','plan','paystack_currency'));
    }


    public function paystack_webview_payment(Request $request, $plan_id){
        $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');
            // $plan_id = Session::get('plan_id');

            $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();
            $package_main_price = $plan->plan_price;
            $order = $this->create_order($auth_user, $plan, $package_main_price, 'Razorpay', '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 mollie_webview(Request $request, $plan_id){

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

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

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

            $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();

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

            $price = $package_main_price * $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('seller.subscription-api.payment.mollie-webview-payment'),
            ]);

            $payment = Mollie::api()->payments()->get($payment->id);
            Session::put('payment_id', $payment->id);
            Session::put('auth_user', $auth_user);
            Session::put('plan_id', $plan_id);
            return redirect($payment->getCheckoutUrl(), 303);

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

    public function mollie_webview_payment(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->isPaid()){

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

            $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();

            $package_main_price = $plan->plan_price;

            $order = $this->create_order($auth_user, $plan, $package_main_price, 'Mollie', 'success', session()->get('payment_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 instamojo_payment(Request $request, $plan_id){
        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);
        }

        $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){

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

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

            $plan = SubscriptionPlan::where('status', 'active')->where('id', $plan_id)->firstOrFail();

            $main_price = $plan->plan_price;

            $order = $this->create_order($auth_user, $plan, $main_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 response()->json(['message' => $notify_message],200);

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

            $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,
                'plan_id' =>  $plan_id
            ]);
        

    }


    public function create_order($user, $subscription_plan, $package_main_price, $payment_method, $payment_status, $transaction_id){

        $purchase = new SubscriptionHistory();

        if($subscription_plan->expiration_date == 'monthly'){
            $expiration_date = date('Y-m-d', strtotime('30 days'));
        }elseif($subscription_plan->expiration_date == 'yearly'){
            $expiration_date = date('Y-m-d', strtotime('365 days'));
        }elseif($subscription_plan->expiration_date == 'lifetime'){
            $expiration_date = 'lifetime';
        }

        SubscriptionHistory::where('user_id', $user->id)->update(['status' => 'expired']);

        $purchase->order_id = substr(rand(0,time()),0,10);
        $purchase->user_id = $user->id;
        $purchase->subscription_plan_id = $subscription_plan->id;
        $purchase->plan_name = $subscription_plan->plan_name;
        $purchase->plan_price = $subscription_plan->plan_price;
        $purchase->expiration = $subscription_plan->expiration_date;
        $purchase->expiration_date = $expiration_date;
        $purchase->max_listing = $subscription_plan->max_listing;
        $purchase->featured_listing = $subscription_plan->featured_listing;
        $purchase->recommended_seller = $subscription_plan->recommended_seller;
        $purchase->status = 'active';
        $purchase->payment_method = $payment_method;
        $purchase->payment_status = $payment_status;
        $purchase->transaction = $transaction_id;
        $purchase->save();

        return $purchase;

    }

}
