<?php

namespace App\Http\Controllers\Traits;

use Stripe\Stripe;
use Stripe\Customer;
use Stripe\PaymentIntent;
use Stripe\PaymentMethod;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Models\Order;
use App\Models\Subscription as AppSubscription;
use Carbon\Carbon;
use App\Http\Controllers\Traits\HelperTrait;

trait StripeTrait {
    use HelperTrait;
    /**
     * Initialize Stripe with API key from config
     *
     * @return void
     */
    protected function initializeStripe()
    {
        $stripeMode = Config::get('constants.stripe_mode', 'sandbox');
        $stripeKey = $stripeMode === 'live' 
            ? Config::get('constants.stripe_live_key') 
            : Config::get('constants.stripe_sandbox_key');

        if (!$stripeKey) {
            Log::error('Stripe API key not found in configuration.');
            return response()->json(['message' => 'Stripe API key not found in configuration.'], 422);
        }
        
        Stripe::setApiKey($stripeKey);
    }

    /**
     * Evaluate payment risk using Stripe Radar
     *
     * @param string $paymentIntentId
     * @param array $additionalData
     * @return array
     */
    protected function evaluatePaymentRisk($paymentIntentId, $additionalData = [])
    {
        try {
            // Check if this is a SetupIntent or PaymentIntent
            if (strpos($paymentIntentId, 'seti_') === 0) {
                // This is a SetupIntent
                $intent = \Stripe\SetupIntent::retrieve([
                    'id' => $paymentIntentId,
                    'expand' => ['payment_method']
                ]);
                $paymentMethod = $intent->payment_method;
            } else {
                // This is a PaymentIntent
                $intent = \Stripe\PaymentIntent::retrieve([
                    'id' => $paymentIntentId,
                    'expand' => ['review', 'payment_method']
                ]);
                $paymentMethod = $intent->payment_method;
            }

            // Get payment method details for risk assessment
            $card = $paymentMethod->card;

            // Store risk assessment data
            $riskAssessment = new \App\Models\RiskAssessment();
            $riskAssessment->payment_intent_id = $paymentIntentId ?? null;
            $riskAssessment->card_country = $card->country ?? null;
            $riskAssessment->card_brand = $card->brand ?? null;
            $riskAssessment->ip_country = $additionalData['ip_country'] ?? null;
            $riskAssessment->ip_address = $additionalData['ip_address'] ?? null;
            
            // Set amount and currency based on the intent type
            if (isset($intent->amount)) {
                // For PaymentIntent, amount is in cents
                $riskAssessment->amount = $intent->amount / 100;
                $riskAssessment->currency = $intent->currency ?? null;
            } else {
                // For SetupIntent, get amount from additional data
                $riskAssessment->amount = $additionalData['amount'] ?? null;
                $riskAssessment->currency = $additionalData['currency'] ?? null;
            }
            
            // Get customer email
            if (isset($intent->customer)) {
                $customer = \Stripe\Customer::retrieve($intent->customer);
                $riskAssessment->customer_email = $customer->email ?? $additionalData['customer_email'] ?? null;
            } else {
                $riskAssessment->customer_email = $additionalData['customer_email'] ?? null;
            }
            
            // Map Stripe risk levels to our enum values
            $riskLevel = 'medium'; // default
            $riskScore = 50; // default score

            // Try to get risk information from different Stripe sources
            if (isset($intent->review)) {
                // Get risk level from review
                switch ($intent->review->risk_level) {
                    case 'normal':
                    case 'low':
                        $riskLevel = 'low';
                        $riskScore = 25;
                        break;
                    case 'elevated':
                        $riskLevel = 'medium';
                        $riskScore = 50;
                        break;
                    case 'high':
                        $riskLevel = 'high';
                        $riskScore = 75;
                        break;
                    case 'highest':
                        $riskLevel = 'very_high';
                        $riskScore = 100;
                        break;
                }

                // If review has a specific risk score, use it
                if (isset($intent->review->risk_score)) {
                    $riskScore = $intent->review->risk_score;
                }
            }

            // Check radar_options if available
            if (isset($paymentIntent->radar_options) && isset($paymentIntent->radar_options->risk_score)) {
                $riskScore = $paymentIntent->radar_options->risk_score;
            }

            $riskAssessment->risk_level = $riskLevel;
            $riskAssessment->risk_score = $riskScore;
            
            Log::info('Risk assessment details:', [
                'risk_level' => $riskLevel,
                'risk_score' => $riskScore,
                'payment_intent_id' => $paymentIntentId
            ]);
            
            // Check for high-risk indicators
            $riskFactors = [];
            
            // Check for location mismatch
            if (isset($card->country) && isset($additionalData['ip_country']) && 
                $card->country !== $additionalData['ip_country']) {
                $riskFactors[] = 'location_mismatch';
            }

            // Check for rapid transaction attempts
            if (isset($additionalData['recent_attempts']) && $additionalData['recent_attempts'] > 3) {
                $riskFactors[] = 'rapid_attempts';
            }

            // Check if card is from a high-risk country
            $highRiskCountries = ['XX', 'YY', 'ZZ']; // Add your high-risk country codes
            if (in_array($card->country, $highRiskCountries)) {
                $riskFactors[] = 'high_risk_country';
            }

            $riskAssessment->risk_factors = json_encode($riskFactors);
            $riskAssessment->save();

            // For PaymentIntent only - check Radar early fraud warnings
            if (strpos($paymentIntentId, 'seti_') !== 0) {
                $fraudWarnings = \Stripe\Radar\EarlyFraudWarning::all([
                    'payment_intent' => $paymentIntentId
                ]);

                if (!empty($fraudWarnings->data)) {
                    foreach ($fraudWarnings->data as $warning) {
                        Log::warning('Fraud warning detected', [
                            'payment_intent' => $paymentIntentId,
                            'fraud_type' => $warning->fraud_type,
                            'actionable' => $warning->actionable
                        ]);

                        // Update risk assessment with fraud warnings
                        $riskAssessment->fraud_warnings = json_encode($fraudWarnings->data);
                        $riskAssessment->save();

                        // If actionable fraud warning, consider blocking the transaction
                        if ($warning->actionable) {
                            throw new \Exception('High-risk transaction detected: ' . $warning->fraud_type);
                        }
                    }
                }
            }

            // Check for blocked payment methods using Radar rules
            if (isset($intent->review) && $intent->review->closed === 'blocked') {
                throw new \Exception('Transaction blocked by Radar rules');
            }

            // Check if we're using a test card in sandbox mode
            $stripeMode = Config::get('constants.stripe_mode', 'sandbox');
            $isTestCard = false;
            if (isset($paymentMethod->card->last4)) {
                $isTestCard = $paymentMethod->card->last4 === '4242';
            }

            return [
                'risk_level' => $riskAssessment->risk_level,
                'risk_factors' => $riskFactors,
                'fraud_warnings' => $fraudWarnings->data ?? [],
                'should_block' => ($stripeMode !== 'sandbox' || !$isTestCard) && 
                                (!empty($riskFactors) || !empty($fraudWarnings->data))
            ];

        } catch (\Exception $e) {
            Log::error('Risk evaluation failed: ' . $e->getMessage());
            throw $e;
        }
    }

