<?php

namespace App\Http\Controllers\Auth;

use App\Models\Package;
use App\Models\Payment;
use App\Models\PaymentCard;
use App\Models\PaymentMethod;
use App\Models\Subscription;
use App\Services\OnboardingService;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Redirect;
use Stripe\StripeClient;

class OnboardController extends Controller
{
    public function show(Request $request)
    {
        $step = (int)($request->session()->get('onboard_step', 1));
        $company = $request->session()->get('onboard_company', []);
        $fleet = $request->session()->get('onboard_fleet', []);
        $drivers = $request->session()->get('onboard_drivers', []);
        $loads = $request->session()->get('onboard_loads', []);
        $plan = $request->session()->get('onboard_plan', null);
        $numTrucks = $request->session()->get('onboard_num_trucks', 1);
        $plans = [
            [
                'id' => 'starter',
                'name' => 'Starter Plan',
                'price' => 15,
                'desc' => 'Perfect for owner-operators or small fleet managers getting started.<br>Manage 1 truck<br>Full access to AI-powered bookkeeping<br>Load tracking & financial insights<br>Expense & income management<br>Real-time reporting dashboard',
            ],
        ];
        $trial = $request->session()->get('onboard_trial', false);

        if ($step === 2) {
            return view('auth.subscription-step', compact('plans', 'plan', 'numTrucks', 'trial'));
        }
        return view('auth.onboard-stepper', compact('step', 'company', 'fleet', 'drivers', 'loads'));
    }

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

        $trial = $request->session()->get('onboard_trial', false);
        $onboardingService = new OnboardingService();
        $payload = [
            'company' => $request->session()->get('onboard_company', []),
            'plan' => $request->session()->get('onboard_plan', 'starter'),
            'num_trucks' => $request->session()->get('onboard_num_trucks', 1),
            'fleet' => $request->session()->get('onboard_fleet', []),
            'drivers' => $request->session()->get('onboard_drivers', []),
        ];

        $amount = $trial ? 0 : $onboardingService->calculateOnboardPrice($payload);
        $amountInCents = (int) round($amount * 100);

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

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

        if ($validated['save_option'] === 'save_auto_renew' || $trial) {
            $company = $payload['company'];
            $existing = $stripe->customers->search([
                'query' => 'email:"' . addslashes(auth()->user()->email) . '"',
                'limit' => 1,
            ]);
            if (!empty($existing->data) && isset($existing->data[0])) {
                $customerId = $existing->data[0]->id;
            } else {
                $customer = $stripe->customers->create([
                    'name' => $company['name'] ?? auth()->user()->name,
                    'email' => auth()->user()->email,
                    'phone' => $company['phone'] ?? null,
                    'metadata' => [
                        'company_name' => $company['name'] ?? null,
                        'user_id' => auth()->id(),
                    ],
                ]);
                $customerId = $customer->id;
            }
        }

        if ($trial) {
            $setupIntentParams = [
                'payment_method_types' => ['card'],
                'usage' => 'off_session',
                'metadata' => [
                    'user_id' => auth()->id(),
                    'save_option' => $validated['save_option'],
                    'trial' => 'true',
                    'description' => 'TrueTrucker onboarding trial setup',
                ],
            ];

            if ($customerId) {
                $setupIntentParams['customer'] = $customerId;
            }

            $setupIntent = $stripe->setupIntents->create($setupIntentParams);

            return response()->json([
                'client_secret' => $setupIntent->client_secret,
                'customer_id' => $customerId,
                'type' => 'setup',
            ]);
        }

        $paymentIntentParams = [
            'amount' => $amountInCents,
            'currency' => 'usd',
            'payment_method_types' => ['card'],
            'receipt_email' => auth()->user()->email,
            'metadata' => [
                'user_id' => auth()->id(),
                'save_option' => $validated['save_option'],
                'description' => 'TrueTrucker onboarding payment',
            ],
        ];

        if ($customerId) {
            $paymentIntentParams['customer'] = $customerId;
            $paymentIntentParams['setup_future_usage'] = 'off_session';
        }

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

