<?php

namespace App\Http\Controllers\api\v1;

use App\Http\Controllers\Controller;
use App\Models\Ad;
use App\Models\AdPlan;
use App\Models\ParentApproval;
use App\Models\PaymentReport;
use App\Models\PlanDuration;
use App\Models\PricingPlan;
use App\Models\PromoCode;
use App\Models\TempOrder;
use App\Models\User;
use App\Models\UserPlan;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;



class PaymentController extends Controller
{

    private function validateAccesToken($access_token)
    {
        $user = User::where(['user_access_token' => $access_token])->first();
        if (!$user) {
            http_response_code(401);
            echo json_encode([
                'status' => (string) 0,
                'message' => "Invalid access token",
                'oData' => (object) array(),
                'errors' => (object) [],
            ]);
            exit;
        }

        if ($user->status != 1) {
            http_response_code(401);
            echo json_encode([
                'status' => (string) 0,
                'message' => "User is not active",
                'oData' => (object) array(),
                'errors' => (object) [],
            ]);
            exit;
        }

        return $user;
    }

    public function userPlans(Request $request){
        $status = "1";
        $message = "Ad plans fetched successfully";
        $o_data = [];
        $errors = [];

        $limit = isset($request->limit) ? $request->limit : 10;
        $offset = isset($request->page) ? ($request->page - 1) * $request->limit : 0;
        $adPlans = PricingPlan::where('status', 1)->limit($limit)->offset($offset)->orderBy('id', 'asc')->get();

        $o_data['ad_plans'] = convert_all_elements_to_string($adPlans);

        return response()->json(['status' => $status, 'error' => $errors, 'message' => $message, 'oData' => $o_data], 200);   
    }

    public function upgradePlans(Request $request)
    {
        $status = (string) 1;
        $message = "Upgrade plans listed successfully";
        $o_data = [];
        $errors = [];
        $validator = Validator::make($request->all(), [
            'access_token' => 'required',
        ]);

        if ($validator->fails()) {
            $status = (string) 0;
            $message = $validator->errors()->first();
            $errors = $validator->messages();
            return response()->json(['status' => $status, 'message' => $message, 'errors' => (object) $errors, 'oData' => (object)$o_data]);
        }

        $user = $this->validateAccesToken($request->access_token);
        
        if($user->active_request_count > 0){
            $status = "1";
            return response()->json(['status' => "1", 'message' => "You have active requests", 'errors' => (object) $errors, 'oData' => (object)$o_data]);
        }
        $userPlan = $user->plan;
        $status = "1";
        if(!$userPlan || $userPlan->type == 'free'){
            $status = (string) 1;
            $o_data['upgrade_plans'] = PricingPlan::where('status', 1)->where('type','!=','free')->get()->toArray();
            $o_data['upgrade_plans'] = convert_all_elements_to_string($o_data['upgrade_plans']);
            return response()->json(['status' => $status, 'message' => $message, 'errors' => (object) $errors, 'oData' => (object)$o_data]);
        }

        $duration_preiod = $userPlan->duration;
        $durationOrder = ['monthly' => 1, 'quarterly' => 2, 'yearly' => 3];
        $currentDurationRank = $durationOrder[$duration_preiod] ?? 0;

        $upgradePlans = PricingPlan::where('status', 1)
            ->where('type', '!=', 'free')
            // ->whereIn('duration', array_keys(array_filter($durationOrder, function ($rank) use ($currentDurationRank) {
            // return $rank > $currentDurationRank;
            // })))
            ->get()
            ->toArray();

        $o_data['upgrade_plans'] = convert_all_elements_to_string($upgradePlans);

        return response()->json([
            'status' => $status,
            'message' => $message,
            'errors' => (object) $errors,
            'oData' => (object) $o_data
        ]);


    }

    public function checkout(Request $request)
    {
        $status = (string) 1;
        $message = "";
        $o_data = [];
        $errors = [];
        $validator = Validator::make($request->all(), [
            'access_token' => 'required',
            'plan_id' => 'required|exists:pricing_plans,id',
            'duration' => 'nullable|exists:plan_durations,id',
            'coupon_code' => 'nullable|exists:promo_codes,code',
        ]);

        if ($validator->fails()) {
            $status = (string) 0;
            $message = $validator->errors()->first();
            $errors = $validator->messages();
        } else {
            $user = $this->validateAccesToken($request->access_token);
            $o_data = $this->process_cart($request);
        }

        $o_data = convert_all_elements_to_string($o_data);

        return response()->json(['status' => $status, 'message' => $message, 'errors' => (object) $errors, 'oData' => (object)$o_data]);    
    }

