<?php

namespace App\Http\Controllers\Traits;

use Illuminate\Http\Request;
use App\Models\Plan;
use App\Models\Order;
use App\Models\Subscription;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Traits\AdminAuthTrait;
use App\Http\Controllers\Traits\EmailTrait;
use App\Models\User;


trait PlanTrait
{
    use AdminAuthTrait;
    use EmailTrait;

    /**
     * Safely format a date for logging
     *
     * @param mixed $date
     * @param string $format
     * @return string
     */
    private function safeFormatDate($date, $format = 'Y-m-d H:i:s')
    {
        if (!$date) {
            return 'null';
        }
        if ($date instanceof \Carbon\Carbon) {
            return $date->format($format);
        }
        // If it's a string, try to parse it first
        try {
            return \Carbon\Carbon::parse($date)->format($format);
        } catch (\Exception $e) {
            return (string) $date;
        }
    }

    protected function storePlan($request)
    {
        $validator = $this->subscriptionPlanValidationRequest($request);
        if ($validator->fails()) {
            return $this->handleValidationFailure($validator);
        }
        $validationData = $validator->validated();
        $plan = Plan::create($validationData);

        return $this->success($plan, 'Plan created successfully');
    }

    protected function showPlan($plan)
    {
        $plan = Plan::find($plan);
        if (!$plan) {
            return $this->message('Plan not found');
        }
        return $this->success($plan, 'Plan retrieved successfully');
    }

    protected function updatePlan($request)
    {
        $validator = $this->subscriptionPlanValidationRequest($request);
        if ($validator->fails()) {
            return $this->handleValidationFailure($validator);
        }
        $validationData = $validator->validated();
        $plan = Plan::find($request->id);
        if (!$plan) {
            return $this->message('Plan not found');
        }
        $plan->update($validationData);
        return $this->success($plan, 'Plan updated successfully');
    }

    protected function destroyPlan($plan)
    {
        $plan = Plan::find($plan);
        if (!$plan) {
            return $this->message('Plan not found');
        }
        $plan->delete();
        return $this->message('Plan deleted successfully');
    }