    public function createStripeCustomer($email, $name)
    {
        return Customer::create([
            'email' => $email,
            'name' => $name,
        ]);
    }

    public function createStripePaymentMethod($cardDetails, $billingDetails)
    {
        try {
            // Validate CVC length
            $cvc = $cardDetails['cvc'];
            if (strlen($cvc) < 3 || strlen($cvc) > 4) {
                throw new \Exception('Invalid CVC length. CVC should be 3 or 4 digits.');
            }
            
            // Create payment method
            return PaymentMethod::create([
                'type' => 'card',
                'card' => [
                    'number' => $cardDetails['number'],
                    'exp_month' => $cardDetails['exp_month'],
                    'exp_year' => $cardDetails['exp_year'],
                    'cvc' => $cvc,
                ],
                'billing_details' => [
                    'email' => $billingDetails['email'],
                    'name' => $billingDetails['name'],
                ],
            ]);
        } catch (\Stripe\Exception\CardException $e) {
            $error = $e->getError();
            Log::error('Payment method creation failed:', [
                'error_code' => $error->code,
                'error_message' => $error->message
            ]);
            
            if ($error->code === 'incorrect_cvc') {
                throw new \Exception('The card\'s security code (CVC) is incorrect.');
            }
            throw $e;
        }
    }

    public function attachPaymentMethodToCustomer($paymentMethodId, $customerId)
    {
        try {
            // Retrieve the payment method from Stripe
            try {
                $paymentMethod = PaymentMethod::retrieve($paymentMethodId);
            } catch (\Stripe\Exception\InvalidRequestException $e) {
                Log::error('Failed to retrieve payment method: ' . $e->getMessage());
                return response()->json(['message' => 'Invalid payment method. Please try again with a new card.'], 400);
            }
    
            // Check if the payment method is already attached to a different customer
            if ($paymentMethod->customer && $paymentMethod->customer !== $customerId) {
                Log::error('Payment method already attached to another customer: ' . $paymentMethod->customer);
                return response()->json(['message' => 'Payment method already attached to another customer'], 400);
            }
    
            // Attach the payment method to the customer
            $paymentMethod->attach(['customer' => $customerId]);
    
            Log::info('Payment method successfully attached to customer: ' . $customerId);
            return $paymentMethod;
        } catch (\Stripe\Exception\ApiErrorException $e) {
            Log::error('Stripe API Error: ' . $e->getMessage());
            return response()->json(['message' => 'Failed to process payment method: ' . $e->getMessage()], 400);
        } catch (\Exception $e) {
            Log::error('General Error: ' . $e->getMessage());
            return response()->json(['message' => 'An unexpected error occurred. Please try again.'], 500);
        }
    }

    public function createPaymentIntent($amount, $currency, $customerId, $paymentMethodId, $metadata = [], $description = '')
    {
        try {
            return PaymentIntent::create([
                'amount' => $amount,
                'currency' => $currency,
                'customer' => $customerId,
                'payment_method' => $paymentMethodId,
                'off_session' => true,
                'confirm' => true,
                'metadata' => $metadata,
                'description' => $description,
                'payment_method_options' => [
                    'card' => [
                        'request_three_d_secure' => 'automatic'
                    ]
                ]
            ]);
        } catch (\Stripe\Exception\CardException $e) {
            $error = $e->getError();
            $errorMessage = 'Card error: ';
            
            if ($error->code === 'incorrect_cvc') {
                $errorMessage .= 'The card\'s security code (CVC) is incorrect.';
            } else if ($error->code === 'expired_card') {
                $errorMessage .= 'The card has expired.';
            } else if ($error->code === 'card_declined') {
                $errorMessage .= isset($error->decline_code) ? ucfirst(str_replace('_', ' ', $error->decline_code)) : 'The card was declined.';
            } else {
                $errorMessage .= $error->message;
            }
            
            Log::error('Payment Intent creation failed:', [
                'error_code' => $error->code,
                'error_message' => $error->message,
                'decline_code' => $error->decline_code ?? null
            ]);
            
            throw new \Exception($errorMessage);
        }
    }
    
    public function createCustomerAndPaymentMethod($request, $validatorData)
    {
        // Create customer in Stripe
        $customer = $this->createStripeCustomer(
            $validatorData['email'],
            $validatorData['name']
        );
    
        // Get the payment method ID from the request
        // We use stripePaymentMethodId as it's coming from frontend
        $paymentMethodId = $request->input('stripePaymentMethodId');
    
        if (!$paymentMethodId) {
            return response()->json(['message' => 'Payment method ID is required'], 400);
        }
    
        try {
            // Log the payment method ID being used
            Log::info('Attempting to attach payment method: ' . $paymentMethodId . ' to customer: ' . $customer->id);
            
            // Attach the payment method to the customer
            $paymentMethod = $this->attachPaymentMethodToCustomer($paymentMethodId, $customer->id);
    
            // If attaching payment method returns a JsonResponse (error occurred), return it directly
            if ($paymentMethod instanceof \Illuminate\Http\JsonResponse) {
                return $paymentMethod;
            }
    
            // Set this payment method as the default for future payments
            Customer::update($customer->id, [
                'invoice_settings' => [
                    'default_payment_method' => $paymentMethod->id
                ]
            ]);
    
            // Return the customer and payment method
            return [$customer, $paymentMethod];
        } catch (\Stripe\Exception\ApiErrorException $e) {
            Log::error('Stripe API Error: ' . $e->getMessage());
            return response()->json(['message' => 'Failed to process payment method: ' . $e->getMessage()], 400);
        } catch (\Exception $e) {
            Log::error('General Error: ' . $e->getMessage());
            return response()->json(['message' => 'An unexpected error occurred. Please try again.'], 500);
        }
    }