    public function process_cart($request=null)
    {
        $tax_amount = 0;

        $cart_total = 0;
        $duration_preiod = '';
        $taxable_amount  = 0;
        $discount_amount = 0;
        
        $plan = PricingPlan::where('id', $request->plan_id)->first();
        $cart_total = $plan->price;
        $duration_preiod = $plan->duration;

        if($request->coupon_code){
            $coupon = PromoCode::where(['code' => $request->coupon_code, 'status' => 1,])->where('start_date', '<=', date('Y-m-d'))->where('end_date', '>=', date('Y-m-d'))->first();
            if(!$coupon){
                http_response_code(200);
                echo json_encode([
                    'status' => (string) 0,
                    'message' => "Invalid Coupon",
                    'oData' => (object) [],
                    'errors' => (object) [],
                ]);
                exit;
            }

            if(!empty($coupon->pricing_plan_id)){
                $applicablePlans = json_decode($coupon->pricing_plan_id);
                if(!in_array($request->plan_id, $applicablePlans)){
                    http_response_code(200);
                    echo json_encode([
                        'status' => (string) 0,
                        'message' => "Coupon not applicable for this plan",
                        'oData' => (object) [],
                        'errors' => (object) [],
                    ]);
                    exit;
                }
            }

            if($coupon->value > $cart_total) {
                http_response_code(200);
                echo json_encode([
                    'status' => (string) 0,
                    'message' => "Coupon not applicable",
                    'oData' => (object) [],
                    'errors' => (object) [],
                ]);
                exit;
            }

            if(!empty($coupon->total_limit)){
                $countOfPromoCode = TempOrder::where('promo_code', $request->coupon_code)->count();
                if($countOfPromoCode >= $coupon->total_limit){
                    http_response_code(200);
                    echo json_encode([
                        'status' => (string) 0,
                        'message' => "Coupon limit is exceeded",
                        'oData' => (object) [],
                        'errors' => (object) [],
                    ]);
                    exit;
                }
            }

            if(!empty($coupon->daily_limit)){
                $countOfPromoCode = TempOrder::where('promo_code', $request->coupon_code)->whereDate('created_at', date('Y-m-d'))->count();
                if($countOfPromoCode >= $coupon->daily_limit){
                    http_response_code(200);
                    echo json_encode([
                        'status' => (string) 0,
                        'message' => "Coupon limit is exceeded",
                        'oData' => (object) [],
                        'errors' => (object) [],
                    ]);
                    exit;
                }
                
            }

            if(!empty($coupon->user_limit)){
                $countOfPromoCode = TempOrder::where('promo_code', $request->coupon_code)->where('user_id', $request->user_id)->count();
                if($countOfPromoCode >= $coupon->user_limit){
                    http_response_code(200);
                    echo json_encode([
                        'status' => (string) 0,
                        'message' => "Coupon limit is exceeded",
                        'oData' => (object) [],
                        'errors' => (object) [],
                    ]);
                    exit;
                }
            }

            $discount_amount = $coupon->value;
            if($coupon->type == 'percentage'){
                $discount_amount = ($cart_total * $coupon->value) / 100;
            }
        }

        $grand_total = $tax_amount + $cart_total - $discount_amount;
        $cart_count = 1;
        $cart_items = [$plan];

        return [
            'cart_total'            => number_format($cart_total, 2, '.', ''), 
            'tax_amount'            => number_format($tax_amount, 2, '.', ''), 
            'grand_total'           => number_format($grand_total, 2, '.', ''), 
            'cart_count'            => (string)$cart_count,
            'cart_items'            => ($cart_items),
            'duration_period'       => (string)$duration_preiod,
            'taxable_amount'           => number_format($taxable_amount, 2, '.', ''),
            'discount_amount'        => number_format($discount_amount, 2, '.', ''),
            'currency'               => $plan->currency,
        ];
    }