    protected function customerSubscriptionRequest($request)
    {

        $validator = $this->customerSubscriptionRequestValidationRequest($request);
        if ($validator->fails()) {
            return $this->handleValidationFailure($validator);
        }
        $validationData = $validator->validated();
        $image = $this->handleFileImageUpload($request, 'order');
        if ($image) {
            $validationData['receipt'] = $image['path'] ?? null;
        }
        // Check for existing active subscription
        $userId = Auth::id();
        $existingSubscription = Subscription::where('user_id', $userId)
            ->where(function ($query) {
                $query->where('stripe_status', 'active')
                    ->orWhere('stripe_status', 'trialing');
            })
            ->where(function ($query) {
                // Exclude subscriptions that are already marked for cancellation
                $query->where('cancel_at_period_end', false)
                    ->orWhereNull('cancel_at_period_end');
            })
            ->first();

        // If there's an existing subscription, handle plan switching
        if ($existingSubscription) {
            try {
                // Cancel the existing subscription at period end
                $this->cancelSubscription($existingSubscription->stripe_id, true);
                // Update the existing subscription record
                $existingSubscription->ends_at = now()->addDays($existingSubscription->daysRemaining());
                $existingSubscription->stripe_status = 'canceled';
                $existingSubscription->cancel_at_period_end = true;
                $existingSubscription->save();
            } catch (\Exception $e) {
                Log::error('Error handling existing subscription: ' . $e->getMessage());
                return $this->error('Failed to process subscription change: ' . $e->getMessage(), 500);
            }
        }
        $orderId = $this->generateOrderId();
        $originalPrice = $validationData['price'] ?? 0;
        $finalPrice = $originalPrice;
        $couponData = [
            'coupon_applied' => false,
            'success' => true,
            'discount_amount' => 0,
            'coupon_code' => null,
            'coupon_id' => null,
            'message' => null,
            'final_price' => $originalPrice
        ];
        // Process coupon if provided
        if (isset($request->coupon_code) && !empty($request->coupon_code)) {
            $planIds = isset($validationData['plan_id']) ? [$validationData['plan_id']] : [];
            if (isset($request->planIds) && is_array($request->planIds)) {
                $planIds = $request->planIds;
            }
            $couponData = $this->processCouponFromRequest($request, $originalPrice, $planIds);
            if (!$couponData['success']) {
                return $this->error($couponData['message'], 422);
            }
            if ($couponData['coupon_applied']) {
                $finalPrice = $couponData['final_price'];
            }
        }
        // Check if this is a recurring subscription
        $isRecurring = false;
        if (isset($validationData['is_recurring'])) {
            if (
                $validationData['is_recurring'] === true ||
                $validationData['is_recurring'] === 1 ||
                $validationData['is_recurring'] === '1' ||
                strtolower($validationData['is_recurring']) === 'true'
            ) {
                $isRecurring = true;
            }
        }
        // Get the plan to check if it's a free plan
        $plan = Plan::find($validationData['plan_id']);
        if (!$plan) {
            return $this->error('Plan not found', 404);
        }
        // Handle free plan logic early - auto-approve free plans for first-time users
        $isFreeAndAutoApproved = false;
        if ($plan->is_free_plan == 1) {
            $hasPreviousFreePlan = User::where('id', $userId)
                ->where('free_plan', 1)
                ->exists();
            if ($hasPreviousFreePlan) {
                return $this->error('You have already used a free plan previously. Please choose a paid plan.', 422);
            }
            // For free plans, automatically set payment status to completed
            $isFreeAndAutoApproved = true;
            $finalPrice = 0; // Free plans should have 0 price
            Log::info('Auto-approving free plan for first-time user', [
                'user_id' => $userId,
                'plan_id' => $plan->id,
                'plan_name' => $plan->name
            ]);
        }
        // Create order with updated price from coupon (if applied)
        $orderData = [
            'name' => $validationData['name'] ?? null,
            'email' => $validationData['email'] ?? null,
            'order_id' => $orderId,
            'plan_name' => $plan->name ?? $validationData['plan_name'] ?? null,
            'plan_id' => $validationData['plan_id'] ?? null,
            'is_recurring' => $isRecurring,
            'price' => $finalPrice,
            'original_price' => $originalPrice,
            'price_curency' => $validationData['price_curency'] ?? null,
            'payment_status' => $isFreeAndAutoApproved ? config('constants.payment_statuses.completed') : ($validationData['payment_status'] ?? 0),
            'receipt' => $validationData['receipt'] ?? null,
            'txn_id' => $isFreeAndAutoApproved ? 'FREE_PLAN_' . $orderId : ($validationData['txn_id'] ?? 0),
            'user_id' => $userId,
            'payment_type' => $isFreeAndAutoApproved ? config('constants.payment_types.stripe') : ($validationData['payment_type'] ?? config('constants.payment_types.bank')),
            'interval' => $validationData['interval'] ?? null,
            'is_refund' => $validationData['is_refund'] ?? 0,
            'workspace' => Auth::user()->current_workspace_id ?? null,
            'refferal_code' => Auth::user()->referral_code_used ?? null,
        ];
        // Add coupon information to order if a coupon was applied
        if ($couponData['coupon_applied']) {
            $orderData['coupon_code'] = $couponData['coupon_code'];
            $orderData['discount_amount'] = $couponData['discount_amount'];
        }
        // Process stripe payment if the payment type is stripe AND it's not a free plan
        if ($validationData['payment_type'] == config('constants.payment_types.stripe') && !$isFreeAndAutoApproved) {
            $validationData['price'] = $finalPrice;
            $validationData['is_recurring'] = $isRecurring;
            $validationData['order_id'] = $orderId;
            // Get the plan information
            $plan = Plan::find($validationData['plan_id']);
            if ($plan) {
                $validationData['plan_name'] = $plan->name;
            }
            if ($isRecurring) {
                // Log the subscription creation attempt
                Log::info('Creating stripe subscription', [
                    'plan_id' => $validationData['plan_id'],
                    'amount' => $finalPrice,
                    'currency' => $validationData['price_curency'] ?? null
                ]);
                $stripeResult = $this->processStripeSubscription($request, $validationData);
            } else {
                // Log the one-time payment attempt
                Log::info('Processing one-time stripe payment', [
                    'plan_id' => $validationData['plan_id'],
                    'amount' => $finalPrice
                ]);
                $stripeResult = $this->processStripePayment($request, $validationData);
            }
            if ($stripeResult instanceof \Illuminate\Http\JsonResponse) {
                return $stripeResult;
            }
            $orderData['payment_status'] = config('constants.payment_statuses.completed');
            if ($isRecurring) {
                $orderData['stripe_subscription_id'] = $stripeResult['subscription']->id;
                // Fix for payment_intent access error
                if (
                    isset($stripeResult['subscription']->latest_invoice) &&
                    isset($stripeResult['subscription']->latest_invoice->payment_intent) &&
                    isset($stripeResult['subscription']->latest_invoice->payment_intent->id)
                ) {
                    $orderData['txn_id'] = $stripeResult['subscription']->latest_invoice->payment_intent->id;
                } else {
                    // Get the invoice ID as a fallback if payment_intent isn't available
                    $orderData['txn_id'] = $stripeResult['subscription']->latest_invoice->id ?? null;
                    Log::info('Using invoice ID as transaction ID. Payment intent not available.');
                }

                if (isset($stripeResult['price']->id)) {
                    $orderData['stripe_price_id'] = $stripeResult['price']->id;
                }
            } else {
                $orderData['txn_id'] = $stripeResult['charge']->id ?? null;
            }

            if (isset($stripeResult['customer']->id)) {
                $orderData['stripe_customer_id'] = $stripeResult['customer']->id;
            }
        }
        // Debug: Log order data before creation
        Log::info('COUPON DEBUG - Order Data Before Creation', [
            'order_id' => $orderData['order_id'],
            'price' => $orderData['price'],
            'original_price' => $orderData['original_price'],
            'coupon_code' => $orderData['coupon_code'] ?? 'No coupon',
            'discount_amount' => $orderData['discount_amount'] ?? 0,
            'plan_name' => $orderData['plan_name'],
            'finalPrice_variable' => $finalPrice,
            'originalPrice_variable' => $originalPrice,
            'coupon_applied' => $couponData['coupon_applied']
        ]);
        // Create the order in the database
        $order = Order::create($orderData);
        if (!$order) {
            return $this->error("Order creation failed", 500);
        }
        // Debug: Log order details after creation
        Log::info('COUPON DEBUG - Order Details After Creation', [
            'order_id' => $order->order_id,
            'price' => $order->price,
            'original_price' => $order->original_price,
            'coupon_code' => $order->coupon_code ?? 'No coupon',
            'discount_amount' => $order->discount_amount ?? 0,
            'plan_name' => $order->plan_name
        ]);
        // Create subscription record if this is a recurring order
        if ($isRecurring && isset($stripeResult['subscription'])) {
            $subscription = $this->createSubscriptionRecord($order, $stripeResult);
            if (!$subscription) {
                return $this->error("Subscription record creation failed", 500);
            }
            // Debug: Log order details after subscription record creation
            Log::info('COUPON DEBUG - Order Details After Subscription Record Creation', [
                'order_id' => $order->order_id,
                'price' => $order->price,
                'original_price' => $order->original_price,
                'coupon_code' => $order->coupon_code ?? 'No coupon',
                'discount_amount' => $order->discount_amount ?? 0
            ]);
        }
        // Record coupon usage if coupon was applied
        if ($couponData['coupon_applied']) {
            $this->recordCouponUsage(
                $couponData['coupon_id'],
                $order->id,
                $couponData['discount_amount']
            );
        }
        // If payment type is bank transfer, send pending notification to customer
        if ($orderData['payment_type'] == config('constants.payment_types.bank')) {
            $this->sendBankTransferPendingEmail($order);
            // Send notification to admin
            $this->sendAdminPaymentNotification($order);
            // Send notifications for bank transfer subscription request
            $this->sendSubscriptionRequestNotifications($order, 'bank_transfer');
        }
        // If payment was processed, send a confirmation email
        else if ($orderData['payment_status'] == config('constants.payment_statuses.completed')) {
            if ($isRecurring) {
                $this->sendSubscriptionConfirmationEmail($order);
            } else {
                $this->sendPurchaseConfirmationEmail($order);
            }
            // Send notification to admin for completed payments too
            $this->sendAdminPaymentNotification($order);
            // Send notifications for successful stripe payment
            if ($orderData['payment_type'] == config('constants.payment_types.stripe')) {
                $this->sendSubscriptionRequestNotifications($order, 'stripe');
            }
        }
        // Get user and plan for further processing
        $user = Auth::user();
        // Plan already fetched earlier in the function
        // Only assign plan and permissions for completed payments (not bank transfers)
        if ($orderData['payment_status'] == config('constants.payment_statuses.completed')) {
            // Update user's active plan and expiry date
            User::where('id', $user->id)->update(['active_plan_id' => $validationData['plan_id']]);
            if ($isRecurring) {
                // For recurring subscriptions, set expiry date based on subscription period
                if (isset($stripeResult['subscription'])) {
                    $stripeSubscription = $stripeResult['subscription'];
                    // Log the raw Stripe data for debugging
                    Log::info('Raw Stripe subscription data for recurring plan', [
                        'user_id' => $user->id,
                        'current_period_end' => $stripeSubscription->current_period_end ?? 'not set',
                        'current_period_start' => $stripeSubscription->current_period_start ?? 'not set',
                        'status' => $stripeSubscription->status ?? 'not set'
                    ]);
                    // Validate the timestamp before using it
                    if (
                        isset($stripeSubscription->current_period_end) &&
                        $stripeSubscription->current_period_end > 1000000000
                    ) { // After year 2001
                        $currentPeriodEnd = Carbon::createFromTimestamp($stripeSubscription->current_period_end);
                        User::where('id', $user->id)->update(['plan_expire_date' => $currentPeriodEnd]);
                        Log::info('Set recurring plan expiry date from Stripe', [
                            'user_id' => $user->id,
                            'expiry_date' => $currentPeriodEnd->format('Y-m-d H:i:s'),
                            'timestamp' => $stripeSubscription->current_period_end
                        ]);
                    } else {
                        // Fallback to interval-based calculation
                        $interval = $validationData['interval'] ?? 1;
                        if ($interval <= 0) {
                            $interval = 1;
                        }
                        $expiryDate = now()->addMonths(is_numeric($interval) ? (int)$interval : 1);
                        User::where('id', $user->id)->update(['plan_expire_date' => $expiryDate]);
                        Log::warning('Invalid Stripe current_period_end, using interval fallback', [
                            'user_id' => $user->id,
                            'invalid_timestamp' => $stripeSubscription->current_period_end ?? 'null',
                            'interval' => $interval,
                            'expiry_date' => $expiryDate->format('Y-m-d H:i:s')
                        ]);
                    }
                } else {
                    // Fallback for recurring with no subscription data
                    $interval = $validationData['interval'] ?? 1;
                    if ($interval <= 0) {
                        $interval = 1;
                    }
                    $expiryDate = now()->addMonths(is_numeric($interval) ? (int)$interval : 1);
                    User::where('id', $user->id)->update(['plan_expire_date' => $expiryDate]);
                    Log::info('Set fallback recurring plan expiry date', [
                        'user_id' => $user->id,
                        'interval' => $interval,
                        'expiry_date' => $expiryDate->format('Y-m-d H:i:s')
                    ]);
                }
            } else {
                // For one-time purchases, set expiry date based on interval
                $expiryDate = null;
                // First check if we got the expiry date from Stripe
                if (isset($stripeResult['expiry_date']) && $stripeResult['expiry_date'] instanceof \Carbon\Carbon) {
                    $expiryDate = $stripeResult['expiry_date'];
                    Log::info('Using expiry date from Stripe result', [
                        'user_id' => $user->id,
                        'expiry_date' => $expiryDate->format('Y-m-d H:i:s')
                    ]);
                }
                // If not, calculate based on interval
                else if (isset($validationData['interval'])) {
                    $interval = $validationData['interval'];

                    // If interval is not numeric, try to extract a numeric value
                    if (!is_numeric($interval)) {
                        preg_match('/(\d+)/', $interval, $matches);
                        $interval = !empty($matches) ? (int)$matches[1] : 1;
                    }

                    $expiryDate = now()->addMonths((int)$interval);
                    Log::info('Calculated expiry date from interval', [
                        'user_id' => $user->id,
                        'interval' => $interval,
                        'expiry_date' => $expiryDate->format('Y-m-d H:i:s')
                    ]);
                }
                // Fallback to 1 month
                else {
                    $expiryDate = now()->addMonths(1);
                    Log::info('Using fallback expiry date (1 month)', [
                        'user_id' => $user->id,
                        'expiry_date' => $expiryDate->format('Y-m-d H:i:s')
                    ]);
                }
                // Update the user's expiry date
                User::where('id', $user->id)->update(['plan_expire_date' => $expiryDate]);
            }
            // Set appropriate expiry date for free plans
            if ($plan->is_free_plan == 1 && $isFreeAndAutoApproved) {
                // Free plans get 1 year expiry by default
                $freeExpiryDate = now()->addYear();
                User::where('id', $user->id)->update(['plan_expire_date' => $freeExpiryDate]);
                Log::info('Set free plan expiry date', [
                    'user_id' => $user->id,
                    'expiry_date' => $freeExpiryDate->format('Y-m-d H:i:s')
                ]);
            }
            // Handle free plan logic - set free_plan flag for approved free plans
            if ($plan->is_free_plan == 1) {
                // Validation was already done earlier, just set the flag
                $userModel = User::find($userId);
                if ($userModel && $userModel->free_plan == 0) {
                    $userModel->free_plan = 1;
                    $userModel->save();
                }
            }
            // Set active plan for completed payments
            $userModel = User::find($userId);
            if ($userModel && $userModel->active_plan_id != $plan->id) {
                $userModel->active_plan_id = $plan->id;
                $userModel->save();
            }
            // Refresh the user object to get the updated active_plan_id before creating roles and permissions
            $user = User::find($userId);
            // Log user state before creating permissions
            Log::info('User state before creating permissions', [
                'user_id' => $user->id,
                'active_plan_id' => $user->active_plan_id,
                'plan_expire_date' => $this->safeFormatDate($user->plan_expire_date),
                'user_type' => $user->user_type,
                'access_role' => $user->access_role ?? 'null'
            ]);
            // Create roles and permissions only for completed payments
            $this->createRolesAndPermissions($user);
            $permissions = $this->getUserPermissions($user);
            // Log permissions result
            Log::info('Permissions created for user', [
                'user_id' => $user->id,
                'permissions_count' => is_array($permissions) ? count($permissions) : 'not array',
                'permissions' => $permissions
            ]);
            if ($request->demo === 'true' || $request->demo === true) {
                (new \App\Http\Controllers\DemoController)->createDemoCustomer($user);
            }
        } else {
            // For pending payments (bank transfers), set default permissions
            $permissions = [];
            Log::info('Bank transfer payment pending admin approval', [
                'user_id' => $user->id,
                'order_id' => $order->order_id,
                'plan_id' => $validationData['plan_id']
            ]);
        }
        // Prepare response data
        $responseData = $order->toArray();
        if ($isRecurring && isset($subscription)) {
            $responseData['subscription'] = $subscription->toArray();
        }
        $responseData['permissions'] = $permissions;
        // Add risk assessment information to response if available
        if (isset($stripeResult['risk_assessment'])) {
            $responseData['risk_assessment'] = [
                'risk_score' => $stripeResult['risk_assessment']['risk_score'],
                'risk_level' => $stripeResult['risk_assessment']['risk_level'],
                'requires_3ds' => $stripeResult['risk_assessment']['requires_3ds'],
                'max_amount_allowed' => $stripeResult['risk_assessment']['max_amount_allowed'],
                'recommended_actions' => $stripeResult['risk_assessment']['recommended_actions']
            ];
        }
        // Add coupon information to response if applied
        if ($couponData['coupon_applied']) {
            $responseData = array_merge(
                $responseData,
                [
                    'coupon' => [
                        'code' => $couponData['coupon_code'],
                        'discount_amount' => $couponData['discount_amount'],
                        'message' => $couponData['message']
                    ]
                ]
            );
        }
        // Determine appropriate message based on payment type and status
        if ($isFreeAndAutoApproved) {
            $message = "Free plan activated successfully! Welcome to your new plan.";
        } elseif ($orderData['payment_type'] == config('constants.payment_types.bank')) {
            $message = "Bank transfer request submitted successfully. Your plan will be activated after admin approval.";
        } else {
            $message = $isRecurring ? "Subscription created successfully" : "Order created successfully";
            if ($couponData['coupon_applied']) {
                $message .= " with coupon applied";
            }
        }

        if($user->referral_code == null){
        $user->referral_code = $user->generateReferralCode();
        $user->status = 'active';
            $user->active_status = 1;
            $user->is_enable_login = 1;
            $user->save();
        }
        // Handle referral commission creation for completed payments
        if ($orderData['payment_status'] == config('constants.payment_statuses.completed')) {
            $this->createReferralCommission($user, $order, $finalPrice);
        }

        return $this->success($responseData, $message);
    }

