<?php

namespace App\Services\Gateways;

use App\Services\PaymentGatewayInterface;
use App\Models\PaymentGateway;
use App\Models\Invoice;
use App\Models\Transaction;
use App\Models\Subscription;
use Stripe\Stripe;
use Stripe\Customer;
use Stripe\Checkout\Session;
use Stripe\Webhook;
use Stripe\Exception\SignatureVerificationException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;

class StripeGateway implements PaymentGatewayInterface
{
    protected $gateway;

    public function __construct()
    {
        $this->gateway = PaymentGateway::where('provider', 'stripe')->first();
        
        // Try to get API key from database first, then fall back to environment variable
        if ($this->gateway) {
            // Use test or live key based on is_live_mode
            $secretKey = $this->gateway->is_live_mode 
                ? $this->gateway->live_secret_key 
                : $this->gateway->test_secret_key;
            
            if ($secretKey) {
                Stripe::setApiKey($secretKey);
                Log::info('Stripe API key loaded from database');
            } else {
                // Fall back to environment variable
                $envKey = env('STRIPE_SECRET_KEY');
                if ($envKey && $envKey !== 'sk_test_REPLACEME') {
                    Stripe::setApiKey($envKey);
                    Log::info('Stripe API key loaded from environment');
                } else {
                    Log::warning('Stripe API key not configured. Please set STRIPE_SECRET_KEY in .env or configure in payment_gateways table.');
                }
            }
        } else {
            // Fall back to environment variable
            $envKey = env('STRIPE_SECRET_KEY');
            if ($envKey && $envKey !== 'sk_test_REPLACEME') {
                Stripe::setApiKey($envKey);
                Log::info('Stripe API key loaded from environment (no database config found)');
            } else {
                Log::warning('Stripe API key not configured. Please set STRIPE_SECRET_KEY in .env or configure in payment_gateways table.');
            }
        }
    }

    /**
     * Create a Stripe customer.
     */
    public function createCustomer(array $customerData)
    {
        return Customer::create([
            'email' => $customerData['email'],
            'name' => $customerData['name'] ?? null,
            'metadata' => $customerData['metadata'] ?? [],
        ]);
    }

    /**
     * Create a checkout session for one-time payment.
     */
    public function createOneTimeCheckout(array $paymentData)
    {
        $sessionData = [
            'payment_method_types' => ['card'],
            'line_items' => [[
                'price_data' => [
                    'currency' => $paymentData['currency'] ?? 'usd',
                    'product_data' => [
                        'name' => $paymentData['product_name'],
                        'description' => $paymentData['description'] ?? null,
                    ],
                    'unit_amount' => $paymentData['amount'] * 100, // Convert to cents
                ],
                'quantity' => 1,
            ]],
            'mode' => 'payment',
            'success_url' => $paymentData['success_url'],
            'cancel_url' => $paymentData['cancel_url'],
            'client_reference_id' => $paymentData['reference_id'] ?? null,
            'metadata' => $paymentData['metadata'] ?? [],
        ];

        // Add customer if provided
        if (!empty($paymentData['customer_id'])) {
            $sessionData['customer'] = $paymentData['customer_id'];
        }

        return Session::create($sessionData);
    }

    /**
     * Create a checkout session for subscription.
     */
    public function createSubscriptionCheckout(array $subscriptionData)
    {
        Log::info('StripeGateway: Creating subscription checkout', [
            'interval' => $subscriptionData['interval'] ?? 'NOT SET',
            'amount' => $subscriptionData['amount'] ?? 'NOT SET',
            'product_name' => $subscriptionData['product_name'] ?? 'NOT SET',
        ]);
        
        // If price_id is provided, use it (existing Stripe Price)
        if (isset($subscriptionData['price_id'])) {
            $lineItems = [[
                'price' => $subscriptionData['price_id'],
                'quantity' => 1,
            ]];
        } else {
            // Otherwise, create inline price data
            $lineItems = [[
                'price_data' => [
                    'currency' => $subscriptionData['currency'] ?? 'usd',
                    'product_data' => [
                        'name' => $subscriptionData['product_name'],
                        'description' => $subscriptionData['description'] ?? null,
                    ],
                    'unit_amount' => $subscriptionData['amount'] * 100, // Convert to cents
                    'recurring' => [
                        'interval' => $subscriptionData['interval'] ?? 'month', // month or year
                    ],
                ],
                'quantity' => 1,
            ]];
        }

        $sessionParams = [
            'payment_method_types' => ['card'],
            'line_items' => $lineItems,
            'mode' => 'subscription',
            'success_url' => $subscriptionData['success_url'],
            'cancel_url' => $subscriptionData['cancel_url'],
            'client_reference_id' => $subscriptionData['reference_id'] ?? null,
            'metadata' => $subscriptionData['metadata'] ?? [],
        ];

        // For Accounts V2, we must provide a customer
        if (isset($subscriptionData['customer_id'])) {
            $sessionParams['customer'] = $subscriptionData['customer_id'];
            Log::info('Using existing customer for subscription checkout', [
                'customer_id' => $subscriptionData['customer_id']
            ]);
        } else {
            // Fallback: let Stripe create customer automatically
            $sessionParams['customer_creation'] = 'always';
            Log::warning('No customer_id provided, using customer_creation');
        }

        Log::info('Creating subscription checkout session', [
            'mode' => 'subscription',
            'has_customer' => isset($sessionParams['customer']),
            'has_customer_creation' => isset($sessionParams['customer_creation']),
        ]);

        return Session::create($sessionParams);
    }