    public function processStripePayment($request, $validatorData)
    {
        try {
            // Initialize Stripe
            $this->initializeStripe();
            // Get IP address from request
            $ipAddress = $request->ip();
            Log::info('Client IP address: ' . $ipAddress);
            // Create customer and attach payment method
            $result = $this->createCustomerAndPaymentMethod($request, $validatorData);
            // If there was an error, return it
            if ($result instanceof \Illuminate\Http\JsonResponse) {
                return $result;
            }
            list($customer, $paymentMethod) = $result;
            // Check for recent payment attempts
            $recentAttempts = \App\Models\RiskAssessment::where('created_at', '>=', now()->subHours(1))
                ->where('card_brand', $paymentMethod->card->brand)
                ->where('card_country', $paymentMethod->card->country)
                ->count();
            // Get the price from the request or validator data
            $price = $request->input('price') ?? $validatorData['price'] ?? 0;
            $currency = $request->input('price_curency') ?? $validatorData['price_curency'] ?? 'AUD';
            // Create metadata for the payment
            $metadata = [
                'plan_id' => $validatorData['plan_id'] ?? $request->input('plan_id'),
                'plan_name' => $validatorData['plan_name'] ?? $request->input('plan_name'),
                'email' => $validatorData['email'] ?? $request->input('email')
            ];
            //stripe description
            $description = $validatorData['order_id'] ?? '';
            // Create payment intent with radar options
            $paymentIntent = $this->createPaymentIntent(
                round($price * 100), // amount in cents, rounded to avoid floating point issues
                $currency,
                $customer->id,
                $paymentMethod->id,
                $metadata,
                $description
            );
            // Evaluate payment risk
            $riskAssessment = $this->evaluatePaymentRisk($paymentIntent->id, [
                'ip_address' => $ipAddress,
                'customer_email' => $validatorData['email'] ?? $request->input('email'),
                'recent_attempts' => $recentAttempts
            ]);
            // Block high-risk transactions
            if ($riskAssessment['should_block']) {
                // Check payment intent status before canceling
                if (in_array($paymentIntent->status, ['requires_payment_method', 'requires_capture', 'requires_confirmation', 'requires_action', 'processing'])) {
                    $paymentIntent->cancel();
                } else if ($paymentIntent->status === 'succeeded') {
                    // If payment has already succeeded, you might want to refund instead
                    $refund = \Stripe\Refund::create([
                        'payment_intent' => $paymentIntent->id
                    ]);
                } 
                Log::error('High-risk transaction blocked', [
                    'payment_intent' => $paymentIntent->id,
                    'payment_status' => $paymentIntent->status,
                    'risk_factors' => $riskAssessment['risk_factors'],
                    'fraud_warnings' => $riskAssessment['fraud_warnings']
                ]);
                return response()->json([
                    'message' => 'This transaction has been declined due to security concerns. Please contact support.',
                    'risk_level' => $riskAssessment['risk_level']
                ], 403);
            }
            
            // Check if payment was successful
            if (!$paymentIntent || $paymentIntent->status !== 'succeeded') {
                Log::error('Payment intent failed', [
                    'status' => $paymentIntent->status ?? 'unknown',
                    'risk_assessment' => $riskAssessment
                ]);
                return response()->json(['message' => 'Payment failed. Please try again or use a different payment method.'], 422);
            }
            
            // Update validator data with payment information
            $validatorData['payment_status'] = config('constants.payment_statuses.completed', 1);
            $validatorData['txn_id'] = $paymentIntent->id;
            $validatorData['stripe_customer_id'] = $customer->id;
            
            // Calculate expiry date for one-time payments
            $interval = $validatorData['interval'] ?? 1;
            $expiryDate = null;
            
            // Convert interval to numeric value if it's not already
            if (!is_numeric($interval)) {
                // Try to extract a numeric value (e.g., "3 months" -> 3)
                preg_match('/(\d+)/', $interval, $matches);
                $interval = !empty($matches) ? (int)$matches[1] : 1;
            }
            
            // Calculate expiry date based on interval
            $expiryDate = now()->addMonths((int)$interval);
            
            // Add expiry date to return data
            $validatorData['expiry_date'] = $expiryDate;
            $validatorData['expiry_date_formatted'] = $expiryDate->format('Y-m-d');
            
            // Log the calculated expiry date
            Log::info('One-time payment expiry date calculated', [
                'customer_id' => $customer->id,
                'interval' => $interval,
                'expiry_date' => $expiryDate->format('Y-m-d H:i:s')
            ]);
            
            // Return success data
            return [
                'success' => true,
                'data' => $validatorData,
                'payment_intent' => $paymentIntent,
                'customer' => $customer,
                'charge' => $paymentIntent,
                'expiry_date' => $expiryDate
            ];
            
        } catch (\Exception $e) {
            Log::error('Error processing Stripe payment: ' . $e->getMessage());
            return response()->json(['message' => 'Error processing payment: ' . $e->getMessage()], 500);
        }
    }