    /**
     * Create referral commission for completed purchases
     */
    protected function createReferralCommission($user, $order, $planPrice)
    {

        if (!$user->referred_by) {
            return;
        }

        $referralUser = User::find($user->referred_by);
        if (!$referralUser) {
            return;
        }


        if (!$referralUser->isReferralUser()) {
            return;
        }

        $settings = \App\Models\ReferralSetting::getActive();

        if (!$settings) {
            return;
        }

        $commissionAmount = $settings->calculateCommission($planPrice);

        // Check if plan price amount meets the payout threshold
        if ($planPrice < $settings->payout_threshold) {
            return;
        }

        $commission = \App\Models\ReferralCommission::create([
            'referral_user_id' => $referralUser->id,
            'customer_id' => $user->id,
            'order_id' => $order->order_id,
            'plan_price' => $planPrice,
            'commission_rate' => $settings->commission_value,
            'commission_amount' => $commissionAmount,
            'status' => 'approved',
        ]);

    }
    protected function createSubscriptionRecord($order, $stripeResult)
    {
        try {
            $stripeSubscription = $stripeResult['subscription'];
            $stripeCustomer = $stripeResult['customer'];
            $stripeProduct = $stripeResult['product'];
            $stripePrice = $stripeResult['price'];

            // Log complete stripe subscription data for debugging
            Log::info('Processing stripe subscription data for record creation', [
                'subscription_id' => $stripeSubscription->id,
                'subscription_status' => $stripeSubscription->status,
                'has_latest_invoice' => isset($stripeSubscription->latest_invoice),
                'has_payment_intent' => isset($stripeSubscription->latest_invoice->payment_intent),
                'current_period_end' => $stripeSubscription->current_period_end ?? 'not available'
            ]);

            // Get the current period dates
            $currentPeriodStart = null;
            $currentPeriodEnd = null;

            // Log the raw values for debugging
            Log::info('Raw Stripe subscription period data', [
                'current_period_start' => $stripeSubscription->current_period_start ?? 'not set',
                'current_period_end' => $stripeSubscription->current_period_end ?? 'not set',
                'current_period_start_type' => gettype($stripeSubscription->current_period_start ?? null),
                'current_period_end_type' => gettype($stripeSubscription->current_period_end ?? null),
                'order_interval' => $order->interval ?? 'not set',
                'order_id' => $order->id,
                'user_id' => $order->user_id
            ]);

            if (isset($stripeSubscription->current_period_start) && $stripeSubscription->current_period_start > 0) {
                $currentPeriodStart = Carbon::createFromTimestamp($stripeSubscription->current_period_start);
                Log::info('Set current_period_start from Stripe', [
                    'timestamp' => $stripeSubscription->current_period_start,
                    'date' => $currentPeriodStart->format('Y-m-d H:i:s')
                ]);
            } else {
                $currentPeriodStart = now();
                Log::info('Set current_period_start to now', [
                    'date' => $currentPeriodStart->format('Y-m-d H:i:s')
                ]);
            }

            if (isset($stripeSubscription->current_period_end) && $stripeSubscription->current_period_end > 0) {
                try {
                    // Validate that the timestamp is reasonable (not in 1970s)
                    if ($stripeSubscription->current_period_end > 1000000000) { // After year 2001
                        $currentPeriodEnd = Carbon::createFromTimestamp($stripeSubscription->current_period_end);
                        Log::info('Set current_period_end from Stripe', [
                            'timestamp' => $stripeSubscription->current_period_end,
                            'date' => $currentPeriodEnd->format('Y-m-d H:i:s')
                        ]);
                    } else {
                        throw new \Exception('Invalid timestamp - too old');
                    }
                } catch (\Exception $e) {
                    Log::warning('Invalid current_period_end timestamp, calculating from interval', [
                        'timestamp' => $stripeSubscription->current_period_end,
                        'error' => $e->getMessage()
                    ]);

                    // Fall back to calculation
                    $interval = $order->interval ?? 1;

                    // Ensure interval is at least 1
                    if ($interval <= 0) {
                        $interval = 1;
                        Log::warning('Invalid interval in fallback, defaulting to 1', [
                            'original_interval' => $order->interval,
                            'user_id' => $order->user_id,
                            'order_id' => $order->id
                        ]);
                    }

                    $currentPeriodEnd = now()->addMonths($interval);
                    Log::info('Calculated current_period_end from interval (fallback)', [
                        'interval' => $interval,
                        'date' => $currentPeriodEnd->format('Y-m-d H:i:s'),
                        'order_interval' => $order->interval
                    ]);
                }
            } else {
                // If current_period_end is not available, calculate it based on interval
                $interval = $order->interval ?? 1;

                // Ensure interval is at least 1
                if ($interval <= 0) {
                    $interval = 1;
                    Log::warning('Invalid interval, defaulting to 1', [
                        'original_interval' => $order->interval,
                        'user_id' => $order->user_id,
                        'order_id' => $order->id
                    ]);
                }

                // Use current_period_start as base if available, otherwise use now()
                $baseDate = $currentPeriodStart ? $currentPeriodStart : now();
                $currentPeriodEnd = $baseDate->copy()->addMonths($interval);

                Log::info('Calculated current_period_end from interval', [
                    'interval' => $interval,
                    'base_date' => $baseDate->format('Y-m-d H:i:s'),
                    'calculated_date' => $currentPeriodEnd->format('Y-m-d H:i:s'),
                    'order_interval' => $order->interval
                ]);
            }

            // Create or update subscription record
            $subscription = Subscription::updateOrCreate(
                ['stripe_id' => $stripeSubscription->id],
                [
                    'user_id' => $order->user_id,
                    'order_id' => $order->id,
                    'plan_id' => $order->plan_id,
                    'name' => $order->plan_name,
                    'stripe_status' => $stripeSubscription->status,
                    'stripe_price' => $stripePrice->id,
                    'stripe_product' => $stripeProduct->id,
                    'stripe_customer' => $stripeCustomer->id,
                    'quantity' => $stripeSubscription->items->data[0]->quantity ?? 1,
                    'current_period_start' => $currentPeriodStart,
                    'current_period_end' => $currentPeriodEnd,
                    'cancel_at_period_end' => $stripeSubscription->cancel_at_period_end ?? false,
                    'interval' => $order->interval,
                    'amount' => $order->price,
                    'currency' => $order->price_curency,
                    'is_recurring' => true,
                    'metadata' => [
                        'stripe_subscription_id' => $stripeSubscription->id,
                        'stripe_customer_id' => $stripeCustomer->id,
                        'stripe_price_id' => $stripePrice->id,
                        'stripe_product_id' => $stripeProduct->id,
                        'order_id' => $order->id,
                        'created_at' => now()->toIso8601String()
                    ]
                ]
            );

            // Update the order with subscription information
            $order->stripe_subscription_id = $stripeSubscription->id;
            $order->stripe_customer_id = $stripeCustomer->id;
            $order->stripe_price_id = $stripePrice->id;
            $order->save();

            // Update user's active plan and expiry date for subscription
            $user = User::find($order->user_id);
            if ($user) {
                $user->active_plan_id = $order->plan_id;

                // Validate the date before saving
                if ($currentPeriodEnd && $currentPeriodEnd->year > 1970) {
                    $user->plan_expire_date = $currentPeriodEnd;
                    Log::info('Using valid currentPeriodEnd for user', [
                        'user_id' => $user->id,
                        'date' => $currentPeriodEnd->format('Y-m-d H:i:s')
                    ]);
                } else {
                    // Fallback to a reasonable date if the calculated date is invalid
                    $fallbackInterval = $order->interval ?? 1;
                    if ($fallbackInterval <= 0) {
                        $fallbackInterval = 1;
                    }

                    $user->plan_expire_date = now()->addMonths($fallbackInterval);
                    Log::warning('Invalid currentPeriodEnd, using fallback date', [
                        'user_id' => $user->id,
                        'invalid_date' => $currentPeriodEnd ? $currentPeriodEnd->format('Y-m-d H:i:s') : 'null',
                        'fallback_interval' => $fallbackInterval,
                        'fallback_date' => $this->safeFormatDate($user->plan_expire_date)
                    ]);
                }

                $user->save();

                Log::info('Updated user with subscription plan details', [
                    'user_id' => $user->id,
                    'active_plan_id' => $user->active_plan_id,
                    'plan_expire_date' => $this->safeFormatDate($user->plan_expire_date),
                    'plan_expire_date_raw' => $user->plan_expire_date,
                    'currentPeriodEnd' => $currentPeriodEnd ? $currentPeriodEnd->format('Y-m-d H:i:s') : 'null',
                    'currentPeriodEnd_raw' => $currentPeriodEnd,
                    'subscription_id' => $subscription->id
                ]);
            }

            // Log successful subscription creation
            Log::info('Created subscription record', [
                'subscription_id' => $subscription->id,
                'stripe_subscription_id' => $stripeSubscription->id,
                'user_id' => $order->user_id,
                'plan_id' => $order->plan_id
            ]);

            return $subscription;
        } catch (\Exception $e) {
            Log::error('Failed to create subscription record: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
            return null;
        }
    }

    /**
     * Send a subscription confirmation email
     *
     * @param Order $order
     * @return void
     */
    protected function sendSubscriptionConfirmationEmail($order)
    {
        try {
            $subscription = Subscription::where('order_id', $order->id)->first();
            if (!$subscription) {
                Log::error('Subscription not found for order: ' . $order->order_id);
                return;
            }

            $user = \App\Models\User::find($order->user_id);
            if (!$user) {
                Log::error('User not found for order: ' . $order->order_id);
                return;
            }

            // Determine next billing date with validation and fallbacks
            $nextBillingDate = null;

            // Try to get a valid next billing date from subscription
            if ($subscription->current_period_end) {
                try {
                    if ($subscription->current_period_end instanceof \Carbon\Carbon) {
                        if ($subscription->current_period_end->year > 1970) {
                            $nextBillingDate = $subscription->current_period_end;
                        }
                    } else {
                        // Parse the date string
                        $parsedDate = Carbon::parse($subscription->current_period_end);
                        if ($parsedDate->year > 1970) {
                            $nextBillingDate = $parsedDate;
                        }
                    }
                } catch (\Exception $e) {
                    Log::error('Error parsing next billing date: ' . $e->getMessage());
                    $nextBillingDate = null;
                }
            }

            // If next billing date couldn't be determined, calculate it
            if (!$nextBillingDate) {
                $interval = $order->interval ?? 1;

                // Ensure interval is numeric
                if (!is_numeric($interval)) {
                    preg_match('/(\d+)/', $interval, $matches);
                    $interval = !empty($matches) ? (int)$matches[1] : 1;
                }

                $nextBillingDate = now()->addMonths((int)$interval);

                // Update the subscription's current_period_end if it was invalid
                if ($subscription) {
                    Log::info('Updating invalid current_period_end for subscription: ' . $subscription->id);
                    $subscription->current_period_end = $nextBillingDate;
                    $subscription->save();
                }
            }

            // Format the date for the email
            $nextBillingDateFormatted = $nextBillingDate->format('Y-m-d');

            Log::info('Using next billing date in subscription confirmation email: ' . $nextBillingDateFormatted);

            // Debug: Log order pricing details before sending email
            Log::info('COUPON DEBUG - Subscription Email Order Details', [
                'order_id' => $order->order_id,
                'price' => $order->price,
                'original_price' => $order->original_price,
                'coupon_code' => $order->coupon_code ?? 'No coupon',
                'discount_amount' => $order->discount_amount ?? 0,
                'plan_name' => $order->plan_name
            ]);

            $emailParams = [
                'to' => $user->email,
                'subject' => 'Your Subscription has been Activated',
                'msg' => view('Emails.subscription-confirmation', [
                    'subject' => 'Your Subscription has been Activated',
                    'name' => $user->name ?? $order->name,
                    'plan_name' => $order->plan_name,
                    'order_id' => $order->order_id,
                    'price' => $order->price,
                    'original_price' => $order->original_price,
                    'discount_amount' => $order->discount_amount ?? 0,
                    'coupon_code' => $order->coupon_code ?? null,
                    'currency' => $order->price_curency,
                    'interval' => $order->interval,
                    'next_billing_date' => $nextBillingDateFormatted
                ])->render()
            ];

            $emailSent = $this->SendInstantEmail($emailParams);
            if (!$emailSent) {
                Log::error('Failed to send subscription confirmation email for order: ' . $order->order_id);
                return $this->message('Failed to send confirmation email. Please try again later.', 500);
            }

            Log::info('Subscription confirmation email sent for order: ' . $order->order_id);
        } catch (\Exception $e) {
            Log::error('Error sending subscription confirmation email: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
        }
    }

    /**
     * Send a purchase confirmation email
     *
     * @param Order $order
     * @return void
     */
    protected function sendPurchaseConfirmationEmail($order)
    {
        try {
            $user = \App\Models\User::find($order->user_id);
            if (!$user) {
                Log::error('User not found for order: ' . $order->order_id);
                return;
            }

            // Determine expiry date with additional validation and fallbacks
            $expiryDate = null;

            // First check if user has a valid plan_expire_date
            if ($user->plan_expire_date) {
                try {
                    if ($user->plan_expire_date instanceof \Carbon\Carbon) {
                        if ($user->plan_expire_date->year > 1970) {
                            $expiryDate = $user->plan_expire_date;
                        }
                    } else {
                        // Parse the date string
                        $parsedDate = Carbon::parse($user->plan_expire_date);
                        if ($parsedDate->year > 1970) {
                            $expiryDate = $parsedDate;
                        }
                    }
                } catch (\Exception $e) {
                    Log::error('Error parsing plan expire date: ' . $e->getMessage());
                    $expiryDate = null;
                }
            }

            // If we couldn't get a valid date from the user model, calculate it from order data
            if (!$expiryDate) {
                $interval = $order->interval ?? 1;

                // Ensure interval is numeric
                if (!is_numeric($interval)) {
                    preg_match('/(\d+)/', $interval, $matches);
                    $interval = !empty($matches) ? (int)$matches[1] : 1;
                }

                $expiryDate = now()->addMonths((int)$interval);

                // Update the user's expiry date if it was invalid
                Log::info('Updating invalid plan expiry date for user: ' . $user->id . ' to ' . $expiryDate->format('Y-m-d'));
                User::where('id', $user->id)->update([
                    'plan_expire_date' => $expiryDate
                ]);
            }

            // Format the date for the email
            $expiryDateFormatted = $expiryDate->format('Y-m-d');

            Log::info('Using expiry date in purchase confirmation email: ' . $expiryDateFormatted);

            // Debug: Log order pricing details before sending email
            Log::info('COUPON DEBUG - Purchase Email Order Details', [
                'order_id' => $order->order_id,
                'price' => $order->price,
                'original_price' => $order->original_price,
                'coupon_code' => $order->coupon_code ?? 'No coupon',
                'discount_amount' => $order->discount_amount ?? 0,
                'plan_name' => $order->plan_name
            ]);

            $emailParams = [
                'to' => $user->email,
                'subject' => 'Your Purchase has been Confirmed',
                'msg' => view('Emails.purchase-confirmation', [
                    'subject' => 'Your Purchase has been Confirmed',
                    'name' => $user->name ?? $order->name,
                    'plan_name' => $order->plan_name,
                    'order_id' => $order->order_id,
                    'price' => $order->price,
                    'original_price' => $order->original_price,
                    'discount_amount' => $order->discount_amount ?? 0,
                    'coupon_code' => $order->coupon_code ?? null,
                    'currency' => $order->price_curency,
                    'interval' => $order->interval,
                    'expiry_date' => $expiryDateFormatted
                ])->render()
            ];

            $emailSent = $this->SendInstantEmail($emailParams);
            if (!$emailSent) {
                Log::error('Failed to send purchase confirmation email for order: ' . $order->order_id);
            } else {
                Log::info('Purchase confirmation email sent for order: ' . $order->order_id);
            }
        } catch (\Exception $e) {
            Log::error('Error sending purchase confirmation email: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
        }
    }

    protected function showbankTransferRequestList(Request $request)
    {
        // Build query for bank transfer orders
        $BankTransferQuery = Order::where('payment_type', config('constants.payment_types.bank'));
        
        // Add search functionality if search parameter is provided
        if ($request->filled('search')) {
            $search = $request->input('search');
            $BankTransferQuery->where(function($query) use ($search) {
                $query->where('order_id', 'like', '%' . $search . '%')  // Order ID
                      ->orWhere('name', 'like', '%' . $search . '%')  // Name
                      ->orWhere('email', 'like', '%' . $search . '%')  // Email
                      ->orWhere('plan_name', 'like', '%' . $search . '%')  // Plan Name
                      ->orWhere('price', 'like', '%' . $search . '%')  // Price
                      // Search in created_at date (format: Y-m-d or partial date)
                      ->orWhereRaw("DATE_FORMAT(created_at, '%Y-%m-%d') LIKE ?", ['%' . $search . '%'])
                      ->orWhereRaw("DATE_FORMAT(created_at, '%d-%m-%Y') LIKE ?", ['%' . $search . '%'])
                      ->orWhereRaw("DATE_FORMAT(created_at, '%m/%d/%Y') LIKE ?", ['%' . $search . '%']);
            });
        }
        
        $BankTransferQuery = $BankTransferQuery->latest()->get();
        
        
        if ($BankTransferQuery->isEmpty()) {
            return $this->message('Bank Request not found');
        }
        
        // Use transform() directly without toArray() conversion
        $BankTransferQuery->transform(function ($order) {
            if ($order->created_at) {
                $order->created_at = $order->created_at;
            }
            if ($order->updated_at) {
                $order->updated_at = $order->updated_at;
            }
            return $order;
        });
        return $this->success($BankTransferQuery, 'Bank Request retrieved successfully');
    }

    private function getSystemDateFormat()
    {
        try {
            $setting = \App\Models\Adminsettings::where('key', 'system_date_format')->where('customer_id', $this->getSuperAdminId())->first();
            if ($setting && $setting->value) {
                $formatMap = [
                    'mm-dd-yyyy' => 'm-d-Y',
                    'dd-mm-yyyy' => 'd-m-Y',
                    'yyyy-mm-dd' => 'Y-m-d',
                ];
                return $formatMap[strtolower($setting->value)] ?? 'd-m-Y';
            }
        } catch (\Exception $e) {
        }
        return 'd-m-Y'; // Default format
    }

    protected function handelShowRequestOrder(Request $request)
    {
        // Build query for orders
        $OrderQuery = Order::query();
        
        // Add search functionality if search parameter is provided
        if ($request->filled('search')) {
            $search = $request->input('search');
            $OrderQuery->where(function($query) use ($search) {
                $query->where('order_id', 'like', '%' . $search . '%')  // Order ID
                      ->orWhere('name', 'like', '%' . $search . '%')  // Name
                      ->orWhere('email', 'like', '%' . $search . '%')  // Email
                      ->orWhere('price', 'like', '%' . $search . '%')  // Price
                      ->orWhere('plan_name', 'like', '%' . $search . '%')  // Plan Name
                      // Search in created_at date (format: Y-m-d or partial date)
                      ->orWhereRaw("DATE_FORMAT(created_at, '%Y-%m-%d') LIKE ?", ['%' . $search . '%'])
                      ->orWhereRaw("DATE_FORMAT(created_at, '%d-%m-%Y') LIKE ?", ['%' . $search . '%'])
                      ->orWhereRaw("DATE_FORMAT(created_at, '%m/%d/%Y') LIKE ?", ['%' . $search . '%']);
            });
        }
        
        $Order = $OrderQuery->latest()->get();
        
        if ($Order->isEmpty()) {
            return $this->message('Order Request not found');
        }        
        $systemDateFormat = $this->getSystemDateFormat();
        // Use transform() directly on the Collection (no getCollection() needed)
        $Order->transform(function ($order) use ($systemDateFormat) {
            if ($order->created_at) {
                $order->created_at = $order->created_at;
            }
            if ($order->updated_at) {
                $order->updated_at = $order->updated_at;
            }
            // Hide modules from plan relationship if plan exists
            if ($order->plan) {
                $order->plan->makeHidden(['modules']);
            }
            return $order;
        });
        return $this->success($Order, 'Order Request retrieved successfully');
    }

    protected function handelbankTransferRequestDelete($id)
    {
        $Order = Order::find($id);
        if (!$Order) {
            return $this->message('Bank Transfer Request not found');
        }
        $Order->delete();
        return $this->message('Bank Transfer Request deleted successfully');
    }


    public function handelBankTransferRequestStatus($request)
    {
        $validator = $this->BankTransferRequestStatusValidationRequest($request);
        if ($validator->fails()) {
            return $this->handleValidationFailure($validator);
        }
        $Order = Order::find($request->bank_id);
        if (!$Order) {
            return $this->message('Bank Transfer Request not found');
        }
        $interval = $Order->interval;
        $plan_id =  $Order->plan_id;
        $price =  $Order->price;
        $customer_id = $Order->user_id; // Get customer ID from order instead of request

        // Store old status before updating
        $oldStatus = $Order->payment_status;

        $Order->payment_status = $request->status;
        $Order->save();
        $currentDate = Carbon::now();
        $expiryDate  = $currentDate->addMonths($interval)->format('Y-m-d');
        // Send notification to admin about the status change
        $this->sendAdminPaymentNotification($Order);

        // Send notifications for bank transfer status change
        $this->sendBankTransferStatusChangeNotifications($Order, $request->status);

        // Also send general payment status change notification
        $this->sendPaymentStatusChangeNotification($Order, $oldStatus, $request->status, 'bank_transfer');

        if ($request->status == 1) {
            // Send confirmation email based on whether this is a recurring subscription

            $request = new Request([
                'customer_id' => $customer_id,
                'plan_id' => $plan_id,
                'price' => $price,
                'expiration_date' => $expiryDate,
                'bank_id' => $Order->id,
            ]);
            return $this->handleAssignPlan($request);
        }
        // Send rejection notification when payment is rejected
        if ($request->status == 4) {
            $this->sendPaymentRejectionEmail($Order);
        }
        $user = User::find($customer_id);
        $plan = Plan::where('id', $plan_id)->first(); // Use plan_id from order instead of user's active_plan_id
        if ($plan && $plan->is_free_plan == 1) {
            $hasPreviousFreePlan = User::where('id', $customer_id)
                ->where('free_plan', 1)
                ->exists();

            if ($hasPreviousFreePlan) {
                return $this->error('You have already used a free plan previously. Please choose a paid plan.', 422);
            }

            if ($user && $user->free_plan == 0) {
                $user->free_plan = 1;
                $user->save();
            }
        }
        return $this->message('status update successfully');
    }

    /**
     * Send email notification to customer about pending bank transfer
     * 
     * @param Order $order
     * @return void
     */
    protected function sendBankTransferPendingEmail($order)
    {
        try {
            $user = \App\Models\User::find($order->user_id);
            if (!$user) {
                Log::error('User not found for order: ' . $order->order_id);
                return;
            }

            $plan = Plan::find($order->plan_id);
            if (!$plan) {
                Log::error('Plan not found for order: ' . $order->order_id);
                return;
            }

            $emailParams = [
                'to' => $user->email,
                'subject' => 'Your Bank Transfer Request is Pending - ' . env('APP_NAME'),
                'msg' => view('Emails.bank-transfer-pending', [
                    'subject' => 'Your Bank Transfer Request is Pending',
                    'name' => $user->name ?? $order->name,
                    'plan_name' => $order->plan_name ?? $plan->name,
                    'order_id' => $order->order_id,
                    'price' => $order->price,
                    'currency' => $order->price_curency ?? 'USD',
                    'interval' => $order->interval
                ])->render()
            ];

            $emailSent = $this->SendInstantEmail($emailParams);
            if (!$emailSent) {
                Log::error('Failed to send bank transfer pending email for order: ' . $order->order_id);
            } else {
                Log::info('Bank transfer pending email sent for order: ' . $order->order_id);
            }
        } catch (\Exception $e) {
            Log::error('Error sending bank transfer pending email: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
        }
    }

    /**
     * Send notification to admin about new payment/order
     *
     * @param Order $order
     * @return void
     */
    protected function sendAdminPaymentNotification($order)
    {
        try {
            // Get admin email from settings
            $admin = User::where('user_type', config('constants.user_types.admin'))->first();
            $adminEmail = DB::table('adminsettings')
                ->where('customer_id', $admin->id)
                ->where('key', 'company_company_sales_email')
                ->value('value');

            if (!$adminEmail) {
                Log::warning('Admin sales email not found in settings');
                return;
            }

            $user = \App\Models\User::find($order->user_id);
            $userName = $user ? $user->name : ($order->name ?? 'Customer');
            $userEmail = $user ? $user->email : ($order->email ?? 'Unknown');

            $plan = Plan::find($order->plan_id);
            $planName = $plan ? $plan->name : ($order->plan_name ?? 'Unknown Plan');

            // Get payment status from order or use the isPending parameter as fallback
            $paymentStatus = isset($order->payment_status) ? (int) $order->payment_status : config('constants.payment_statuses.completed');

            // Define status-specific content based on payment status
            $statusConfig = $this->getPaymentStatusConfig($paymentStatus);

            // Get a descriptive payment type name
            $paymentType = $this->getPaymentTypeName($order->payment_type ?? config('constants.payment_types.bank'), $paymentStatus);

            $subject = $statusConfig['subject'];

            $emailParams = [
                'to' => $adminEmail,
                'subject' => $subject . ' - WMS',
                'msg' => view('Emails.admin-payment-notification', [
                    'subject' => $subject,
                    'order_id' => $order->order_id,
                    'customer_name' => $userName,
                    'customer_email' => $userEmail,
                    'plan_name' => $planName,
                    'price' => $order->price,
                    'currency' => $order->price_curency ?? 'USD',
                    'payment_type' => $paymentType,
                    'is_recurring' => $order->is_recurring ? 'Yes' : 'No',
                    'interval' => $order->interval ?? '1',
                    'date' => now()->format('Y-m-d H:i:s'),
                    // Pass the payment status and configuration to the template
                    'payment_status' => $paymentStatus,
                    'status_config' => $statusConfig
                ])->render()
            ];

            $emailSent = $this->SendInstantEmail($emailParams);
            if (!$emailSent) {
                Log::error('Failed to send admin payment notification for order: ' . $order->order_id);
            } else {
                Log::info('Admin payment notification sent for order: ' . $order->order_id);
            }
        } catch (\Exception $e) {
            Log::error('Error sending admin payment notification: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
        }
    }

    /**
     * Send email notification to customer about rejected payment
     * 
     * @param Order $order
     * @return void
     */
    protected function sendPaymentRejectionEmail($order)
    {
        try {
            $user = \App\Models\User::find($order->user_id);
            if (!$user) {
                Log::error('User not found for order: ' . $order->order_id);
                return;
            }

            $plan = Plan::find($order->plan_id);
            if (!$plan) {
                Log::error('Plan not found for order: ' . $order->order_id);
                return;
            }

            // Get the status configuration for rejected payments
            $statusConfig = $this->getPaymentStatusConfig(config('constants.payment_statuses.rejected'));

            $emailParams = [
                'to' => $user->email,
                'subject' => 'Your Payment Request Has Been Rejected - ' . env('APP_NAME'),
                'msg' => view('Emails.payment-rejected', [
                    'subject' => 'Your Payment Request Has Been Rejected',
                    'name' => $user->name ?? $order->name,
                    'plan_name' => $order->plan_name ?? $plan->name,
                    'order_id' => $order->order_id,
                    'price' => $order->price,
                    'currency' => $order->price_curency ?? 'USD',
                    'interval' => $order->interval,
                    'payment_type' => $this->getPaymentTypeName($order->payment_type, $order->payment_status),
                    'status_config' => $statusConfig
                ])->render()
            ];

            $emailSent = $this->SendInstantEmail($emailParams);
            if (!$emailSent) {
                Log::error('Failed to send payment rejection email for order: ' . $order->order_id);
            } else {
                Log::info('Payment rejection email sent for order: ' . $order->order_id);
            }
        } catch (\Exception $e) {
            Log::error('Error sending payment rejection email: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
        }
    }

    /**
     * Send notifications for subscription requests to both customer and admin
     * 
     * @param Order $order
     * @param string $paymentMethod
     * @return void
     */
    protected function sendSubscriptionRequestNotifications($order, $paymentMethod)
    {
        try {
            $user = \App\Models\User::find($order->user_id);
            if (!$user) {
                Log::error('User not found for order: ' . $order->order_id);
                return;
            }

            $plan = Plan::find($order->plan_id);
            if (!$plan) {
                Log::error('Plan not found for order: ' . $order->order_id);
                return;
            }

            // Get admin users
            $adminUsers = \App\Models\User::where('user_type', config('constants.user_types.admin'))->get();

            // Prepare notification messages based on payment method
            if ($paymentMethod === 'bank_transfer') {
                $customerTitle = 'Subscription Request Submitted';
                $customerDescription = 'Your subscription request for ' . ($plan->name ?? 'the selected plan') . ' has been submitted successfully. Please wait for admin approval after bank transfer verification.';

                $adminTitle = 'New Bank Transfer Subscription Request';
                $adminDescription = 'Customer ' . ($user->name ?? 'Unknown') . ' has submitted a subscription request for ' . ($plan->name ?? 'the selected plan') . ' via bank transfer. Order ID: ' . $order->order_id;
            } else {
                $customerTitle = 'Subscription Activated Successfully';
                $customerDescription = 'Your subscription for ' . ($plan->name ?? 'the selected plan') . ' has been activated successfully via Stripe payment.';

                $adminTitle = 'New Stripe Subscription Request';
                $adminDescription = 'Customer ' . ($user->name ?? 'Unknown') . ' has successfully subscribed to ' . ($plan->name ?? 'the selected plan') . ' via Stripe. Order ID: ' . $order->order_id;
            }

            // Get first admin user for sender_id
            $adminUser = \App\Models\User::where('user_type', config('constants.user_types.admin'))->first();
            $adminId = $adminUser ? $adminUser->id : 0;

            // Send notification to customer
            $this->save_notifications(
                $customerTitle,
                $customerDescription,
                'admin', // sender_type
                $adminId, // sender_id (admin user ID)
                'customer', // receiver_type
                $user->id, // receiver_id
                'subscription_request', // type
                $user->id, // customer_id
                $user->current_workspace_id ?? null // workspace_id
            );

            // Send notifications to all admin users
            foreach ($adminUsers as $admin) {
                $this->save_notifications(
                    $adminTitle,
                    $adminDescription,
                    'admin', // sender_type
                    $adminId, // sender_id (admin user ID)
                    'admin', // receiver_type
                    $admin->id, // receiver_id
                    'subscription_request', // type
                    $adminId, // customer_id
                    $admin->current_workspace_id ?? null // workspace_id
                );
            }

            Log::info('Subscription request notification sent successfully', [
                'order_id' => $order->order_id,
                'payment_method' => $paymentMethod,
                'customer_id' => $user->id
            ]);
        } catch (\Exception $e) {
            Log::error('Error sending subscription request notifications: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
        }
    }

    /**
     * Send notifications for payment status changes to both customer and admin
     * 
     * @param Order $order
     * @param int $status
     * @return void
     */
    protected function sendBankTransferStatusChangeNotifications($order, $status)
    {
        try {
            $user = \App\Models\User::find($order->user_id);
            if (!$user) {
                Log::error('User not found for order: ' . $order->order_id);
                return;
            }

            $plan = Plan::find($order->plan_id);
            if (!$plan) {
                Log::error('Plan not found for order: ' . $order->order_id);
                return;
            }

            // Get admin users
            $adminUsers = \App\Models\User::where('user_type', config('constants.user_types.admin'))->get();

            // Prepare notification messages based on status
            switch ($status) {
                case 0: // Pending
                    $customerTitle = 'Payment Status: Pending';
                    $customerDescription = 'Your payment for ' . ($plan->name ?? 'the selected plan') . ' is currently pending. Please wait for processing or admin approval.';

                    $adminTitle = 'Payment Status Changed to Pending';
                    $adminDescription = 'Payment for customer ' . ($user->name ?? 'Unknown') . ' has been set to pending. Order ID: ' . $order->order_id;
                    break;

                case 1: // Completed/Approved
                    $customerTitle = 'Payment Approved';
                    $customerDescription = 'Your payment for ' . ($plan->name ?? 'the selected plan') . ' has been approved. Your subscription is now active.';

                    $adminTitle = 'Payment Approved';
                    $adminDescription = 'Payment for customer ' . ($user->name ?? 'Unknown') . ' has been approved. Order ID: ' . $order->order_id;
                    break;

                case 2: // Failed
                    $customerTitle = 'Payment Failed';
                    $customerDescription = 'Your payment for ' . ($plan->name ?? 'the selected plan') . ' has failed. Please try again or contact support for assistance.';

                    $adminTitle = 'Payment Failed';
                    $adminDescription = 'Payment for customer ' . ($user->name ?? 'Unknown') . ' has failed. Order ID: ' . $order->order_id;
                    break;

                case 3: // Refunded
                    $customerTitle = 'Payment Refunded';
                    $customerDescription = 'Your payment for ' . ($plan->name ?? 'the selected plan') . ' has been refunded. Please contact support if you have any questions.';

                    $adminTitle = 'Payment Refunded';
                    $adminDescription = 'Payment for customer ' . ($user->name ?? 'Unknown') . ' has been refunded. Order ID: ' . $order->order_id;
                    break;

                case 4: // Rejected
                    $customerTitle = 'Payment Rejected';
                    $customerDescription = 'Your payment for ' . ($plan->name ?? 'the selected plan') . ' has been rejected. Please contact support for assistance.';

                    $adminTitle = 'Payment Rejected';
                    $adminDescription = 'Payment for customer ' . ($user->name ?? 'Unknown') . ' has been rejected. Order ID: ' . $order->order_id;
                    break;

                default:
                    $customerTitle = 'Payment Status Updated';
                    $customerDescription = 'The status of your payment for ' . ($plan->name ?? 'the selected plan') . ' has been updated.';

                    $adminTitle = 'Payment Status Updated';
                    $adminDescription = 'Payment status for customer ' . ($user->name ?? 'Unknown') . ' has been updated. Order ID: ' . $order->order_id;
                    break;
            }

            // Get first admin user for sender_id
            $adminUser = \App\Models\User::where('user_type', config('constants.user_types.admin'))->first();
            $adminId = $adminUser ? $adminUser->id : 0;

            // Send notification to customer
            $this->save_notifications(
                $customerTitle,
                $customerDescription,
                'admin', // sender_type
                $adminId, // sender_id (admin user ID)
                'customer', // receiver_type
                $user->id, // receiver_id
                'payment_status_change', // type
                $user->id, // customer_id
                $user->current_workspace_id ?? null // workspace_id
            );

            // Admin notifications removed - only customer notifications are sent

            Log::info('Payment status change notification sent successfully', [
                'order_id' => $order->order_id,
                'status' => $status,
                'customer_id' => $user->id
            ]);
        } catch (\Exception $e) {
            Log::error('Error sending payment status change notifications: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
        }
    }

    /**
     * Send notifications for Stripe payment status changes to both customer and admin
     * 
     * @param Order $order
     * @param string $stripeEvent
     * @param array $stripeData
     * @return void
     */
    protected function sendStripePaymentStatusNotifications($order, $stripeEvent, $stripeData = [])
    {
        try {
            $user = \App\Models\User::find($order->user_id);
            if (!$user) {
                Log::error('User not found for order: ' . $order->order_id);
                return;
            }

            $plan = Plan::find($order->plan_id);
            if (!$plan) {
                Log::error('Plan not found for order: ' . $order->order_id);
                return;
            }

            // Get admin users
            $adminUsers = \App\Models\User::where('user_type', config('constants.user_types.admin'))->get();

            // Get first admin user for sender_id
            $adminUser = \App\Models\User::where('user_type', config('constants.user_types.admin'))->first();
            $adminId = $adminUser ? $adminUser->id : 0;

            // Prepare notification messages based on Stripe event
            switch ($stripeEvent) {
                case 'invoice.payment_failed':
                    $customerTitle = 'Stripe Payment Failed';
                    $customerDescription = 'Your Stripe payment for ' . ($plan->name ?? 'the selected plan') . ' has failed. Please update your payment method or contact support.';

                    $adminTitle = 'Stripe Payment Failed';
                    $adminDescription = 'Stripe payment for customer ' . ($user->name ?? 'Unknown') . ' has failed. Order ID: ' . $order->order_id;
                    break;

                case 'invoice.payment_succeeded':
                    $customerTitle = 'Stripe Payment Successful';
                    $customerDescription = 'Your Stripe payment for ' . ($plan->name ?? 'the selected plan') . ' has been processed successfully.';

                    $adminTitle = 'Stripe Payment Successful';
                    $adminDescription = 'Stripe payment for customer ' . ($user->name ?? 'Unknown') . ' has been processed successfully. Order ID: ' . $order->order_id;
                    break;

                case 'customer.subscription.updated':
                    $customerTitle = 'Subscription Updated';
                    $customerDescription = 'Your subscription for ' . ($plan->name ?? 'the selected plan') . ' has been updated.';

                    $adminTitle = 'Subscription Updated';
                    $adminDescription = 'Subscription for customer ' . ($user->name ?? 'Unknown') . ' has been updated. Order ID: ' . $order->order_id;
                    break;

                case 'customer.subscription.deleted':
                    $customerTitle = 'Subscription Cancelled';
                    $customerDescription = 'Your subscription for ' . ($plan->name ?? 'the selected plan') . ' has been cancelled.';

                    $adminTitle = 'Subscription Cancelled';
                    $adminDescription = 'Subscription for customer ' . ($user->name ?? 'Unknown') . ' has been cancelled. Order ID: ' . $order->order_id;
                    break;

                case 'charge.refunded':
                    $customerTitle = 'Payment Refunded';
                    $customerDescription = 'Your payment for ' . ($plan->name ?? 'the selected plan') . ' has been refunded. Please contact support if you have any questions.';

                    $adminTitle = 'Payment Refunded';
                    $adminDescription = 'Payment for customer ' . ($user->name ?? 'Unknown') . ' has been refunded. Order ID: ' . $order->order_id;
                    break;

                default:
                    $customerTitle = 'Stripe Payment Status Updated';
                    $customerDescription = 'The status of your Stripe payment for ' . ($plan->name ?? 'the selected plan') . ' has been updated.';

                    $adminTitle = 'Stripe Payment Status Updated';
                    $adminDescription = 'Stripe payment status for customer ' . ($user->name ?? 'Unknown') . ' has been updated. Order ID: ' . $order->order_id;
                    break;
            }

            // Send notification to customer
            $this->save_notifications(
                $customerTitle,
                $customerDescription,
                'admin', // sender_type
                $adminId, // sender_id (admin user ID)
                'customer', // receiver_type
                $user->id, // receiver_id
                'stripe_payment_status', // type
                $user->id, // customer_id
                $user->current_workspace_id ?? null // workspace_id
            );

            // Admin notifications removed - only customer notifications are sent

            Log::info('Stripe payment status notification sent successfully', [
                'order_id' => $order->order_id,
                'stripe_event' => $stripeEvent,
                'customer_id' => $user->id
            ]);
        } catch (\Exception $e) {
            Log::error('Error sending Stripe payment status notifications: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
        }
    }

    /**
     * General method to send payment status change notifications
     * This can be called from anywhere in the system when payment status changes
     * 
     * @param Order $order
     * @param int $oldStatus
     * @param int $newStatus
     * @param string $paymentType
     * @return void
     */
    protected function sendPaymentStatusChangeNotification($order, $oldStatus, $newStatus, $paymentType = 'general')
    {
        try {
            // Only send notification if status actually changed
            if ($oldStatus === $newStatus) {
                return;
            }

            $user = \App\Models\User::find($order->user_id);
            if (!$user) {
                Log::error('User not found for order: ' . $order->order_id);
                return;
            }

            $plan = Plan::find($order->plan_id);
            if (!$plan) {
                Log::error('Plan not found for order: ' . $order->order_id);
                return;
            }

            // Get admin users
            $adminUsers = \App\Models\User::where('user_type', config('constants.user_types.admin'))->get();

            // Get first admin user for sender_id
            $adminUser = \App\Models\User::where('user_type', config('constants.user_types.admin'))->first();
            $adminId = $adminUser ? $adminUser->id : 0;

            // Prepare notification messages based on status change
            $statusNames = [
                0 => 'Pending',
                1 => 'Completed',
                2 => 'Failed',
                3 => 'Refunded',
                4 => 'Rejected'
            ];

            $oldStatusName = $statusNames[$oldStatus] ?? 'Unknown';
            $newStatusName = $statusNames[$newStatus] ?? 'Unknown';

            $customerTitle = 'Payment Status Changed';
            $customerDescription = 'Your payment status for ' . ($plan->name ?? 'the selected plan') . ' has changed from ' . $oldStatusName . ' to ' . $newStatusName . '.';

            $adminTitle = 'Payment Status Changed';
            $adminDescription = 'Payment status for customer ' . ($user->name ?? 'Unknown') . ' has changed from ' . $oldStatusName . ' to ' . $newStatusName . '. Order ID: ' . $order->order_id;

            // Send notification to customer
            $this->save_notifications(
                $customerTitle,
                $customerDescription,
                'admin', // sender_type
                $adminId, // sender_id (admin user ID)
                'customer', // receiver_type
                $user->id, // receiver_id
                'payment_status_change', // type
                $user->id, // customer_id
                $user->current_workspace_id ?? null // workspace_id
            );

            // Admin notifications removed - only customer notifications are sent

            Log::info('General payment status change notification sent successfully', [
                'order_id' => $order->order_id,
                'old_status' => $oldStatus,
                'new_status' => $newStatus,
                'payment_type' => $paymentType,
                'customer_id' => $user->id
            ]);
        } catch (\Exception $e) {
            Log::error('Error sending general payment status change notification: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
        }
    }
}