    /**
     * Handle Stripe webhook events.
     */
    public function handleWebhook(string $payload, string $signature): bool
    {
        try {
            // Get webhook secret based on mode
            $webhookSecret = $this->gateway->is_live_mode 
                ? $this->gateway->live_webhook_secret 
                : $this->gateway->test_webhook_secret;
                
            if (!$webhookSecret) {
                Log::error('Stripe webhook secret not configured');
                return false;
            }
            
            Log::info('Attempting webhook verification', [
                'has_secret' => !empty($webhookSecret),
                'secret_prefix' => substr($webhookSecret, 0, 10),
                'has_signature' => !empty($signature),
                'signature_prefix' => substr($signature, 0, 20),
            ]);
            
            $event = Webhook::constructEvent(
                $payload,  // Now it's raw JSON string, not array
                $signature,
                $webhookSecret
            );
        } catch (SignatureVerificationException $e) {
            Log::error('Stripe webhook signature verification failed: ' . $e->getMessage());
            return false;
        }

        // Handle different event types
        switch ($event->type) {
            case 'checkout.session.completed':
                $this->handleCheckoutCompleted($event->data->object);
                break;

            case 'payment_intent.succeeded':
                $this->handlePaymentSucceeded($event->data->object);
                break;

            case 'payment_intent.payment_failed':
                $this->handlePaymentFailed($event->data->object);
                break;

            case 'customer.subscription.updated':
                $this->handleSubscriptionUpdated($event->data->object);
                break;

            case 'customer.subscription.deleted':
                $this->handleSubscriptionDeleted($event->data->object);
                break;

            case 'invoice.payment_succeeded':
            case 'invoice.paid':
                $this->handleInvoicePaymentSucceeded($event->data->object);
                break;

            case 'invoice.payment_failed':
                $this->handleInvoicePaymentFailed($event->data->object);
                break;

            case 'setup_intent.succeeded':
                $this->handleSetupIntentSucceeded($event->data->object);
                break;

            default:
                Log::info('Unhandled Stripe webhook event: ' . $event->type);
        }

        return true;
    }