    public function paymentInit(Request $request)
    {
        $status = (string) 0;
        $o_data = [];
        $errors = [];
        $message = "Unable to initialize the payment";

        $validator = Validator::make($request->all(), [
            'access_token' => 'required',
            'plan_id' => 'required|exists:pricing_plans,id',
            'payment_type' => 'required|integer',
            'duration' => 'nullable|exists:plan_durations,id',
            'coupon_code' => 'nullable|exists:promo_codes,code',
        ]);

        if ($validator->fails()) {
            http_response_code(200);
                echo json_encode([
                    'status' => (string) 0,
                    'message' => $message = $validator->errors()->first(),
                    'oData' => (object) [],
                    'errors' => (object) $validator->messages(),
                ]);
                exit;
        }

        $user = $this->validateAccesToken($request->access_token);

        $cart = $this->process_cart($request);

        if($cart['grand_total'] > 0){
            \Stripe\Stripe::setApiKey(env('STRIPE_SECRET'));
            // $checkout_session = \Stripe\PaymentIntent::create([
            //     'amount' => $cart['grand_total'] * 100,
            //     'currency' => $cart['currency'],
            //     'description' => 'Plan Purchase',
            //     'shipping' => [
            //         'name' => $user->first_name??'' . ' ' . $user->last_name??'',
            //         'address' => [
            //             'line1' => '',
            //             'state' => '',
            //             'city' => '',
            //             'country' => '',
            //         ],
            //     ],
            // ]);

            //  $ref = $checkout_session->id;
            $paymentIntent = \Stripe\PaymentIntent::create([
                                'amount' => (int)round($cart['grand_total'] * 100,2), // amount in cents/paise
                                'currency' => 'AED',
                            ]);
            $ref = $paymentIntent->client_secret;
            //$ref = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 10);
            $invoice_id = $user->id . uniqid() . time();
            $paymentreport = [
                'transaction_id' => $invoice_id,
                'payment_status' => 'Pending',
                'user_id' => $user->id,
                'ref_id' => $ref,
                'amount' => $cart['grand_total'],
                'method_type' => $request->payment_type,
                'ad_id' => $request->ad_id,
            ];

            PaymentReport::insert($paymentreport);
            $o_data['payment_ref'] = $ref;//substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 10);;
            $o_data['invoice_id'] = $invoice_id;
        } else {
            $o_data['payment_ref'] = '';
            $o_data['invoice_id'] = '';
        }

        $tempOrder = TempOrder::create([
            'ad_id' => $request->ad_id,
            'user_id' => $user->id,
            'plan_id' => $request->plan_id,
            'duration_id' => $request->duration??null,
            'payment_method' => $request->payment_type,
            'total_price' => $cart['cart_total'],
            'currency' => 'AED',
            'discount' => $cart['discount_amount'],
            'promo_code' => $request->coupon_code,
            'grand_total' => $cart['grand_total'],
            'transaction_id' => $o_data['invoice_id'],
            'duration' => $cart['duration_period'],
        ]);

        $o_data['order_id'] = $tempOrder->id;

        $status = (string) 1;
        $message = "";

        return response()->json(['status' => $status, 'message' => $message, 'errors' => (object) $errors, 'oData' => (object)$o_data]);
    }

    public function paymentFailure(Request $request)
    {
        $status = (string) 0;
        $message = "Payment failed";
        $o_data = [];
        $errors = [];

        $validator = Validator::make($request->all(), [
            'transaction_id' => 'required|exists:payment_reports,transaction_id',
        ]);

        if ($validator->fails()) {
            $status = (string) 0;
            $message = "Validation error occured";
            $errors = $validator->messages();
        } else {
            $paymentReport = PaymentReport::where('transaction_id', $request->transaction_id)->first();
            if($paymentReport){
                $paymentReport->update(['payment_status' => 'Failed']);

                $status = (string) 1;
                $message = "Payment failed";
                $o_data['payment_ref'] = '';
                $o_data['invoice_id'] = $paymentReport->transaction_id;
            }
        }

        return response()->json(['status' => $status, 'message' => $message, 'errors' => (object) $errors, 'oData' => (object)$o_data]);
    }

    public function paymentCancel(Request $request)
    {
        $status = (string) 0;
        $message = "Payment cancelled";
        $o_data = [];
        $errors = [];

        $validator = Validator::make($request->all(), [
            'transaction_id' => 'required|exists:payment_reports,transaction_id',
        ]);

        if ($validator->fails()) {
            $status = (string) 0;
            $message = "Validation error occured";
            $errors = $validator->messages();
        } else {
            $paymentReport = PaymentReport::where('transaction_id', $request->transaction_id)->first();
            if($paymentReport){
                $paymentReport->update(['payment_status' => 'Cancelled']);
                $status = (string) 1;
                $message = "Payment cancelled";
                $o_data['payment_ref'] = '';
                $o_data['invoice_id'] = $paymentReport->transaction_id;
            }
        }

        return response()->json(['status' => $status, 'message' => $message, 'errors' => (object) $errors, 'oData' => (object)$o_data]);
    }

