<?php

namespace App\Http\Controllers;

use App\Models\Payment;
use App\Models\PaymentCard;
use App\Models\PaymentMethod;
use App\Services\BillingService;
use App\Services\StripeService;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Stripe\StripeClient;

class TrialPaymentController extends Controller
{
    public function show(Request $request)
    {
        $user = auth()->user();
        $subscription = $user->subscription;

        if (!$subscription || !$subscription->isTrialExpired()) {
            return redirect()->route('dashboard');
        }

        $billingService = new BillingService();
        $amount = $billingService->calculateBillingAmount($subscription->package, $subscription->last_driver_count);

        return view('trial-payment.complete', compact('subscription', 'amount'));
    }

    public function createPaymentIntent(Request $request)
    {
        $validated = $request->validate([
            'save_option' => 'required|in:save_auto_renew,no_save',
        ]);

        $user = auth()->user();
        $subscription = $user->subscription;

        if (!$subscription || !$subscription->isTrialExpired()) {
            return response()->json(['error' => 'Invalid subscription state'], 422);
        }

        $billingService = new BillingService();
        $amount = $billingService->calculateBillingAmount($subscription->package, $subscription->last_driver_count);
        $amountInCents = (int) round($amount * 100);

        if ($amountInCents <= 0) {
            return response()->json(['error' => 'Invalid payment amount'], 422);
        }

        try {
            $stripeService = new StripeService();
            
            // Ensure customer exists in Stripe
            if (empty($subscription->stripe_customer_id)) {
                $customerId = $stripeService->createCustomer($subscription);
                $subscription->update(['stripe_customer_id' => $customerId]);
            } else {
                $customerId = $subscription->stripe_customer_id;
            }

            $stripe = new StripeClient(config('services.stripe.secret'));

            // Create payment intent for trial completion
            $paymentIntentParams = [
                'amount' => $amountInCents,
                'currency' => 'usd',
                'payment_method_types' => ['card'],
                'receipt_email' => $user->email,
                'customer' => $customerId,
                'metadata' => [
                    'user_id' => $user->id,
                    'subscription_id' => $subscription->id,
                    'save_option' => $validated['save_option'],
                    'description' => 'TrueTrucker trial completion payment',
                ],
            ];

            if ($validated['save_option'] === 'save_auto_renew') {
                $paymentIntentParams['setup_future_usage'] = 'off_session';
            }

            $paymentIntent = $stripe->paymentIntents->create($paymentIntentParams);

            return response()->json([
                'client_secret' => $paymentIntent->client_secret,
                'amount' => $amount,
                'type' => 'payment',
            ]);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Failed to create payment intent: ' . $e->getMessage()], 422);
        }
    }

    public function complete(Request $request)
    {
        $saveOption = $request->input('payment.save_option', 'save_auto_renew');
        
        $rules = [
            'payment.save_option' => 'required|in:save_auto_renew,no_save',
        ];

        // Require a Stripe payment intent for both flows, because we always collect a payment now.
        $rules['payment.stripe_payment_intent_id'] = 'required|string';
        $rules['payment.cardholder_name'] = 'required|string|max:255';

        $validated = $request->validate($rules);

        $user = auth()->user();
        $subscription = $user->subscription;

        if (!$subscription || !$subscription->isTrialExpired()) {
            return back()->withErrors(['trial' => 'Trial has not expired yet.']);
        }

        try {
            $paymentData = Arr::get($validated, 'payment', $validated);
            $stripePaymentIntentId = Arr::get($paymentData, 'stripe_payment_intent_id');
            $cardholderName = Arr::get($paymentData, 'cardholder_name') ?: 'Card Holder';
            $saveOption = Arr::get($paymentData, 'save_option');

            $stripe = new StripeClient(config('services.stripe.secret'));
            $paymentIntent = $stripe->paymentIntents->retrieve($stripePaymentIntentId);

            if (($paymentIntent->status ?? '') !== 'succeeded') {
                throw new \Exception('Stripe payment was not completed');
            }

            // Get charge details
            $charge = null;
            if (!empty($paymentIntent->charges->data) && is_array($paymentIntent->charges->data)) {
                $charge = $paymentIntent->charges->data[0];
            }
            if (!$charge && !empty($paymentIntent->latest_charge)) {
                try {
                    $charge = $stripe->charges->retrieve($paymentIntent->latest_charge);
                } catch (\Exception $e) {
                    $charge = null;
                }
            }

            $billingService = new BillingService();
            $amount = $billingService->calculateBillingAmount($subscription->package, $subscription->last_driver_count);

            // Create payment record for trial completion
            $paymentMethodGateway = PaymentMethod::firstOrCreate([
                'provider' => 'stripe',
            ], [
                'name' => 'Stripe',
                'credentials' => [],
                'is_active' => true,
                'description' => 'Stripe payment gateway',
            ]);

            $payment = Payment::create([
                'subscription_id' => $subscription->id,
                'payment_method_id' => $paymentMethodGateway->id,
                'amount' => $amount,
                'status' => 'completed',
                'transaction_id' => $paymentIntent->id,
                'metadata' => [
                    'stripe_customer_id' => $paymentIntent->customer,
                    'stripe_payment_intent_id' => $stripePaymentIntentId,
                    'stripe_charge_id' => $charge?->id ?? $paymentIntent->latest_charge ?? null,
                    'save_option' => $saveOption,
                    'type' => 'trial_completion',
                ],
            ]);

            if ($saveOption === 'save_auto_renew') {
                // Save card details only when the user chooses auto-renew.
                $cardBrand = $charge?->payment_method_details->card->brand ?? null;
                $cardLast4 = $charge?->payment_method_details->card->last4 ?? null;
                $cardExpMonth = $charge?->payment_method_details->card->exp_month ?? null;
                $cardExpYear = $charge?->payment_method_details->card->exp_year ?? null;

                PaymentCard::create([
                    'payment_id' => $payment->id,
                    'card_brand' => $cardBrand,
                    'card_last4' => $cardLast4,
                    'card_exp_month' => $cardExpMonth,
                    'card_exp_year' => $cardExpYear,
                    'cardholder_name' => $cardholderName,
                ]);
            }

            // Calculate the next billing date for the plan
            $nextBillingDate = now()->add($subscription->billing_cycle === 'weekly' ? \DateInterval::createFromDateString('1 week') : \DateInterval::createFromDateString('1 month'));

            // Update subscription to mark trial as completed and schedule next billing
            $subscription->update([
                'payment_status' => 'completed',
                'amount_paid' => $amount,
                'next_billing_date' => $nextBillingDate,
                'trial_ends_at' => now(),
                'trial_days' => 0,
            ]);

            return redirect()->route('dashboard')->with('success', 'Payment completed successfully! Your trial has ended and subscription is now active.');
        } catch (\Exception $e) {
            return back()->withErrors(['payment' => 'Payment processing failed: ' . $e->getMessage()]);
        }
    }
}