    /**
     * Process a recurring subscription with Stripe
     *
     * @param Request $request
     * @param array $validatorData
     * @return array|\Illuminate\Http\JsonResponse
     */
    public function processStripeSubscription($request, $validatorData)
    {
        try {
            // Initialize Stripe
            $this->initializeStripe();
            
            // Get IP address from request
            $ipAddress = $request->ip();
            Log::info('Client IP address: ' . $ipAddress);

            // Log the request data for debugging
            Log::info('Stripe subscription request data:', [
                'request' => $request->all(),
                'validatorData' => $validatorData,
                'ip_address' => $ipAddress
            ]);
            
            // Create customer and attach payment method
            $result = $this->createCustomerAndPaymentMethod($request, $validatorData);
        
            // If there was an error, return it
            if ($result instanceof \Illuminate\Http\JsonResponse) {
                return $result;
            }
            
            list($customer, $paymentMethod) = $result;

            // Check for recent subscription attempts with this card
            $recentAttempts = \App\Models\RiskAssessment::where('created_at', '>=', now()->subHours(24))
                ->where('card_brand', $paymentMethod->card->brand)
                ->where('card_country', $paymentMethod->card->country)
                ->count();
            
            // Get subscription data from the request/validatorData
            $planId = $validatorData['plan_id'] ?? null;
            $planName = $validatorData['plan_name'] ?? 'Subscription';
            $price = $validatorData['price'] ?? $request->input('price');
            $currency = $validatorData['price_curency'] ?? $request->input('price_curency', 'AUD');
            $interval = $validatorData['interval'] ?? 1; // Default to monthly
            // Get or create Stripe Product for this plan - UPDATED
            $product = $this->getOrCreateStripeProduct($planName, [
                'plan_id' => $planId
            ]);
            
            // Get or create Stripe Price for billing - UPDATED
            $stripePrice = $this->getOrCreateStripePrice(
                $product->id,
                $price,
                $currency,
                $this->getIntervalType($interval),
                $this->getIntervalCount($interval)
            );
            
            // Create metadata for subscription
            $metadata = [
                'order_id' => $validatorData['order_id'] ?? null,
                'plan_id' => $planId,
                'user_id' => $validatorData['user_id'] ?? null,
                'email' => $validatorData['email'] ?? null,
                'ip_address' => $ipAddress
            ];
            
            // Create initial payment intent for risk assessment
            $setupIntent = \Stripe\SetupIntent::create([
                'customer' => $customer->id,
                'payment_method' => $paymentMethod->id,
                'payment_method_types' => ['card'],
                'usage' => 'off_session',
                'metadata' => $metadata
            ]);

            // Evaluate payment risk
            $riskAssessment = $this->evaluatePaymentRisk($setupIntent->id, [
                'ip_address' => $ipAddress,
                'recent_attempts' => $recentAttempts,
                'is_subscription' => true,
                'amount' => $price, // Pass the original price
                'currency' => $currency
            ]);

            // Block high-risk transactions, but allow test cards in sandbox mode
            if ($riskAssessment['should_block']) {
                // Check if we're in sandbox mode and using a test card
                $stripeMode = Config::get('constants.stripe_mode', 'sandbox');
                $isTestCard = $paymentMethod->card->last4 === '4242';
                
                if ($stripeMode != 'sandbox' || !$isTestCard) {
                    Log::error('High-risk subscription attempt blocked', [
                        'setup_intent' => $setupIntent->id,
                        'risk_factors' => $riskAssessment['risk_factors'],
                        'fraud_warnings' => $riskAssessment['fraud_warnings']
                    ]);
                    
                    return response()->json([
                        'message' => 'This subscription request has been declined due to security concerns. Please contact support.',
                        'risk_level' => $riskAssessment['risk_level']
                    ], 403);
                } else {
                    Log::info('Allowing test card transaction in sandbox mode', [
                        'card_last4' => '4242',
                        'risk_level' => $riskAssessment['risk_level']
                    ]);
                }
            }

            // Create subscription and charge the customer
            $subscription = $this->createStripeSubscription(
                $customer->id, 
                $stripePrice->id,
                $paymentMethod->id,
                array_merge($metadata, [
                    'risk_level' => $riskAssessment['risk_level'],
                    'risk_assessment_id' => $riskAssessment['id'] ?? null
                ])
            );
            
            // Log subscription details, especially the current_period_end
            Log::info('Subscription created successfully:', [
                'id' => $subscription->id,
                'status' => $subscription->status,
                'current_period_start' => $subscription->current_period_start ?? 'not set',
                'current_period_end' => $subscription->current_period_end ?? 'not set'
            ]);
            
            // Check if we need to handle 3D Secure or other authentication
            if ($subscription->status === 'incomplete' && isset($subscription->latest_invoice)) {
                try {
                    // Make sure we have the invoice object
                    $invoiceId = null;
                    if (is_object($subscription->latest_invoice)) {
                        $invoiceId = $subscription->latest_invoice->id;
                    } else if (is_string($subscription->latest_invoice)) {
                        $invoiceId = $subscription->latest_invoice;
                    }
                    
                    if ($invoiceId) {
                        // Retrieve the invoice with payment intent expanded
                        $invoice = \Stripe\Invoice::retrieve([
                            'id' => $invoiceId,
                            'expand' => ['payment_intent']
                        ]);
                        
                        // Check if payment requires additional authentication
                        if (isset($invoice->payment_intent) &&
                            ($invoice->payment_intent->status === 'requires_action' || 
                             $invoice->payment_intent->status === 'requires_source_action')) {
                            
                            return response()->json([
                                'message' => 'Payment requires additional authentication.',
                                'payment_intent' => $invoice->payment_intent,
                                'subscription_id' => $subscription->id
                            ], 202); // Using 202 Accepted status code
                        }
                    }
                } catch (\Exception $e) {
                    Log::error('Error retrieving invoice payment intent: ' . $e->getMessage());
                    // Continue execution as we still want to return the subscription
                }
            }
            
            // If needed, refresh the subscription to make sure we have all the data
            if (!isset($subscription->current_period_end) || !$subscription->current_period_end) {
                try {
                    $subscription = \Stripe\Subscription::retrieve([
                        'id' => $subscription->id,
                        'expand' => ['latest_invoice']
                    ]);
                    
                    // If the latest_invoice is available, get the payment_intent separately
                    if (isset($subscription->latest_invoice) && is_object($subscription->latest_invoice)) {
                        $invoice = \Stripe\Invoice::retrieve([
                            'id' => $subscription->latest_invoice->id,
                            'expand' => ['payment_intent']
                        ]);
                        $subscription->latest_invoice = $invoice;
                    }
                    
                    Log::info('Refreshed subscription data', [
                        'current_period_end' => $subscription->current_period_end ?? 'still not available'
                    ]);
                } catch (\Exception $e) {
                    Log::error('Failed to refresh subscription: ' . $e->getMessage());
                }
            }
            
            // Return success data
            return [
                'success' => true,
                'subscription' => $subscription,
                'customer' => $customer,
                'product' => $product,
                'price' => $stripePrice
            ];
        } catch (\Exception $e) {
            Log::error('Error creating subscription: ' . $e->getMessage());
            // Add stack trace for debugging
            Log::error($e->getTraceAsString());
            return response()->json(['message' => 'Error creating subscription: ' . $e->getMessage()], 500);
        }
    }
    