    public function paymentSuccess(Request $request)
    {
        $status = (string) 0;
        $message = "Unable to place the order";
        $o_data = [];
        $errors = [];

        $validator = Validator::make($request->all(), [
            'access_token' => 'required',
            'order_id' => 'required|exists:temp_orders,id',
        ]);

        if ($validator->fails()) {
            http_response_code(200);
            echo json_encode([
                'status' => (string) 0,
                'message' => "Validation error occured",
                'oData' => (object) [],
                'errors' => (object) $validator->messages(),
            ]);
            exit;
        }

        $user = $this->validateAccesToken($request->access_token);

        $tempOrder = TempOrder::where('id', $request->order_id)->first();
        $paymentReport = PaymentReport::where('transaction_id', $tempOrder->transaction_id)->first();
        if($paymentReport){
            $paymentReport->update(['payment_status' => 'Success']);
        }



        switch ($tempOrder->duration) {
            case 'monthly':
            $expiryDate = now()->addMonth();
            break;
            case 'quarterly':
            $expiryDate = now()->addMonths(3);
            break;
            case 'yearly':
            $expiryDate = now()->addYear();
            break;
            default:
            $expiryDate = now(); // Default to current date if duration is invalid
            break;
        }

        // dd([
        //     'name' => $tempOrder->plan->name,
        //     'plan_id' => $tempOrder->plan_id,
        //     'duration_id' => $tempOrder->duration_id,
        //     'user_id' => $tempOrder->user_id,
        //     'payment_method' => $tempOrder->payment_method,
        //     'total_price' => $tempOrder->total_price,
        //     'currency' => $tempOrder->currency,
        //     'discount' => $tempOrder->discount,
        //     'promo_code' => $tempOrder->promo_code,
        //     'price' => $tempOrder->grand_total,
        //     'payment_id' => $paymentReport->id??null,
        //     'expiry_date' => $expiryDate,
        // ]);
        $adPlan = UserPlan::create([
            'name' => $tempOrder->plan->name,
            'name_ar' => $tempOrder->plan->name_ar,
            'type' => $tempOrder->plan->type,
            'duration' => $tempOrder->plan->duration,
            'description' => $tempOrder->plan->description,
            'description_ar' => $tempOrder->plan->description_ar,
            'plan_id' => $tempOrder->plan_id,
            'duration_id' => $tempOrder->duration_id,
            'user_id' => $tempOrder->user_id,
            'payment_method' => $tempOrder->payment_method,
            'total_price' => $tempOrder->total_price,
            'currency' => $tempOrder->currency,
            'discount' => $tempOrder->discount,
            'promo_code' => $tempOrder->promo_code,
            'price' => $tempOrder->grand_total,
            'payment_id' => $paymentReport->id??null,
            'expiry_date' => $expiryDate,
            'status' => 1,
            'request_count' => $tempOrder->plan->max_request_count,
        ]);

        $usX = User::find($tempOrder->user_id);
        $usX->active_request_count = $tempOrder->plan->max_request_count;
        $usX->save();
        UserPlan::where('user_id', $tempOrder->user_id)->whereNotIn('id',[$adPlan->id])->update(['status' => 0]);

        $ad_id = $tempOrder->ad_id;

        $tempOrder->delete();
        $status = (string) 1;
        $message = "Membership updated successfully";
        $o_data['invoice_id'] = $paymentReport->transaction_id??null;
        $o_data['payment_ref'] = $paymentReport->ref_id??null;
        $o_data['order_id'] = $adPlan->id;
        $o_data['user_id'] = $tempOrder->user_id;

        $name = $user->name;

        if($user->gender == GENDER_FEMALE && $user->parent_approval == 0){
            $parentToken = bin2hex(random_bytes(8));
            $pemail = $user->parent_email??'info@luqia.ae';
            $pname = $user->parent_name;
            ParentApproval::create([
                'user_id' => $user->id,
                'name' => $user->parent_name,
                'email' => $user->parent_email,
                'token' => $parentToken,
                'gardien_phone_dial_code' => $user->gardien_phone_dial_code,
                'gardien_phone_number' => $user->gardien_phone_number
            ]);
            if (config('global.server_mode') == 'local') {
                \Artisan::call("send:parent_verification_email --uri=" . urlencode("Parental Approval Request for Luqia Matrimonial App Registration") . " --uri2=" . urlencode($pemail) . " --uri3=" . urlencode($name)." --uri4=" . urlencode($parentToken)." --uri5=" . urlencode($pname)." --user_id=".$user->id);
             } else {
                exec("php " . base_path() . "/artisan send:parent_verification_email --uri=" . urlencode("Parental Approval Request for Luqia Matrimonial App Registration") . " --uri2=" . urlencode($pemail) . " --uri3=" . urlencode($name)." --uri4=" . urlencode($parentToken) . " --uri5=" . urlencode($pname) . " --user_id=" . $user->id . " > /dev/null 2>&1 & ");
             }
        }

        // if (config('global.server_mode') == 'local') {
        //     \Artisan::call("send:send_ad_posted_email --uri=" . urlencode("Your Ad Has Been Successfully Posted on Luqia!") . " --uri2=" . urlencode($user->email) . " --uri3=" . urlencode($name). " --uri4=" . $ad_id);
        // } else {
        //     exec("php " . base_path() . "/artisan send:send_ad_posted_email --uri=" . urlencode("Your Ad Has Been Successfully Posted on Luqia!") . " --uri2=" . urlencode($user->email) . " --uri3=" . urlencode($name). " --uri4=" . $ad_id . " > /dev/null 2>&1 & ");
        // }

        return response()->json(['status' => $status, 'message' => $message, 'errors' => (object) $errors, 'oData' => (object)$o_data]);
    }
}