    /**
     * Cancel a Stripe subscription.
     */
    public function cancelSubscription(string $subscriptionId): bool
    {
        try {
            $subscription = \Stripe\Subscription::retrieve($subscriptionId);
            $subscription->cancel();
            return true;
        } catch (\Exception $e) {
            Log::error('Failed to cancel Stripe subscription: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * Get gateway name.
     */
    public function getName(): string
    {
        return 'Stripe';
    }

    /**
     * Retrieve a checkout session from Stripe.
     */
    public function retrieveCheckoutSession(string $sessionId)
    {
        try {
            return \Stripe\Checkout\Session::retrieve($sessionId);
        } catch (\Exception $e) {
            Log::error('Failed to retrieve checkout session: ' . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Update a Stripe subscription.
     * 
     * @param string $subscriptionId The Stripe subscription ID
     * @param array $data Data to update (e.g., ['cancel_at_period_end' => true])
     * @return \Stripe\Subscription
     */
    public function updateSubscription(string $subscriptionId, array $data)
    {
        try {
            Log::info("Updating Stripe subscription", [
                'subscription_id' => $subscriptionId,
                'data' => $data
            ]);

            return \Stripe\Subscription::update($subscriptionId, $data);
        } catch (\Exception $e) {
            Log::error('Failed to update subscription: ' . $e->getMessage(), [
                'subscription_id' => $subscriptionId,
                'data' => $data
            ]);
            throw $e;
        }
    }

    /**
     * Get customer's default payment method from Stripe
     * 
     * @param string $customerId The Stripe customer ID
     * @return array|null Payment method details (brand, last4, exp_month, exp_year)
     */
    public function getCustomerPaymentMethod(string $customerId)
    {
        try {
            Log::info('Fetching payment method for customer', ['customer_id' => $customerId]);

            // Retrieve customer with default payment method
            $customer = \Stripe\Customer::retrieve([
                'id' => $customerId,
                'expand' => ['invoice_settings.default_payment_method']
            ]);

            $paymentMethod = $customer->invoice_settings->default_payment_method;

            // If payment method is a string ID, retrieve the full object
            if (is_string($paymentMethod)) {
                Log::info('Payment method is ID, retrieving full object', ['pm_id' => $paymentMethod]);
                $paymentMethod = \Stripe\PaymentMethod::retrieve($paymentMethod);
            }

            if (!$paymentMethod) {
                Log::info('No default payment method on customer, checking subscriptions');
                
                // Try to get from subscriptions
                $subscriptions = \Stripe\Subscription::all([
                    'customer' => $customerId,
                    'status' => 'active',
                    'limit' => 1
                ]);

                if ($subscriptions->data && count($subscriptions->data) > 0) {
                    $subscription = $subscriptions->data[0];
                    Log::info('Found active subscription', [
                        'subscription_id' => $subscription->id,
                        'default_payment_method' => $subscription->default_payment_method
                    ]);
                    
                    if ($subscription->default_payment_method) {
                        $paymentMethod = \Stripe\PaymentMethod::retrieve($subscription->default_payment_method);
                    }
                }
            }

            if ($paymentMethod && is_object($paymentMethod)) {
                $result = [
                    'brand' => $paymentMethod->card->brand ?? 'card',
                    'last4' => $paymentMethod->card->last4 ?? '****',
                    'exp_month' => $paymentMethod->card->exp_month ?? null,
                    'exp_year' => $paymentMethod->card->exp_year ?? null,
                ];
                
                Log::info('Payment method retrieved successfully', $result);
                return $result;
            }

            Log::warning('No payment method found for customer', ['customer_id' => $customerId]);
            return null;
        } catch (\Exception $e) {
            Log::error('Failed to get payment method: ' . $e->getMessage(), [
                'customer_id' => $customerId,
                'trace' => $e->getTraceAsString()
            ]);
            return null;
        }
    }

    /**
     * Create a Stripe Checkout session to update payment method
     * 
     * @param array $data Session data (customer_id, success_url, cancel_url)
     * @return \Stripe\Checkout\Session
     */
    public function createPaymentMethodUpdateSession(array $data)
    {
        try {
            return \Stripe\Checkout\Session::create([
                'mode' => 'setup',
                'customer' => $data['customer_id'],
                'payment_method_types' => ['card'],
                'success_url' => $data['success_url'],
                'cancel_url' => $data['cancel_url'],
                'metadata' => [
                    'purpose' => 'update_payment_method',
                ],
            ]);
        } catch (\Exception $e) {
            Log::error('Failed to create payment method update session: ' . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Handle checkout session completed.
     */
    protected function handleCheckoutCompleted($session)
    {
        Log::info('Stripe checkout completed', [
            'session_id' => $session->id,
            'mode' => $session->mode,
            'payment_status' => $session->payment_status,
            'customer' => $session->customer ?? 'guest',
        ]);

        // Extract metadata
        $userId = $session->client_reference_id;
        $metadata = $session->metadata;

        // Check if this is a quotation payment
        if (isset($metadata->payment_type) && $metadata->payment_type === 'quotation') {
            $this->handleQuotationPayment($session, $metadata);
            return;
        }

        // Check if this is an ImmigoPro installment payment
        if (isset($metadata->type) && $metadata->type === 'immigopro_installment') {
            $this->handleImmigoProInstallmentPayment($session, $metadata);
            return;
        }

        // Check if this is an ImmigoPro subsequent installment payment
        if (isset($metadata->type) && $metadata->type === 'immigopro_installment_payment') {
            $this->handleImmigoProInstallmentPaymentCharge($session, $metadata);
            return;
        }

        // Check if this is a course enrollment payment
        if (isset($metadata->payment_type) && $metadata->payment_type === 'course_enrollment') {
            $this->handleCourseEnrollmentPayment($session, $metadata);
            return;
        }

        if ($session->mode === 'payment') {
            // Check if this is a subscription payment
            $subscription = Subscription::where('stripe_session_id', $session->id)->first();
            
            if ($subscription) {
                // Calculate subscription period (default to monthly)
                $currentPeriodStart = now();
                $interval = $subscription->interval ?? 'month';
                $currentPeriodEnd = match($interval) {
                    'month' => now()->addMonth(),
                    'year' => now()->addYear(),
                    'week' => now()->addWeek(),
                    default => now()->addMonth(),
                };
                
                // Update subscription with all available Stripe data
                $updateData = [
                    'status' => 'active',
                    'activated_at' => now(),
                    'stripe_session_id' => $session->id,
                    'current_period_start' => $currentPeriodStart,
                    'current_period_end' => $currentPeriodEnd,
                    'expires_at' => $currentPeriodEnd,
                ];
                
                // Add customer ID if available (created customer)
                if ($session->customer) {
                    $updateData['stripe_customer_id'] = $session->customer;
                }
                
                // Add subscription ID if this is a recurring subscription
                if ($session->subscription) {
                    $updateData['stripe_subscription_id'] = $session->subscription;
                    $updateData['gateway_subscription_id'] = $session->subscription;
                }
                
                $subscription->update($updateData);
                
                Log::info('Subscription activated with full data', [
                    'subscription_id' => $subscription->id,
                    'stripe_customer_id' => $session->customer ?? 'guest',
                    'stripe_subscription_id' => $session->subscription ?? 'one-time',
                    'payment_intent' => $session->payment_intent,
                    'period_start' => $currentPeriodStart,
                    'period_end' => $currentPeriodEnd,
                ]);
                
                // Convert metadata object to array for JSON storage
                $invoiceMetadata = $metadata ? json_decode(json_encode($metadata), true) : [];
                
                // Create invoice and transaction for this subscription
                $invoice = Invoice::create([
                    'user_id' => $subscription->user_id,
                    'subscription_id' => $subscription->id,
                    'invoice_number' => 'INV-' . strtoupper(uniqid()),
                    'amount' => $session->amount_total / 100,
                    'currency' => $session->currency,
                    'status' => 'paid',
                    'paid_at' => now(),
                    'metadata' => json_encode($invoiceMetadata),
                ]);

                Transaction::create([
                    'invoice_id' => $invoice->id,
                    'subscription_id' => $subscription->id,
                    'user_id' => $subscription->user_id,
                    'gateway_provider' => 'stripe',
                    'gateway_transaction_id' => $session->payment_intent,
                    'type' => 'payment',
                    'amount' => $session->amount_total / 100,
                    'currency' => $session->currency,
                    'status' => 'completed',
                    'metadata' => json_encode($invoiceMetadata),
                ]);
                
                Log::info('Invoice and transaction created', [
                    'invoice_id' => $invoice->id,
                    'subscription_id' => $subscription->id,
                    'payment_intent' => $session->payment_intent,
                ]);
            } else {
                Log::warning('Checkout completed but subscription not found', [
                    'session_id' => $session->id,
                    'user_id' => $userId,
                ]);
            }
        } elseif ($session->mode === 'subscription') {
            // Recurring subscription mode - customer and subscription are created
            Log::info('Subscription checkout completed', [
                'session_id' => $session->id,
                'customer' => $session->customer,
                'subscription' => $session->subscription,
            ]);
            
            // Find our subscription record
            $subscription = Subscription::where('stripe_session_id', $session->id)->first();
            
            if ($subscription) {
                // Get the Stripe subscription object for period details
                try {
                    $stripeSubscription = \Stripe\Subscription::retrieve($session->subscription);
                    
                    // Update subscription with Stripe data
                    $updateData = [
                        'status' => 'active',
                        'activated_at' => now(),
                        'stripe_customer_id' => $session->customer,
                        'stripe_subscription_id' => $session->subscription,
                        'gateway_subscription_id' => $session->subscription,
                        'current_period_start' => \Carbon\Carbon::createFromTimestamp($stripeSubscription->current_period_start),
                        'current_period_end' => \Carbon\Carbon::createFromTimestamp($stripeSubscription->current_period_end),
                        'expires_at' => \Carbon\Carbon::createFromTimestamp($stripeSubscription->current_period_end),
                    ];
                    
                    $subscription->update($updateData);
                    
                    Log::info('Subscription activated with Stripe data', [
                        'subscription_id' => $subscription->id,
                        'stripe_customer_id' => $session->customer,
                        'stripe_subscription_id' => $session->subscription,
                        'current_period_start' => $updateData['current_period_start'],
                        'current_period_end' => $updateData['current_period_end'],
                    ]);
                    
                    // Create invoice and transaction
                    $invoice = Invoice::create([
                        'user_id' => $subscription->user_id,
                        'subscription_id' => $subscription->id,
                        'invoice_number' => 'INV-' . strtoupper(uniqid()),
                        'amount' => $session->amount_total / 100,
                        'currency' => $session->currency,
                        'status' => 'paid',
                        'paid_at' => now(),
                        'metadata' => $metadata,
                    ]);

                    Transaction::create([
                        'invoice_id' => $invoice->id,
                        'subscription_id' => $subscription->id,
                        'user_id' => $subscription->user_id,
                        'gateway_provider' => 'stripe',
                        'gateway_transaction_id' => $session->subscription, // Use subscription ID as transaction reference
                        'type' => 'payment',
                        'amount' => $session->amount_total / 100,
                        'currency' => $session->currency,
                        'status' => 'completed',
                        'metadata' => $metadata,
                    ]);
                    
                    Log::info('Invoice and transaction created for subscription', [
                        'invoice_id' => $invoice->id,
                        'subscription_id' => $subscription->id,
                    ]);
                } catch (\Exception $e) {
                    Log::error('Error retrieving Stripe subscription: ' . $e->getMessage());
                }
            } else {
                Log::warning('Subscription checkout completed but record not found', [
                    'session_id' => $session->id,
                    'user_id' => $userId,
                ]);
            }
        }
    }

    /**
     * Handle payment succeeded.
     */
    protected function handlePaymentSucceeded($paymentIntent)
    {
        Log::info('Stripe payment succeeded', ['payment_intent_id' => $paymentIntent->id]);
        
        // Update transaction status if exists
        $transaction = Transaction::where('gateway_transaction_id', $paymentIntent->id)->first();
        if ($transaction) {
            $transaction->markAsCompleted();
            
            // Update invoice status
            if ($transaction->invoice_id) {
                $transaction->invoice->markAsPaid();
            }
        }
    }

    /**
     * Handle payment failed.
     */
    protected function handlePaymentFailed($paymentIntent)
    {
        Log::error('Stripe payment failed', ['payment_intent_id' => $paymentIntent->id]);
        
        // Update transaction status if exists
        $transaction = Transaction::where('gateway_transaction_id', $paymentIntent->id)->first();
        if ($transaction) {
            $transaction->markAsFailed();
            
            // Update invoice status
            if ($transaction->invoice_id) {
                $transaction->invoice->markAsFailed();
            }
        }
    }

    /**
     * Handle subscription updated.
     */
    protected function handleSubscriptionUpdated($stripeSubscription)
    {
        Log::info('Stripe subscription updated', [
            'subscription_id' => $stripeSubscription->id,
            'status' => $stripeSubscription->status,
        ]);
        
        $subscription = Subscription::where('gateway_subscription_id', $stripeSubscription->id)->first();
        
        if ($subscription) {
            // Only update if we have valid period dates
            if (isset($stripeSubscription['current_period_start']) && isset($stripeSubscription['current_period_end'])) {
                $subscription->update([
                    'status' => $stripeSubscription->status,
                    'current_period_start' => date('Y-m-d H:i:s', $stripeSubscription['current_period_start']),
                    'current_period_end' => date('Y-m-d H:i:s', $stripeSubscription['current_period_end']),
                ]);
                
                Log::info('Subscription dates updated', [
                    'subscription_id' => $subscription->id,
                    'period_start' => $subscription->current_period_start,
                    'period_end' => $subscription->current_period_end,
                ]);
            } else {
                // Just update status without touching dates
                $subscription->update(['status' => $stripeSubscription->status]);
                Log::info('Subscription status updated only (no period data)', ['subscription_id' => $subscription->id]);
            }
        }
    }

    /**
     * Handle subscription deleted.
     */
    protected function handleSubscriptionDeleted($stripeSubscription)
    {
        Log::info('Stripe subscription deleted', ['subscription_id' => $stripeSubscription->id]);
        
        $subscription = Subscription::where('gateway_subscription_id', $stripeSubscription->id)->first();
        
        if ($subscription) {
            $subscription->cancel();
        }
    }

    /**
     * Handle invoice payment succeeded (for renewals).
     */
    protected function handleInvoicePaymentSucceeded($invoice)
    {
        // First, check if this is a support invoice (not a subscription invoice)
        if (isset($invoice->metadata['user_id']) && !isset($invoice->subscription)) {
            $this->handleSupportInvoicePayment($invoice);
            return;
        }
        
        $billingReason = $invoice->billing_reason ?? null;
        $amountPaid = $invoice->amount_paid ?? 0;
        $customerId = $invoice->customer ?? null;
        
        // Try to get subscription ID - retrieve fresh invoice from Stripe if needed
        $subscriptionId = null;
        try {
            // First try direct access
            $subscriptionId = $invoice->subscription ?? null;
            
            // If not found, retrieve the full invoice from Stripe API
            if (!$subscriptionId && $invoice->id) {
                $fullInvoice = \Stripe\Invoice::retrieve($invoice->id);
                $subscriptionId = $fullInvoice->subscription ?? null;
            }
        } catch (\Exception $e) {
            Log::error('Error retrieving subscription from invoice', ['error' => $e->getMessage()]);
        }
        
        Log::info('Stripe invoice payment succeeded', [
            'invoice_id' => $invoice->id,
            'customer_id' => $customerId,
            'subscription_id' => $subscriptionId,
            'amount_paid' => $amountPaid / 100,
            'billing_reason' => $billingReason,
        ]);

        // Only process subscription renewal invoices (skip initial subscription creation)
        if (!$subscriptionId) {
            // Try to find subscription by customer ID as fallback
            if ($customerId) {
                $subscription = Subscription::where('stripe_customer_id', $customerId)
                    ->where('status', 'active')
                    ->orderBy('id', 'desc')
                    ->first();
                    
                if ($subscription) {
                    $subscriptionId = $subscription->stripe_subscription_id;
                    Log::info('Found subscription by customer ID', [
                        'subscription_id' => $subscriptionId,
                        'db_subscription_id' => $subscription->id,
                    ]);
                }
            }
            
            if (!$subscriptionId) {
                Log::warning('Skipping invoice - no subscription ID found');
                return;
            }
        }
        
        if ($billingReason === 'subscription_create') {
            Log::info('Skipping invoice - initial subscription creation', ['billing_reason' => $billingReason]);
            return;
        }
        
        // Process renewals (billing_reason will be 'subscription_cycle' for renewals)
        Log::info('Processing renewal invoice', ['billing_reason' => $billingReason]);

        // Find subscription by stripe subscription ID
        $subscription = Subscription::where('stripe_subscription_id', $subscriptionId)
            ->orWhere('gateway_subscription_id', $subscriptionId)
            ->first();

        if (!$subscription) {
            Log::warning('Subscription not found for renewal invoice', ['subscription_id' => $subscriptionId]);
            return;
        }

        // Retrieve full subscription object for period dates
        $stripeSubscription = \Stripe\Subscription::retrieve($subscriptionId);

        // Update subscription period and expiry date
        $newPeriodEnd = date('Y-m-d H:i:s', $stripeSubscription['current_period_end']);
        $subscription->update([
            'status' => $stripeSubscription->status,
            'current_period_start' => date('Y-m-d H:i:s', $stripeSubscription['current_period_start']),
            'current_period_end' => $newPeriodEnd,
            'expires_at' => $newPeriodEnd,
        ]);

        // Check if invoice already exists for this period (prevent duplicates)
        $paidAtDate = date('Y-m-d H:i:s', $invoice->created ?? $invoice['created']);
        $existingInvoice = Invoice::where('subscription_id', $subscription->id)
            ->where('paid_at', $paidAtDate)
            ->first();
            
        if ($existingInvoice) {
            Log::info('Invoice already exists for this renewal period, skipping duplicate', [
                'subscription_id' => $subscription->id,
                'existing_invoice_id' => $existingInvoice->id,
                'paid_at' => $paidAtDate,
            ]);
            return;
        }

        // Create invoice record for the renewal
        $invoiceRecord = Invoice::create([
            'user_id' => $subscription->user_id,
            'subscription_id' => $subscription->id,
            'invoice_number' => 'INV-' . strtoupper(uniqid()),
            'amount' => ($invoice->amount_paid ?? $invoice['amount_paid']) / 100,
            'currency' => strtoupper($invoice->currency ?? $invoice['currency']),
            'status' => 'paid',
            'due_date' => now(),
            'paid_at' => $paidAtDate,
        ]);

        // Create transaction record
        Transaction::create([
            'subscription_id' => $subscription->id,
            'invoice_id' => $invoiceRecord->id,
            'amount' => ($invoice->amount_paid ?? $invoice['amount_paid']) / 100,
            'currency' => strtoupper($invoice->currency ?? $invoice['currency']),
            'payment_method' => ($invoice->payment_intent ?? $invoice['payment_intent']) ? 'card' : 'unknown',
            'gateway_transaction_id' => $invoice->payment_intent ?? $invoice['payment_intent'] ?? $invoice->id,
            'status' => 'completed',
            'processed_at' => now(),
        ]);

        Log::info('Subscription renewed successfully', [
            'subscription_id' => $subscription->id,
            'invoice_id' => $invoiceRecord->id,
            'new_period_end' => $subscription->current_period_end,
        ]);
    }

    /**
     * Handle invoice payment failed.
     */
    protected function handleInvoicePaymentFailed($invoice)
    {
        $subscriptionId = $invoice->subscription ?? $invoice['subscription'] ?? null;
        $amountDue = $invoice->amount_due ?? $invoice['amount_due'] ?? 0;
        
        Log::warning('Stripe invoice payment failed', [
            'invoice_id' => $invoice->id,
            'subscription_id' => $subscriptionId,
            'amount_due' => $amountDue / 100,
        ]);

        if (!$subscriptionId) {
            return;
        }

        $subscription = Subscription::where('stripe_subscription_id', $subscriptionId)
            ->orWhere('gateway_subscription_id', $subscriptionId)
            ->first();

        if ($subscription) {
            // Optionally mark subscription as having payment issues
            Log::warning('Subscription payment failed', ['subscription_id' => $subscription->id]);
        }
    }

    /**
     * Handle course enrollment payment completion.
     */
    protected function handleCourseEnrollmentPayment($session, $metadata)
    {
        Log::info('Processing course enrollment payment', [
            'session_id' => $session->id,
            'course_id' => $metadata->course_id ?? null,
            'user_id' => $metadata->user_id ?? null,
        ]);

        try {
            $userId = $metadata->user_id;
            $courseId = $metadata->course_id;
            
            // Check if already enrolled
        $existingEnrollment = DB::table('lms_course_enrollments')
                ->where('user_id', $userId)
                ->first();

            if ($existingEnrollment) {
                Log::info('User already enrolled in course', [
                    'user_id' => $userId,
                    'course_id' => $courseId,
                ]);
                return;
            }

            DB::beginTransaction();

            // Create enrollment
            $enrollmentId = DB::table('lms_course_enrollments')->insertGetId([
                'course_id' => $courseId,
                'user_id' => $userId,
                'enrollment_date' => now(),
                'status' => 'active',
                'progress' => 0,
                'created_at' => now(),
                'updated_at' => now(),
            ]);

            // Create invoice
            $invoice = Invoice::create([
                'user_id' => $userId,
                'invoice_number' => 'INV-' . strtoupper(uniqid()),
                'amount' => $metadata->total_amount ?? ($session->amount_total / 100),
                'currency' => strtoupper($session->currency),
                'status' => 'paid',
                'due_date' => now(),
                'paid_at' => now(),
                'metadata' => json_encode([
                    'course_id' => $courseId,
                    'course_title' => $metadata->course_title ?? '',
                    'payment_type' => 'course_enrollment',
                    'amount' => $metadata->amount ?? 0,
                    'tax_amount' => $metadata->tax_amount ?? 0,
                    'stripe_session_id' => $session->id,
                ]),
            ]);

            // Create transaction
            Transaction::create([
                'user_id' => $userId,
                'invoice_id' => $invoice->id,
                'amount' => $metadata->total_amount ?? ($session->amount_total / 100),
                'currency' => strtoupper($session->currency),
                'payment_method' => 'card',
                'gateway_provider' => 'stripe',
                'gateway_transaction_id' => $session->payment_intent,
                'status' => 'completed',
                'processed_at' => now(),
                'metadata' => json_encode([
                    'course_id' => $courseId,
                    'course_title' => $metadata->course_title ?? '',
                    'payment_type' => 'course_enrollment',
                    'stripe_session_id' => $session->id,
                ]),
            ]);

            DB::commit();

            Log::info('Course enrollment payment processed successfully', [
                'enrollment_id' => $enrollmentId,
                'invoice_id' => $invoice->id,
                'user_id' => $userId,
                'course_id' => $courseId,
            ]);

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Failed to process course enrollment payment', [
                'error' => $e->getMessage(),
                'session_id' => $session->id,
            ]);
        }
    }

    /**
     * Handle setup intent succeeded (payment method update)
     */
    protected function handleSetupIntentSucceeded($setupIntent)
    {
        try {
            Log::info('Setup intent succeeded', [
                'setup_intent_id' => $setupIntent->id,
                'customer' => $setupIntent->customer,
                'payment_method' => $setupIntent->payment_method,
            ]);

            // Get customer ID
            $customerId = $setupIntent->customer;

            if (!$customerId) {
                Log::warning('Setup intent has no customer ID');
                return;
            }

            // Update the customer's default payment method
            \Stripe\Customer::update($customerId, [
                'invoice_settings' => [
                    'default_payment_method' => $setupIntent->payment_method,
                ],
            ]);

            // Update all active subscriptions for this customer to use the new payment method
            $subscriptions = \Stripe\Subscription::all([
                'customer' => $customerId,
                'status' => 'active',
            ]);

            foreach ($subscriptions->data as $subscription) {
                \Stripe\Subscription::update($subscription->id, [
                    'default_payment_method' => $setupIntent->payment_method,
                ]);

                Log::info('Updated subscription with new payment method', [
                    'subscription_id' => $subscription->id,
                    'payment_method' => $setupIntent->payment_method,
                ]);
            }

            Log::info('Payment method updated successfully for customer', [
                'customer_id' => $customerId,
                'payment_method' => $setupIntent->payment_method,
            ]);

        } catch (\Exception $e) {
            Log::error('Failed to handle setup intent succeeded', [
                'error' => $e->getMessage(),
                'setup_intent_id' => $setupIntent->id,
            ]);
        }
    }

    /**
     * Handle ImmigoPro installment payment completion
     */
    protected function handleImmigoProInstallmentPayment($session, $metadata)
    {
        try {
            Log::info('Processing ImmigoPro installment payment', [
                'session_id' => $session->id,
                'user_id' => $metadata->user_id ?? null,
                'package_id' => $metadata->package_id ?? null,
                'payment_plan' => $metadata->payment_plan ?? null,
            ]);

            // Find the pending subscription
            $subscription = \App\Models\ImmigoProSubscription::where('stripe_checkout_session_id', $session->id)
                ->where('status', 'pending')
                ->first();

            if (!$subscription) {
                Log::error('ImmigoPro subscription not found for session', [
                    'session_id' => $session->id,
                ]);
                return;
            }

            // Update user with Stripe customer ID if not already set
            if ($session->customer && !$subscription->user->stripe_customer_id) {
                $subscription->user->update(['stripe_customer_id' => $session->customer]);
                Log::info('Updated user with Stripe customer ID', [
                    'user_id' => $subscription->user_id,
                    'customer_id' => $session->customer,
                ]);
            }

            // Generate license key if not already set
            if (!$subscription->license_key) {
                $licenseKey = $this->generateUniqueLicenseKey();
                Log::info('Generated license key for ImmigoPro subscription', [
                    'subscription_id' => $subscription->id,
                    'license_key' => $licenseKey,
                ]);
            } else {
                $licenseKey = $subscription->license_key;
            }

            // Update subscription with payment information
            $updateData = [
                'status' => 'active',
                'stripe_payment_intent_id' => $session->payment_intent,
                'license_key' => $licenseKey,
            ];

            // Store payment method for future charges if there are installments
            if ($subscription->installments > 0 && $session->payment_intent) {
                // Retrieve payment intent to get payment method
                try {
                    $paymentIntent = \Stripe\PaymentIntent::retrieve($session->payment_intent);
                    if ($paymentIntent->payment_method) {
                        $updateData['stripe_payment_method_id'] = $paymentIntent->payment_method;
                        
                        // Calculate next charge date based on payment plan
                        // For split payment (1 installment), charge in 30 days
                        // For other plans, charge monthly
                        $daysUntilNextCharge = 30;
                        $updateData['next_charge_date'] = now()->addDays($daysUntilNextCharge);
                        
                        Log::info('Set next charge date for ImmigoPro subscription', [
                            'subscription_id' => $subscription->id,
                            'next_charge_date' => $updateData['next_charge_date'],
                            'installments_remaining' => $subscription->installments,
                        ]);
                    }
                } catch (\Exception $e) {
                    Log::error('Failed to retrieve payment method from payment intent', [
                        'error' => $e->getMessage(),
                        'payment_intent' => $session->payment_intent,
                    ]);
                }
            } else {
                // Full payment (installments = 0) - mark as completed
                $updateData['status'] = 'completed';
                $updateData['completed_at'] = now();
            }

            $subscription->update($updateData);

            Log::info('ImmigoPro subscription activated', [
                'subscription_id' => $subscription->id,
                'status' => $updateData['status'],
                'has_installments' => $subscription->installments > 0,
                'next_charge_date' => $updateData['next_charge_date'] ?? null,
            ]);

            // TODO: Send email notification to user about successful payment

        } catch (\Exception $e) {
            Log::error('Failed to handle ImmigoPro installment payment', [
                'error' => $e->getMessage(),
                'session_id' => $session->id,
                'trace' => $e->getTraceAsString(),
            ]);
        }
    }

    /**
     * Handle ImmigoPro subsequent installment payment charge
     */
    protected function handleImmigoProInstallmentPaymentCharge($session, $metadata)
    {
        try {
            Log::info('Processing ImmigoPro installment payment charge', [
                'session_id' => $session->id,
                'subscription_id' => $metadata->subscription_id ?? null,
                'installment_number' => $metadata->installment_number ?? null,
            ]);

            // Find the subscription
            $subscription = \App\Models\ImmigoProSubscription::find($metadata->subscription_id);

            if (!$subscription) {
                Log::error('ImmigoPro subscription not found', [
                    'subscription_id' => $metadata->subscription_id,
                ]);
                return;
            }

            $installmentNumber = (int)$metadata->installment_number;
            $amount = $session->amount_total / 100; // Convert from cents

            // Record the installment payment
            \App\Models\ImmigoProInstallmentPayment::create([
                'subscription_id' => $subscription->id,
                'installment_number' => $installmentNumber,
                'amount' => $subscription->monthly_amount,
                'status' => 'completed',
                'stripe_payment_intent_id' => $session->payment_intent,
                'paid_at' => now(),
            ]);

            // Update subscription
            $newPaidInstallments = $subscription->paid_installments + 1;
            $updateData = [
                'paid_installments' => $newPaidInstallments,
            ];

            // Check if all installments are paid
            if ($newPaidInstallments >= $subscription->installments) {
                $updateData['status'] = 'completed';
                $updateData['completed_at'] = now();
                $updateData['next_charge_date'] = null;
                
                Log::info('ImmigoPro subscription completed - all installments paid', [
                    'subscription_id' => $subscription->id,
                ]);
            } else {
                // Calculate next charge date
                $updateData['next_charge_date'] = now()->addDays(30);
                
                Log::info('ImmigoPro installment paid, next charge scheduled', [
                    'subscription_id' => $subscription->id,
                    'paid_installments' => $newPaidInstallments,
                    'remaining_installments' => $subscription->installments - $newPaidInstallments,
                    'next_charge_date' => $updateData['next_charge_date'],
                ]);
            }

            $subscription->update($updateData);

            Log::info('ImmigoPro installment payment recorded', [
                'subscription_id' => $subscription->id,
                'installment_number' => $installmentNumber,
                'amount' => $amount,
                'paid_installments' => $newPaidInstallments,
                'total_installments' => $subscription->installments,
            ]);

            // TODO: Send email notification to user about successful installment payment

        } catch (\Exception $e) {
            Log::error('Failed to handle ImmigoPro installment payment charge', [
                'error' => $e->getMessage(),
                'session_id' => $session->id,
                'trace' => $e->getTraceAsString(),
            ]);
        }
    }

    /**
     * Handle support invoice payment.
     */
    protected function handleSupportInvoicePayment($invoice)
    {
        try {
            Log::info('Processing support invoice payment', [
                'invoice_id' => $invoice->id,
                'amount' => ($invoice->amount_paid ?? 0) / 100,
                'status' => $invoice->status,
                'metadata' => $invoice->metadata ?? [],
            ]);

            $supportInvoice = \App\Models\SupportInvoice::where('stripe_invoice_id', $invoice->id)->first();

            if (!$supportInvoice) {
                Log::warning('Support invoice not found in database', ['stripe_invoice_id' => $invoice->id]);
                return;
            }

            // Update invoice status
            $supportInvoice->update([
                'status' => $invoice->status,
                'paid_at' => $invoice->status === 'paid' && isset($invoice->status_transitions->paid_at)
                    ? now()->setTimestamp($invoice->status_transitions->paid_at)
                    : now(),
                'payment_intent_id' => $invoice->payment_intent ?? null,
            ]);

            // Create transaction record if payment succeeded
            if ($invoice->status === 'paid' && $invoice->payment_intent) {
                try {
                    // Retrieve payment intent to get payment details
                    $paymentIntent = \Stripe\PaymentIntent::retrieve($invoice->payment_intent);
                    
                    // Get charge details
                    $charge = null;
                    if ($paymentIntent->charges && count($paymentIntent->charges->data) > 0) {
                        $charge = $paymentIntent->charges->data[0];
                    }

                    // Create transaction record
                    \App\Models\InvoiceTransaction::create([
                        'support_invoice_id' => $supportInvoice->id,
                        'user_id' => $supportInvoice->user_id,
                        'transaction_id' => $invoice->payment_intent,
                        'amount' => ($invoice->amount_paid ?? 0) / 100,
                        'currency' => strtoupper($invoice->currency ?? 'usd'),
                        'payment_method' => $paymentIntent->payment_method_types[0] ?? 'card',
                        'status' => 'succeeded',
                        'stripe_payment_intent_id' => $invoice->payment_intent,
                        'stripe_charge_id' => $charge ? $charge->id : null,
                        'payment_method_details' => $charge ? [
                            'type' => $charge->payment_method_details->type ?? null,
                            'card_brand' => $charge->payment_method_details->card->brand ?? null,
                            'card_last4' => $charge->payment_method_details->card->last4 ?? null,
                        ] : null,
                        'paid_at' => now()->setTimestamp($invoice->status_transitions->paid_at),
                    ]);

                    Log::info('Invoice transaction recorded', [
                        'invoice_id' => $supportInvoice->id,
                        'transaction_id' => $invoice->payment_intent,
                        'amount' => ($invoice->amount_paid ?? 0) / 100,
                    ]);

                } catch (\Exception $e) {
                    Log::error('Failed to create transaction record', [
                        'error' => $e->getMessage(),
                        'invoice_id' => $supportInvoice->id,
                    ]);
                }
            }

            Log::info('Support invoice payment recorded', [
                'invoice_id' => $supportInvoice->id,
                'user_id' => $supportInvoice->user_id,
                'amount' => $supportInvoice->amount,
                'status' => $supportInvoice->status,
            ]);

            // TODO: Send notification to admin about payment received
            // TODO: Send confirmation email to user

        } catch (\Exception $e) {
            Log::error('Failed to handle support invoice payment', [
                'error' => $e->getMessage(),
                'invoice_id' => $invoice->id ?? null,
                'trace' => $e->getTraceAsString(),
            ]);
        }
    }

    /**
     * Handle quotation payment success
     */
    protected function handleQuotationPayment($session, $metadata)
    {
        try {
            $quotationId = $metadata->quotation_id ?? null;
            
            if (!$quotationId) {
                Log::error('Quotation payment missing quotation_id in metadata');
                return;
            }

            $quotation = \App\Models\Quotation::find($quotationId);
            
            if (!$quotation) {
                Log::error('Quotation not found', ['quotation_id' => $quotationId]);
                return;
            }

            // Update quotation payment status
            $quotation->update([
                'payment_status' => 'paid',
                'paid_at' => now(),
                'stripe_session_id' => $session->id,
                'status' => 'accepted', // Ensure status is accepted
            ]);

            // Create invoice record for the quotation payment
            $invoice = Invoice::create([
                'user_id' => $quotation->user_id,
                'invoice_number' => 'INV-QT-' . $quotation->id . '-' . strtoupper(substr(uniqid(), -6)),
                'amount' => $session->amount_total / 100,
                'currency' => strtoupper($session->currency),
                'status' => 'paid',
                'due_date' => now(),
                'paid_at' => now(),
                'metadata' => json_encode([
                    'quotation_id' => $quotation->id,
                    'customer_name' => $quotation->customer_name,
                    'payment_type' => 'quotation',
                    'stripe_session_id' => $session->id,
                    'subtotal' => $metadata->subtotal ?? null,
                    'tax_amount' => $metadata->tax_amount ?? null,
                ]),
            ]);

            // Create transaction record
            Transaction::create([
                'user_id' => $quotation->user_id,
                'invoice_id' => $invoice->id,
                'amount' => $session->amount_total / 100,
                'currency' => strtoupper($session->currency),
                'payment_method' => 'card',
                'gateway_provider' => 'stripe',
                'gateway_transaction_id' => $session->payment_intent,
                'status' => 'completed',
                'processed_at' => now(),
                'metadata' => json_encode([
                    'quotation_id' => $quotation->id,
                    'payment_type' => 'quotation',
                    'stripe_session_id' => $session->id,
                ]),
            ]);

            Log::info('Quotation payment successful with invoice created', [
                'quotation_id' => $quotation->id,
                'user_id' => $quotation->user_id,
                'invoice_id' => $invoice->id,
                'amount' => $session->amount_total / 100,
                'session_id' => $session->id,
            ]);

            // TODO: Send payment confirmation email to user
            // TODO: Notify admin about successful payment

        } catch (\Exception $e) {
            Log::error('Failed to handle quotation payment', [
                'error' => $e->getMessage(),
                'session_id' => $session->id ?? null,
                'metadata' => $metadata ?? null,
                'trace' => $e->getTraceAsString(),
            ]);
        }
    }

    /**
     * Generate a unique license key for ImmigoPro subscriptions
     */
    private function generateUniqueLicenseKey()
    {
        do {
            // Generate format: IMGPRO-XXXX-XXXX-XXXX
            $key = 'IMGPRO-' . 
                   strtoupper(substr(md5(uniqid(rand(), true)), 0, 4)) . '-' .
                   strtoupper(substr(md5(uniqid(rand(), true)), 0, 4)) . '-' .
                   strtoupper(substr(md5(uniqid(rand(), true)), 0, 4));
            
            // Check if key already exists
            $exists = \App\Models\ImmigoProSubscription::where('license_key', $key)->exists();
        } while ($exists);

        return $key;
    }
}