    /**
     * Create a Stripe product
     *
     * @param string $name
     * @param array $metadata
     * @return \Stripe\Product
     */
    private function getOrCreateStripeProduct($name, $metadata = [])
    {
        // First, try to find an existing product with this name
        $existingProducts = \Stripe\Product::all([
            'active' => true,
            'limit' => 100 // Adjust as needed
        ]);
        
        // Look for a product with matching name
        foreach ($existingProducts->data as $product) {
            if ($product->name === $name) {
                // If the product exists but metadata needs updating, update it
                $shouldUpdate = false;
                foreach ($metadata as $key => $value) {
                    if (!isset($product->metadata->$key) || $product->metadata->$key !== $value) {
                        $shouldUpdate = true;
                        break;
                    }
                }
                
                if ($shouldUpdate) {
                    return \Stripe\Product::update($product->id, [
                        'metadata' => $metadata
                    ]);
                }
                
                // If no updates needed, return the existing product
                return $product;
            }
        }
        
        // If no existing product found, create a new one
        return \Stripe\Product::create([
            'name' => $name,
            'metadata' => $metadata
        ]);
    }

    /**
     * Create a Stripe price
     *
     * @param string $productId
     * @param float $amount
     * @param string $currency
     * @param string $interval
     * @param int $intervalCount
     * @return \Stripe\Price
     */
    private function getOrCreateStripePrice($productId, $amount, $currency = 'AUD', $interval = 'month', $intervalCount = 1)
    {
        // First check if there's an existing price for this product with the same parameters
        $existingPrices = \Stripe\Price::all([
            'product' => $productId,
            'active' => true,
            'limit' => 100 // Adjust as needed
        ]);
        
        // Convert amount to cents if needed (Stripe uses smallest currency unit)
        $amountInCents = (int)($amount * 100);
        
        // Look for a matching price
        foreach ($existingPrices->data as $price) {
            if ($price->unit_amount === $amountInCents && 
                $price->currency === strtolower($currency) &&
                $price->recurring->interval === $interval &&
                $price->recurring->interval_count === $intervalCount) {
                // Found a matching price
                return $price;
            }
        }
        
        // If no existing price found, create a new one
        return \Stripe\Price::create([
            'product' => $productId,
            'unit_amount' => $amountInCents,
            'currency' => strtolower($currency),
            'recurring' => [
                'interval' => $interval,
                'interval_count' => $intervalCount
            ]
        ]);
    }

    /**
     * Create a Stripe subscription
     *
     * @param string $customerId
     * @param string $priceId
     * @param string $paymentMethodId
     * @param array $metadata
     * @return \Stripe\Subscription
     */
    private function createStripeSubscription($customerId, $priceId, $paymentMethodId, $metadata = [])
    {
        try {
            // Sanitize inputs
            $customerId = trim($customerId);
            $priceId = trim($priceId);
            $paymentMethodId = trim($paymentMethodId);

            // Get payment method details for risk assessment
            $paymentMethod = \Stripe\PaymentMethod::retrieve($paymentMethodId);
            
            // Check if the card is from a blocked country
            $blockedCountries = Config::get('constants.stripe_blocked_countries', []); // Add blocked countries in your config
            if (in_array($paymentMethod->card->country, $blockedCountries)) {
                throw new \Exception('Cards from this country are not accepted.');
            }

            // Check card velocity (number of subscriptions attempted with this card)
            $cardFingerprint = $paymentMethod->card->fingerprint;
            $recentSubscriptionAttempts = \App\Models\RiskAssessment::where('created_at', '>=', now()->subHours(24))
                ->where('card_fingerprint', $cardFingerprint)
                ->count();

            if ($recentSubscriptionAttempts > Config::get('constants.max_subscription_attempts', 3)) {
                throw new \Exception('Too many subscription attempts with this card.');
            }

            // Get price details for the subscription
            $price = \Stripe\Price::retrieve($priceId);
            $amount = $price->unit_amount / 100; // Convert from cents to actual amount
            
            // Store risk assessment for this subscription attempt
            $riskAssessment = new \App\Models\RiskAssessment([
                'card_fingerprint' => $cardFingerprint ?? null,
                'card_country' => $paymentMethod->card->country ?? null,
                'card_brand' => $paymentMethod->card->brand ?? null,
                'attempt_type' => 'subscription',
                'risk_score' => 50, // Default score for new subscription attempts
                'transaction_type' => 'subscription',
                'amount' => $amount, // Save the actual amount from the price
                'customer_email' => isset($metadata['email']) ? $metadata['email'] : null,
                'ip_address' => isset($metadata['ip_address']) ? $metadata['ip_address'] : null,
                'currency' => $price->currency
            ]);
            $riskAssessment->save();

            // Make sure payment method is attached to customer
            if ($paymentMethod->customer != $customerId) {
                if ($paymentMethod->customer) {
                    $paymentMethod->detach();
                }
                $paymentMethod->attach(['customer' => $customerId]);
            }
            
            // Set this payment method as default for the customer
            \Stripe\Customer::update($customerId, [
                'invoice_settings' => ['default_payment_method' => $paymentMethodId]
            ]);
            
            // Create the subscription with enhanced risk management
            $subscriptionData = [
                'customer' => $customerId,
                'items' => [['price' => $priceId]],
                'default_payment_method' => $paymentMethodId,
                'metadata' => array_merge($metadata, [
                    'risk_assessment_id' => $riskAssessment->id,
                    'risk_level' => $riskAssessment->risk_level ?? 'normal'
                ]),
                'expand' => ['latest_invoice'],
                'payment_behavior' => 'error_if_incomplete',
                'payment_settings' => [
                    'payment_method_types' => ['card'],
                    'save_default_payment_method' => 'on_subscription',
                    'payment_method_options' => [
                        'card' => [
                            'request_three_d_secure' => 'automatic'
                        ]
                    ]
                ],
                'collection_method' => 'charge_automatically',
                'proration_behavior' => 'always_invoice',
                'cancel_at_period_end' => false,
                'trial_end' => null
            ];

            try {
                // Create the subscription
                $subscription = \Stripe\Subscription::create($subscriptionData);
                
                // Update risk assessment with subscription ID
                $riskAssessment->subscription_id = $subscription->id;
                $riskAssessment->save();
            } catch (\Stripe\Exception\CardException $e) {
                $error = $e->getError();
                $errorMessage = 'Card error: ';
                
                if ($error->code === 'incorrect_cvc') {
                    throw new \Exception('The card\'s security code (CVC) is incorrect.');
                } else if ($error->code === 'expired_card') {
                    throw new \Exception('The card has expired.');
                } else if ($error->code === 'card_declined') {
                    $declineMessage = isset($error->decline_code) ? 
                        ucfirst(str_replace('_', ' ', $error->decline_code)) : 
                        'The card was declined.';
                    throw new \Exception($declineMessage);
                }
                
                Log::error('Subscription creation failed:', [
                    'error_code' => $error->code,
                    'error_message' => $error->message,
                    'decline_code' => $error->decline_code ?? null
                ]);
                
                throw new \Exception($error->message);
            }

            // Log subscription details including current period end
            Log::info('Subscription created with details:', [
                'id' => $subscription->id,
                'status' => $subscription->status,
                'current_period_start' => $subscription->current_period_start,
                'current_period_end' => $subscription->current_period_end,
                'has_latest_invoice' => isset($subscription->latest_invoice) ? 'yes' : 'no'
            ]);
            
            // If invoice exists, fetch it separately with payment_intent expanded
            if (isset($subscription->latest_invoice)) {
                try {
                    // Get the invoice ID from the subscription
                    $invoiceId = is_object($subscription->latest_invoice) ? 
                        $subscription->latest_invoice->id : 
                        $subscription->latest_invoice;
                    
                    // Fetch the invoice with payment_intent expanded
                    $invoice = \Stripe\Invoice::retrieve([
                        'id' => $invoiceId,
                        'expand' => ['payment_intent']
                    ]);
                    
                    // Replace the invoice object in the subscription
                    $subscription->latest_invoice = $invoice;
                    
                    if (isset($invoice->payment_intent)) {
                        Log::info('Retrieved invoice with payment intent: ' . $invoice->payment_intent->id);
                    }
                } catch (\Exception $e) {
                    Log::error('Failed to retrieve invoice with payment intent: ' . $e->getMessage());
                }
            }

            return $subscription;

        } catch (\Exception $e) {
            Log::error('Error in createStripeSubscription: ' . $e->getMessage());
            throw $e;
        }
    }
    

