<?php

namespace App\Http\Controllers\Api\V1\Client;

use App\Http\Controllers\Controller;
use App\Services\Gateways\StripeGateway;
use App\Models\Subscription;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;

class SubscriptionController extends Controller
{
    protected $stripeGateway;

    public function __construct(StripeGateway $stripeGateway)
    {
        $this->stripeGateway = $stripeGateway;
    }

    /**
     * Create a checkout session for subscription
     */
    public function createCheckout(Request $request)
    {
        $request->validate([
            'package_id' => 'required|string',
            'package_name' => 'required|string',
            'amount' => 'required|numeric|min:0',
            'tax_amount' => 'nullable|numeric|min:0',
            'total_amount' => 'required|numeric|min:0',
            'interval' => 'required|string|in:month,year',
            'success_url' => 'required|string',
            'cancel_url' => 'required|url',
            'billing_info' => 'nullable|array',
        ]);

        try {
            $user = Auth::user();
            
            Log::info('Creating subscription checkout', [
                'interval' => $request->interval,
                'amount' => $request->amount,
                'total_amount' => $request->total_amount,
                'package_name' => $request->package_name,
            ]);

            // Create or get Stripe customer for this user (required for Accounts V2)
            $stripeCustomer = $this->stripeGateway->createCustomer([
                'email' => $user->email,
                'name' => $user->name ?? $user->email,
                'metadata' => [
                    'user_id' => $user->id,
                ],
            ]);

            // Create subscription record (pending)
            $subscription = Subscription::create([
                'user_id' => $user->id,
                'package_name' => $request->package_name,
                'package_id' => $request->package_id,
                'plan_name' => $request->package_name, // Legacy field
                'amount' => $request->amount,
                'interval' => $request->interval,
                'status' => 'pending',
                'gateway_provider' => 'stripe',
                'stripe_subscription_id' => null,
                'stripe_customer_id' => $stripeCustomer->id, // Store customer ID immediately
            ]);

            // Create Stripe checkout session for recurring subscription
            $checkoutData = [
                'product_name' => $request->package_name . ' Subscription',
                'amount' => $request->total_amount, // Use total amount including tax
                'currency' => 'usd',
                'interval' => $request->interval, // 'month' or 'year'
                'customer_id' => $stripeCustomer->id, // Pass the customer ID
                'success_url' => $request->success_url,
                'cancel_url' => $request->cancel_url,
                'reference_id' => (string) $user->id, // Send user_id as client_reference_id
                'metadata' => [
                    'user_id' => $user->id,
                    'subscription_id' => $subscription->id,
                    'package_id' => $request->package_id,
                    'package_name' => $request->package_name,
                    'base_amount' => $request->amount,
                    'tax_amount' => $request->tax_amount ?? 0,
                    'total_amount' => $request->total_amount,
                    'billing_country' => $request->billing_info['country'] ?? null,
                    'billing_province' => $request->billing_info['province'] ?? null,
                ],
            ];

            // Create recurring subscription checkout with auto-renewal
            $session = $this->stripeGateway->createSubscriptionCheckout($checkoutData);

            // Update subscription with session ID
            $subscription->update([
                'stripe_session_id' => $session->id,
            ]);

            return response()->json([
                'success' => true,
                'checkout_url' => $session->url,
                'session_id' => $session->id,
            ]);
        } catch (\Exception $e) {
            Log::error('Subscription checkout error: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'message' => 'Failed to create checkout session: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Get user's active subscription
     */
    public function getActiveSubscription()
    {
        $user = Auth::user();
        
        $subscription = Subscription::where('user_id', $user->id)
            ->where('status', 'active')
            ->first();

        return response()->json([
            'success' => true,
            'subscription' => $subscription,
        ]);
    }

    /**
     * Get all user subscriptions
     */
    public function index()
    {
        $user = Auth::user();
        
        $subscriptions = Subscription::where('user_id', $user->id)
            ->orderBy('created_at', 'desc')
            ->get();

        return response()->json([
            'success' => true,
            'subscriptions' => $subscriptions,
        ]);
    }

    /**
     * Cancel subscription
     */
    public function cancel(Request $request, $id)
    {
        $user = Auth::user();
        
        $subscription = Subscription::where('id', $id)
            ->where('user_id', $user->id)
            ->firstOrFail();

        try {
            // Cancel in Stripe if subscription has Stripe ID
            if ($subscription->stripe_subscription_id) {
                Log::info('Cancelling Stripe subscription', [
                    'subscription_id' => $subscription->id,
                    'stripe_subscription_id' => $subscription->stripe_subscription_id,
                ]);
                
                $cancelled = $this->stripeGateway->cancelSubscription($subscription->stripe_subscription_id);
                
                if (!$cancelled) {
                    throw new \Exception('Failed to cancel subscription in Stripe');
                }
                
                Log::info('Stripe subscription cancelled successfully');
            }

            $subscription->update([
                'status' => 'cancelled',
                'cancelled_at' => now(),
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Subscription cancelled successfully',
            ]);
        } catch (\Exception $e) {
            Log::error('Subscription cancellation error: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'message' => 'Failed to cancel subscription',
            ], 500);
        }
    }

    /**
     * Toggle auto-renewal for subscription
     */
    public function toggleAutoRenew(Request $request, $id)
    {
        $user = Auth::user();
        
        $request->validate([
            'auto_renew' => 'required|boolean',
        ]);

        $subscription = Subscription::where('id', $id)
            ->where('user_id', $user->id)
            ->where('status', 'active')
            ->firstOrFail();

        try {
            $autoRenew = $request->auto_renew;

            // Update in Stripe if subscription has Stripe subscription ID
            if ($subscription->stripe_subscription_id) {
                Log::info("Updating Stripe subscription auto-renewal", [
                    'stripe_subscription_id' => $subscription->stripe_subscription_id,
                    'auto_renew' => $autoRenew
                ]);

                // When auto_renew is false, set cancel_at_period_end to true
                // When auto_renew is true, set cancel_at_period_end to false
                $this->stripeGateway->updateSubscription(
                    $subscription->stripe_subscription_id,
                    ['cancel_at_period_end' => !$autoRenew]
                );

                Log::info("Stripe subscription updated successfully");
            }

            // Update local database
            $subscription->update([
                'auto_renew' => $autoRenew,
            ]);

            // Refresh the subscription to get the latest data
            $subscription->refresh();

            return response()->json([
                'success' => true,
                'message' => 'Auto-renewal ' . ($autoRenew ? 'enabled' : 'disabled') . ' successfully',
                'subscription' => $subscription,
            ]);
        } catch (\Exception $e) {
            Log::error('Toggle auto-renewal error: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'message' => 'Failed to update auto-renewal setting: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Get customer's payment method details from Stripe
     */
    public function getPaymentMethod()
    {
        $user = Auth::user();
        
        $subscription = Subscription::where('user_id', $user->id)
            ->where('status', 'active')
            ->first();

        if (!$subscription || !$subscription->stripe_customer_id) {
            return response()->json([
                'success' => true,
                'payment_method' => null,
            ]);
        }

        try {
            $paymentMethod = $this->stripeGateway->getCustomerPaymentMethod($subscription->stripe_customer_id);
            
            return response()->json([
                'success' => true,
                'payment_method' => $paymentMethod,
            ]);
        } catch (\Exception $e) {
            Log::error('Get payment method error: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve payment method',
                'payment_method' => null,
            ]);
        }
    }

    /**
     * Create a Stripe Checkout session to update payment method
     */
    public function updatePaymentMethod(Request $request)
    {
        $user = Auth::user();
        
        $request->validate([
            'success_url' => 'required|string',
            'cancel_url' => 'required|string',
        ]);

        $subscription = Subscription::where('user_id', $user->id)
            ->where('status', 'active')
            ->first();

        if (!$subscription || !$subscription->stripe_customer_id) {
            return response()->json([
                'success' => false,
                'message' => 'No active subscription found',
            ], 404);
        }

        try {
            // Create a Stripe Checkout session in 'setup' mode to update payment method
            $session = $this->stripeGateway->createPaymentMethodUpdateSession([
                'customer_id' => $subscription->stripe_customer_id,
                'success_url' => $request->success_url,
                'cancel_url' => $request->cancel_url,
            ]);

            return response()->json([
                'success' => true,
                'checkout_url' => $session->url,
                'session_id' => $session->id,
            ]);
        } catch (\Exception $e) {
            Log::error('Update payment method error: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'message' => 'Failed to create update session: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Sync payment method from Stripe after setup mode checkout
     * This is called when user returns from Stripe Checkout to manually update the payment method
     * since webhooks don't work in local development
     */
    public function syncPaymentMethod(Request $request)
    {
        $user = Auth::user();

        $subscription = Subscription::where('user_id', $user->id)
            ->where('status', 'active')
            ->first();

        if (!$subscription || !$subscription->stripe_customer_id) {
            return response()->json([
                'success' => false,
                'message' => 'No active subscription found',
            ], 404);
        }

        try {
            Log::info('Syncing payment method from Stripe', [
                'customer_id' => $subscription->stripe_customer_id,
                'subscription_id' => $subscription->stripe_subscription_id
            ]);

            // Get the latest payment methods for this customer
            $paymentMethods = \Stripe\PaymentMethod::all([
                'customer' => $subscription->stripe_customer_id,
                'type' => 'card',
                'limit' => 10,
            ]);

            if (empty($paymentMethods->data)) {
                return response()->json([
                    'success' => false,
                    'message' => 'No payment methods found',
                ], 404);
            }

            // Get the most recently created payment method
            $latestPaymentMethod = $paymentMethods->data[0];

            Log::info('Found latest payment method', [
                'payment_method_id' => $latestPaymentMethod->id,
                'brand' => $latestPaymentMethod->card->brand,
                'last4' => $latestPaymentMethod->card->last4
            ]);

            // Update customer's default payment method
            \Stripe\Customer::update($subscription->stripe_customer_id, [
                'invoice_settings' => [
                    'default_payment_method' => $latestPaymentMethod->id,
                ],
            ]);

            Log::info('Updated customer default payment method');

            // Update subscription's default payment method
            if ($subscription->stripe_subscription_id) {
                \Stripe\Subscription::update($subscription->stripe_subscription_id, [
                    'default_payment_method' => $latestPaymentMethod->id,
                ]);

                Log::info('Updated subscription default payment method');
            }

            return response()->json([
                'success' => true,
                'message' => 'Payment method synced successfully',
                'payment_method' => [
                    'brand' => $latestPaymentMethod->card->brand,
                    'last4' => $latestPaymentMethod->card->last4,
                    'exp_month' => $latestPaymentMethod->card->exp_month,
                    'exp_year' => $latestPaymentMethod->card->exp_year,
                ]
            ]);

        } catch (\Exception $e) {
            Log::error('Sync payment method error: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString()
            ]);
            
            return response()->json([
                'success' => false,
                'message' => 'Failed to sync payment method: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Handle successful payment callback
     */
    public function handleSuccess(Request $request)
    {
        $sessionId = $request->query('session_id');
        
        if (!$sessionId) {
            return redirect('/client?payment=error');
        }

        try {
            // Find subscription by session ID
            $subscription = Subscription::where('stripe_session_id', $sessionId)->first();
            
            if ($subscription) {
                $subscription->update([
                    'status' => 'active',
                    'activated_at' => now(),
                ]);
            }

            return redirect('/client?payment=success');
        } catch (\Exception $e) {
            Log::error('Payment success handler error: ' . $e->getMessage());
            return redirect('/client?payment=error');
        }
    }
}