        return response()->json([
            'client_secret' => $paymentIntent->client_secret,
            'customer_id' => $customerId,
            'type' => 'payment',
        ]);
    }

    public function submit(Request $request)
    {
        $step = (int)($request->session()->get('onboard_step', 1));
        $action = $request->input('onboard_action');

        // Save step data
        switch ($step) {
            case 1:
                $company = $request->input('company', []);
                $request->session()->put('onboard_company', $company);
                break;
            case 2:
                $plan = $request->input('plan', null);
                $numTrucks = $request->input('num_trucks', 1);
                $subscriptionType = $request->input('subscription_type', 'paid');
                $trial = $subscriptionType === 'trial';

                $request->session()->put('onboard_plan', $plan);
                $request->session()->put('onboard_num_trucks', $numTrucks);
                $request->session()->put('onboard_trial', $trial);
                break;
            case 3:
                $fleet = $request->input('fleet', []);
                $request->session()->put('onboard_fleet', $fleet);
                break;
            case 4:
                $drivers = $request->input('drivers', []);
                $request->session()->put('onboard_drivers', $drivers);
                break;
            case 5:
                $loads = $request->input('loads', []);
                $request->session()->put('onboard_loads', $loads);
                break;
        }

        if ($action === 'prev') {
            $step = max(1, $step - 1);
            $request->session()->put('onboard_step', $step);
            return Redirect::route('onboard.show');
        }

        if ($step < 5 && $action === 'next') {
            $step++;
            $request->session()->put('onboard_step', $step);
            return Redirect::route('onboard.show');
        }
        // Final step: save loads and submit
        if ($step === 5 && $action !== 'prev') {
            $trial = $request->session()->get('onboard_trial', false);
            $saveOption = $request->input('payment.save_option', 'save_auto_renew');

            $rules = [
                'payment.save_option' => 'required|in:save_auto_renew,no_save',
            ];

            // Only require payment intent details if saving the card
            if ($saveOption === 'save_auto_renew') {
                $rules['payment.stripe_payment_intent_id'] = 'nullable|string';
                $rules['payment.stripe_setup_intent_id'] = 'nullable|string';
                $rules['payment.cardholder_name'] = 'required|string|max:255';
                $rules['payment.stripe_customer_id'] = 'nullable|string';
            } else {
                // For "do not save card", skip all payment details and collect later
                $rules['payment.stripe_payment_intent_id'] = 'nullable|string';
                $rules['payment.stripe_setup_intent_id'] = 'nullable|string';
                $rules['payment.cardholder_name'] = 'nullable|string|max:255';
                $rules['payment.stripe_customer_id'] = 'nullable|string';
            }

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

            $paymentData = Arr::get($validatedPayment, 'payment', $validatedPayment);
            $stripePaymentIntentId = Arr::get($paymentData, 'stripe_payment_intent_id');
            $stripeSetupIntentId = Arr::get($paymentData, 'stripe_setup_intent_id');
            $cardholderName = Arr::get($paymentData, 'cardholder_name') ?: 'Card Holder';
            $saveOption = Arr::get($paymentData, 'save_option');
            $stripeCustomerId = Arr::get($paymentData, 'stripe_customer_id');

            // If not saving card, skip payment validation - user will enter details later
            if ($saveOption === 'no_save') {
                $stripePaymentIntentId = null;
                $stripeSetupIntentId = null;
            }

            if ($trial && $saveOption === 'save_auto_renew' && empty($stripeSetupIntentId)) {
                return back()->withErrors(['payment' => 'Trial setup requires a saved card. Please complete the setup form.']);
            }

            // Only require payment confirmation if saving card
            if (!$trial && $saveOption === 'save_auto_renew' && empty($stripePaymentIntentId)) {
                return back()->withErrors(['payment' => 'Payment confirmation is required to complete onboarding.']);
            }
            $payload = [
                'company'    => $request->session()->get('onboard_company', []),
                'plan'       => $request->session()->get('onboard_plan', 'starter'),
                'num_trucks' => $request->session()->get('onboard_num_trucks', 1),
                'fleet'      => $request->session()->get('onboard_fleet', []),
                'drivers'    => $request->session()->get('onboard_drivers', []),
                'loads'      => $request->session()->get('onboard_loads', []),
            ];
            try {
                $service = new OnboardingService();
                $result = $service->onboardForExistingUser(auth()->user(), $payload);

                $stripe = new StripeClient(config('services.stripe.secret'));
                $charge = null;
                $cardDetails = null;
                $transactionId = null;
                $amount = 0;

                // If not saving card, create subscription without payment
                if ($saveOption === 'no_save') {
                    $transactionId = 'no-payment-' . time();
                } elseif ($trial) {
                    $setupIntent = $stripe->setupIntents->retrieve($stripeSetupIntentId, ['expand' => ['payment_method.card']]);
                    $transactionId = $setupIntent->id;
                    $cardDetails = $setupIntent->payment_method?->card ?? null;
                } else {
                    $paymentIntent = $stripe->paymentIntents->retrieve($stripePaymentIntentId);

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

                    $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;
                        }
                    }

                    $transactionId = $paymentIntent->id;
                    $amount = $service->calculateOnboardPrice($payload);
                }

                $package = Package::firstOrCreate([
                    'name' => 'Starter',
                ], [
                    'description' => 'Starter plan for onboarding',
                    'driver_limit' => max(1, count(array_filter($payload['drivers'] ?? [], fn($d) => !empty($d['name'])))),
                    'truck_limit' => max(1, $payload['num_trucks'] ?? 1),
                    'price' => 15.00,
                    'base_price' => 15.00,
                    'price_per_driver' => 5.00,
                    'billing_cycle' => 'monthly',
                    'is_active' => true,
                    'features' => [
                        ['key' => 'Onboarding', 'value' => 'Starter onboarding plan'],
                    ],
                ]);

                $subscriptionData = [
                    'user_id' => auth()->id(),
                    'package_id' => $package->id,
                    'status' => 'active',
                    'started_at' => now(),
                    'billing_cycle' => 'monthly',
                    'last_driver_count' => max(1, count(array_filter($payload['drivers'] ?? [], fn($d) => !empty($d['name'])))),
                    'stripe_customer_id' => $stripeCustomerId,
                ];

                if ($trial) {
                    $subscriptionData = array_merge($subscriptionData, [
                        'payment_status' => 'pending',
                        'amount_paid' => 0,
                        'trial_days' => 7,
                        'trial_ends_at' => now()->addDays(7),
                        'next_billing_date' => now()->addDays(7),
                    ]);
                } elseif ($saveOption === 'no_save') {
                    // For "do not save card", mark as pending payment
                    $subscriptionData = array_merge($subscriptionData, [
                        'payment_status' => 'pending',
                        'amount_paid' => 0,
                        'next_billing_date' => null,
                    ]);
                } else {
                    $subscriptionData = array_merge($subscriptionData, [
                        'payment_status' => 'completed',
                        'amount_paid' => $amount,
                        'next_billing_date' => now()->addMonth(),
                    ]);
                }

                $subscription = Subscription::create($subscriptionData);

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

                $paymentStatus = $saveOption === 'no_save' ? 'pending' : ($trial ? 'completed' : 'completed');
                
                $paymentMetadata = [
                    'stripe_customer_id' => $stripeCustomerId,
                    'save_option' => $saveOption,
                ];

                if ($trial && !($saveOption === 'no_save')) {
                    $paymentMetadata['stripe_setup_intent_id'] = $stripeSetupIntentId;
                } elseif (!$trial && !($saveOption === 'no_save')) {
                    $paymentMetadata['stripe_payment_intent_id'] = $stripePaymentIntentId;
                    if (isset($charge) && $charge) {
                        $paymentMetadata['stripe_charge_id'] = $charge->id;
                    }
                }

                $payment = Payment::create([
                    'subscription_id' => $subscription->id,
                    'payment_method_id' => $paymentMethodGateway->id,
                    'amount' => $amount,
                    'status' => $paymentStatus,
                    'transaction_id' => $transactionId,
                    'metadata' => $paymentMetadata,
                ]);

                // Create payment card details only if card info exists
                if ($saveOption !== 'no_save' || $cardDetails || $charge) {
                    $cardBrand = $cardDetails?->brand ?? $charge?->payment_method_details->card->brand ?? null;
                    $cardLast4 = $cardDetails?->last4 ?? $charge?->payment_method_details->card->last4 ?? null;
                    $cardExpMonth = $cardDetails?->exp_month ?? $charge?->payment_method_details->card->exp_month ?? null;
                    $cardExpYear = $cardDetails?->exp_year ?? $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,
                    ]);
                }

                $request->session()->forget([
                    'onboard_step', 'onboard_company', 'onboard_plan',
                    'onboard_num_trucks', 'onboard_fleet', 'onboard_drivers', 'onboard_loads',
                ]);

                $successMessage = $saveOption === 'no_save' 
                    ? 'Welcome to TrueTrucker! Your company has been set up. Your 7-day trial starts now.'
                    : 'Welcome to TrueTrucker! Your company and payment have been set up.';

                return redirect()->route('dashboard')->with('success', $successMessage);
            } catch (\Exception $e) {
                return back()->withErrors(['onboard' => 'Onboarding failed: ' . $e->getMessage()]);
            }
        }
        return Redirect::route('onboard.show');
    }
}