    /**
     * Get interval type for Stripe based on interval value
     *
     * @param int|string $interval
     * @return string
     */
    private function getIntervalType($interval)
    {
        if (is_string($interval) && in_array($interval, ['day', 'week', 'month', 'year'])) {
            return $interval;
        }
        
        $interval = (int)$interval;
        
        if ($interval >= 1 && $interval < 12) {
            return 'month';
        } else if ($interval == 12) {
            return 'year';
        } else {
            return 'month'; // Default to monthly
        }
    }

    /**
     * Get interval count for Stripe based on interval value
     *
     * @param int|string $interval
     * @return int
     */
    private function getIntervalCount($interval)
    {
        if (is_string($interval)) {
            return 1;
        }
        
        $interval = (int)$interval;
        
        if ($interval >= 1 && $interval < 12) {
            return $interval;
        } else if ($interval == 12) {
            return 1; // 1 year, not 12 months
        } else {
            return 1; // Default to 1
        }
    }

    /**
     * Cancel a subscription in Stripe
     *
     * @param string $subscriptionId The Stripe subscription ID
     * @param bool $atPeriodEnd Whether to cancel at the end of the billing period
     * @return \Stripe\Subscription
     */
    public function cancelSubscription($subscriptionId, $atPeriodEnd = true)
    {
        try {
            $this->initializeStripe();
            
            // First, retrieve the subscription to check its current status
            $subscription = \Stripe\Subscription::retrieve($subscriptionId);
            
            // Check if subscription is already canceled
            if ($subscription->status === 'canceled') {
                Log::info('Subscription already canceled: ' . $subscriptionId);
                return $subscription;
            }
            
            // Check if subscription is already set to cancel at period end
            if ($subscription->cancel_at_period_end && $atPeriodEnd) {
                Log::info('Subscription already set to cancel at period end: ' . $subscriptionId);
                return $subscription;
            }
            
            if ($atPeriodEnd) {
                // Cancel at period end (user keeps access until billing period ends)
                return \Stripe\Subscription::update($subscriptionId, [
                    'cancel_at_period_end' => true
                ]);
            } else {
                // Cancel immediately
                return $subscription->cancel();
            }
        } catch (\Exception $e) {
            Log::error('Error canceling subscription: ' . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Process Stripe webhook - used by the controller to avoid recursive call
     *
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function processStripeWebhook(Request $request)
    {
        try {
            $this->initializeStripe();
            
            $payload = $request->getContent();
            $endpointSecret = Config::get('constants.stripe_webhook_secret');
            Log::info('Webhook received with payload: ' . substr($payload, 0, 500) . '...');
            if (empty($payload)) {
                return response('Empty payload', 400);
            }
            
            $event = null;
            
            // Check for test mode header (ONLY FOR DEVELOPMENT/TESTING)
            $isTestMode = $request->header('X-Stripe-Test-Mode') === 'true';
            
            // Verify webhook signature if endpoint secret is configured and not in test mode
            if ($endpointSecret && !$isTestMode) {
                try {
                    $event = \Stripe\Webhook::constructEvent(
                        $payload, $request->header('Stripe-Signature'), $endpointSecret
                    );
                } catch (\Exception $e) {
                    Log::error('Webhook signature verification failed: ' . $e->getMessage());
                    return response('Webhook signature verification failed', 400);
                }
            } else {
                // For test mode or if no endpoint secret is configured
                $event = json_decode($payload, true);
                if (is_array($event)) {
                    $event = \Stripe\Event::constructFrom($event);
                } else {
                    Log::error('Invalid JSON payload');
                    return response('Invalid JSON payload', 400);
                }
            }
            
            Log::info('Webhook received: ' . $event->type);
            
            // Handle different webhook events
            switch ($event->type) {
                case 'checkout.session.completed':
                    return $this->handleCheckoutSessionCompleted($event->data->object);
                
                case 'invoice.paid':
                    return $this->handleInvoicePaid($event->data->object);
                
                case 'invoice.payment_failed':
                    return $this->handleInvoicePaymentFailed($event->data->object);
                
                case 'customer.subscription.updated':
                    return $this->handleSubscriptionUpdated($event->data->object);
                
                case 'customer.subscription.deleted':
                    return $this->handleSubscriptionDeleted($event->data->object);
                    
                default:
                    Log::info('Unhandled webhook event: ' . $event->type);
                    return response('Webhook received: ' . $event->type, 200);
            }
        } catch (\Exception $e) {
            Log::error('Webhook processing error: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
            return response('Webhook error: ' . $e->getMessage(), 500);
        }
    }

    /**
     * Handle checkout.session.completed webhook event
     *
     * @param \Stripe\Checkout\Session $session
     * @return \Illuminate\Http\Response
     */
    private function handleCheckoutSessionCompleted($session)
    {
        Log::info('Handling checkout.session.completed for session: ' . $session->id);
        Log::info('Payment status: ' . $session->payment_status);
        Log::info('Amount total: ' . ($session->amount_total / 100));
        Log::info('Currency: ' . $session->currency);
        Log::info('Customer ID: ' . ($session->customer ?? 'null'));
        Log::info('Payment intent: ' . ($session->payment_intent ?? 'null'));
        Log::info('Subscription ID: ' . ($session->subscription ?? 'null'));
        
        if ($session->payment_status !== 'paid') {
            Log::warning('Checkout session not paid: ' . $session->id);
            return response('Checkout session not paid', 200);
        }

        try {
            // Log the metadata
            if (isset($session->metadata) && !empty($session->metadata)) {
                Log::info('Session metadata: ' . json_encode($session->metadata->toArray()));
            } else {
                Log::info('No metadata available in session');
            }
            
            // Get customer details from the session
            $customer = null;
            if ($session->customer) {
                try {
                    Log::info('Retrieving customer details for ID: ' . $session->customer);
                    $customer = \Stripe\Customer::retrieve($session->customer);
                    if ($customer) {
                        Log::info('Customer retrieved - Name: ' . ($customer->name ?? 'null') . ', Email: ' . ($customer->email ?? 'null'));
                    }
                } catch (\Exception $e) {
                    Log::warning('Failed to retrieve customer: ' . $e->getMessage());
                    Log::warning($e->getTraceAsString());
                }
            }

            // Get plan details from metadata
            $planId = null;
            $planName = null;
            $userId = null;
            if (isset($session->metadata)) {
                $metadata = $session->metadata->toArray();
                $planId = $metadata['plan_id'] ?? null;
                $planName = $metadata['plan_name'] ?? null;
                $userId = $metadata['user_id'] ?? null;
                
                Log::info('Extracted from metadata - Plan ID: ' . ($planId ?? 'null') . 
                         ', Plan Name: ' . ($planName ?? 'null') . 
                         ', User ID: ' . ($userId ?? 'null'));
            }

            // If plan details not in metadata, try to get from line items
            if (!$planId && isset($session->line_items)) {
                try {
                    $lineItems = \Stripe\Checkout\Session::retrieve($session->id, [
                        'expand' => ['line_items']
                    ])->line_items;
                    
                    if (!empty($lineItems->data)) {
                        $firstItem = $lineItems->data[0];
                        if (isset($firstItem->price->product)) {
                            $product = \Stripe\Product::retrieve($firstItem->price->product);
                            $planId = $product->metadata->plan_id ?? null;
                            $planName = $product->name;
                        }
                    }
                } catch (\Exception $e) {
                    Log::warning('Failed to get plan details from line items: ' . $e->getMessage());
                }
            }

            // Create order
            Log::info('Creating new order object');
            $order = new Order();
            $orderId = $this->generateOrderId();
            Log::info('Generated order ID: ' . $orderId);
            
            // Set basic order details
            $order->order_id = $orderId;
            $order->price = $session->amount_total / 100;
            $order->original_price = $session->amount_total / 100;
            $order->price_curency = strtolower($session->currency);
            
            // Set payment details
            Log::info('Setting payment status to: ' . config('constants.payment_statuses.completed'));
            Log::info('Setting payment type to: ' . config('constants.payment_types.stripe'));
            $order->payment_status = config('constants.payment_statuses.completed');
            $order->payment_type = config('constants.payment_types.stripe');
            
            // Set transaction details
            $txnId = $session->payment_intent ?? $session->id;
            Log::info('Setting transaction ID to: ' . $txnId);
            $order->txn_id = $txnId;
            $order->stripe_customer_id = $session->customer ?? null;
            
            // Set customer details
            if ($customer) {
                Log::info('Setting customer details on order - Name: ' . ($customer->name ?? 'null') . ', Email: ' . ($customer->email ?? 'null'));
                $order->name = $customer->name;
                $order->email = $customer->email;
            } else {
                // Try to get customer details from session
                $order->name = $session->customer_details->name ?? null;
                $order->email = $session->customer_details->email ?? null;
                Log::info('Setting customer details from session - Name: ' . ($order->name ?? 'null') . ', Email: ' . ($order->email ?? 'null'));
            }

            // Set plan and user details
            $order->plan_id = $planId;
            $order->plan_name = $planName;
            $order->user_id = $userId;
            $order->is_recurring = false;

            // Handle subscription if present
            if ($session->subscription) {
                Log::info('Processing subscription with ID: ' . $session->subscription);
                $order->is_recurring = true;
                $order->stripe_subscription_id = $session->subscription;
                
                // Get subscription details
                try {
                    Log::info('Retrieving subscription details');
                    $subscription = \Stripe\Subscription::retrieve($session->subscription);
                    if ($subscription) {
                        Log::info('Subscription retrieved - Status: ' . $subscription->status);
                        // Check if subscription has items and price data
                        if (!empty($subscription->items->data)) {
                            Log::info('Subscription has ' . count($subscription->items->data) . ' items');
                            if (isset($subscription->items->data[0]->price->recurring)) {
                                $interval = $subscription->items->data[0]->price->recurring->interval ?? null;
                                Log::info('Setting subscription interval: ' . $interval);
                                $order->interval = $interval;
                            } else {
                                Log::warning('No recurring information found in subscription price data');
                            }
                        } else {
                            Log::warning('No items data found in subscription');
                        }
                        
                        // Create subscription record
                        Log::info('Creating subscription record');
                        $this->createSubscriptionRecord($order, [
                            'subscription' => $subscription,
                            'customer' => $customer,
                            'product' => isset($subscription->items->data[0]->price->product) ? $subscription->items->data[0]->price->product : null,
                            'price' => isset($subscription->items->data[0]->price) ? $subscription->items->data[0]->price : null
                        ]);
                    }
                } catch (\Exception $e) {
                    Log::warning('Failed to retrieve subscription: ' . $e->getMessage());
                    Log::warning($e->getTraceAsString());
                }
            }

            // Log all order properties before saving
            $orderProperties = [];
            foreach ($order->getAttributes() as $key => $value) {
                // Don't log large objects
                if (!is_object($value) && !is_array($value)) {
                    $orderProperties[$key] = $value;
                } elseif (is_array($value)) {
                    $orderProperties[$key] = json_encode($value);
                } else {
                    $orderProperties[$key] = "Object: " . get_class($value);
                }
            }
            Log::info('Order properties before save: ' . json_encode($orderProperties));

            // Save order and log result
            try {
                DB::beginTransaction();
                $result = $order->save();
                DB::commit();
                
                if ($result) {
                    Log::info('Order saved successfully with ID: ' . $order->id);
                } else {
                    Log::error('Order save failed - did not return true');
                }
            } catch (\Exception $e) {
                DB::rollBack();
                Log::error('Exception during order save: ' . $e->getMessage());
                Log::error($e->getTraceAsString());
                
                // Check for specific database errors
                if (strpos($e->getMessage(), 'Incorrect integer value') !== false) {
                    Log::error('Database data type error - txn_id might be defined as integer instead of string');
                }
                throw $e; // Re-throw to be caught by the outer catch block
            }

            Log::info('Created order for checkout session: ' . $session->id);
            return response('Order created for checkout session', 200);
        } catch (\Exception $e) {
            Log::error('Error processing checkout session: ' . $e->getMessage());
            Log::error($e->getTraceAsString());
            return response('Error processing checkout session: ' . $e->getMessage(), 500);
        }
    }

    /**
     * Handle invoice.paid webhook event
     *
     * @param \Stripe\Invoice $invoice
     * @return \Illuminate\Http\Response
     */
    private function handleInvoicePaid($invoice)
    {
        Log::info('Handling invoice.paid for invoice: ' . $invoice->id);
        
        try {
            // Get the subscription from the invoice
            $subscription = $invoice->subscription;
            if (!$subscription) {
                Log::warning('No subscription found for invoice: ' . $invoice->id);
                return response('No subscription found', 200);
            }

            // Find the subscription in our database
            $appSubscription = AppSubscription::where('stripe_id', $subscription)->first();
            if (!$appSubscription) {
                Log::warning('Subscription not found in database: ' . $subscription);
                return response('Subscription not found', 200);
            }

            // Update subscription status and period
            $appSubscription->stripe_status = 'active';
            $appSubscription->current_period_start = Carbon::createFromTimestamp($invoice->period_start);
            $appSubscription->current_period_end = Carbon::createFromTimestamp($invoice->period_end);
            $appSubscription->save();

            // Create a new order for the renewal
            $order = new Order();
            $order->order_id = $this->generateOrderId();
            $order->name = $appSubscription->user->name ?? null;
            $order->email = $appSubscription->user->email ?? null;
            $order->plan_id = $appSubscription->plan_id;
            $order->plan_name = $appSubscription->name;
            $order->price = $invoice->amount_paid / 100;
            $order->original_price = $invoice->amount_paid / 100;
            $order->price_curency = strtolower($invoice->currency);
            $order->payment_status = config('constants.payment_statuses.completed');
            $order->payment_type = config('constants.payment_types.stripe');
            $order->txn_id = $invoice->payment_intent;
            $order->stripe_customer_id = $invoice->customer;
            $order->stripe_subscription_id = $subscription;
            $order->is_recurring = true;
            $order->user_id = $appSubscription->user_id;
            $order->interval = $appSubscription->interval;
            $order->metadata = [
                'invoice_id' => $invoice->id,
                'subscription_id' => $subscription
            ];
            $order->save();

            Log::info('Created renewal order for subscription: ' . $subscription);
            return response('Renewal order created', 200);
        } catch (\Exception $e) {
            Log::error('Error handling invoice.paid: ' . $e->getMessage());
            return response('Error processing invoice', 500);
        }
    }

    /**
     * Handle invoice.payment_failed webhook event
     *
     * @param \Stripe\Invoice $invoice
     * @return \Illuminate\Http\Response
     */
    private function handleInvoicePaymentFailed($invoice)
    {
        Log::info('Handling invoice.payment_failed for invoice: ' . $invoice->id);
        
        try {
            $subscription = $invoice->subscription;
            if (!$subscription) {
                return response('No subscription found', 200);
            }

            $appSubscription = AppSubscription::where('stripe_id', $subscription)->first();
            if ($appSubscription) {
                $appSubscription->stripe_status = 'past_due';
                $appSubscription->save();

                // Notify user about failed payment
                // TODO: Implement notification system
            }

            return response('Payment failure handled', 200);
        } catch (\Exception $e) {
            Log::error('Error handling invoice.payment_failed: ' . $e->getMessage());
            return response('Error processing payment failure', 500);
        }
    }

    /**
     * Handle customer.subscription.updated webhook event
     *
     * @param \Stripe\Subscription $subscription
     * @return \Illuminate\Http\Response
     */
    private function handleSubscriptionUpdated($subscription)
    {
        Log::info('Handling subscription.updated for subscription: ' . $subscription->id);
        
        try {
            $appSubscription = AppSubscription::where('stripe_id', $subscription->id)->first();
            if (!$appSubscription) {
                return response('Subscription not found', 200);
            }

            // Update subscription status and period
            $appSubscription->stripe_status = $subscription->status;
            $appSubscription->current_period_start = Carbon::createFromTimestamp($subscription->current_period_start);
            $appSubscription->current_period_end = Carbon::createFromTimestamp($subscription->current_period_end);
            
            // Handle cancel_at_period_end flag
            $appSubscription->cancel_at_period_end = $subscription->cancel_at_period_end ?? false;
            
            if ($subscription->cancel_at_period_end) {
                $appSubscription->ends_at = Carbon::createFromTimestamp($subscription->current_period_end);
            } else {
                // If subscription is no longer set to cancel, clear the ends_at date
                $appSubscription->ends_at = null;
            }
            
            $appSubscription->save();

            return response('Subscription updated', 200);
        } catch (\Exception $e) {
            Log::error('Error handling subscription.updated: ' . $e->getMessage());
            return response('Error updating subscription', 500);
        }
    }

    /**
     * Handle customer.subscription.deleted webhook event
     *
     * @param \Stripe\Subscription $subscription
     * @return \Illuminate\Http\Response
     */
    private function handleSubscriptionDeleted($subscription)
    {
        Log::info('Handling subscription.deleted for subscription: ' . $subscription->id);
        
        try {
            $appSubscription = AppSubscription::where('stripe_id', $subscription->id)->first();
            if (!$appSubscription) {
                return response('Subscription not found', 200);
            }

            // Update subscription status
            $appSubscription->stripe_status = 'canceled';
            $appSubscription->ends_at = Carbon::now();
            $appSubscription->save();

            return response('Subscription canceled', 200);
        } catch (\Exception $e) {
            Log::error('Error handling subscription.deleted: ' . $e->getMessage());
            return response('Error canceling subscription', 500);
        }
    }
}