<?php

namespace App\Http\Controllers;

use App\Models\BookedSlot;
use App\Models\BookingSlot;
use App\Models\BookingFor;
use App\Models\OldBookedSlot;
use App\Models\Transaction;
use App\Models\SpecialBookingSlot;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;


class BookingController extends Controller
{
    protected $paymentService;

    public function __construct(\App\Services\PaymentService $paymentService)
    {
        $this->paymentService = $paymentService;
    }

    public function checkout(Request $request)
    {
        $validated = $request->validate([
            'booking_for_id' => 'required',
            'date' => 'required|date',
            'hours' => 'required|string',
        ]);

        $bookingForId = $validated['booking_for_id'];
        $date = $validated['date'];
        $hoursStr = $validated['hours'];

        if (empty($hoursStr)) {
            return back()->with('error', 'Please select at least one time slot.');
        }

        $timeSlots = explode(',', $hoursStr);
        $day = ucfirst(Carbon::parse($date)->format('D'));
        $service = BookingFor::find($bookingForId)->service ?? 'Unknown Service';

        // Backend validation: Ensure time slots are consecutive
        if (count($timeSlots) > 1) {
            // Get all available slots for this day to determine order
            $allAvailableSlots = BookingSlot::where('booking_for_id', $bookingForId)
                ->where('day', $day)
                ->orderBy('time')
                ->pluck('time')
                ->map(function ($time) {
                    return substr($time, 0, 5); // Normalize to H:i format
                })
                ->toArray();

            // Get booked slots to exclude them
            $bookedSlots = BookedSlot::where('booking_for_id', $bookingForId)
                ->whereDate('date', $date)
                ->where('status', '1')
                ->pluck('time')
                ->map(function ($time) {
                    return substr($time, 0, 5);
                })
                ->toArray();

            // Available slots (not booked)
            $availableSlots = array_values(array_diff($allAvailableSlots, $bookedSlots));

            // Normalize selected slots
            $normalizedSelected = array_map(function ($slot) {
                return substr(trim($slot), 0, 5);
            }, $timeSlots);

            // Get indices of selected slots in available slots
            $selectedIndices = [];
            foreach ($normalizedSelected as $slot) {
                $index = array_search($slot, $availableSlots);
                if ($index !== false) {
                    $selectedIndices[] = $index;
                }
            }

            // Sort indices and check if consecutive
            sort($selectedIndices);
            for ($i = 1; $i < count($selectedIndices); $i++) {
                if ($selectedIndices[$i] - $selectedIndices[$i - 1] !== 1) {
                    return back()->with('error', 'Invalid selection: You can only book consecutive time slots. Please select adjacent slots without gaps.');
                }
            }
        }

        // Fetch prices from DB (Regular Slots)
        $slotsData = BookingSlot::where('booking_for_id', $bookingForId)
            ->where('day', $day)
            ->whereIn('time', $timeSlots)
            ->get();

        $totalPrice = 0;
        $slotPrices = []; // Array to store individual slot prices

        foreach ($timeSlots as $slotTime) {
            // 1. Check Special Price
            $specialPrice = SpecialBookingSlot::where('booking_for_id', $bookingForId)
                ->where('date', $date)
                ->where('time', $slotTime)
                ->value('price');

            if ($specialPrice !== null) {
                $totalPrice += $specialPrice;
                $slotPrices[$slotTime] = $specialPrice;
                continue;
            }

            // 2. Fallback to Regular Price
            $slot = $slotsData->first(function ($s) use ($slotTime) {
                // Determine equality - careful with H:i:s vs H:i
                return $s->time == $slotTime || substr($s->time, 0, 5) == substr($slotTime, 0, 5);
            });
            $price = $slot ? $slot->price : 0;
            $totalPrice += $price;
            $slotPrices[$slotTime] = $price;
        }

        // Calculate average price per hour for display (or use specific logic)
        $pricePerHour = count($timeSlots) > 0 ? $totalPrice / count($timeSlots) : 0;

        // Create Razorpay Order
        $paymentEnabled = config('services.razorpay.enabled', true);
        $orderId = null;

        if ($paymentEnabled) {
            try {
                $orderId = $this->paymentService->createOrder($totalPrice);
            } catch (\Exception $e) {
                return back()->with('error', 'Error initializing payment: ' . $e->getMessage());
            }
        } else {
            $orderId = 'bypass_order_' . \Illuminate\Support\Str::random(10);
        }

        return view('user.checkout', compact('bookingForId', 'date', 'timeSlots', 'service', 'pricePerHour', 'totalPrice', 'orderId', 'paymentEnabled', 'slotPrices'));
    }

    public function confirmBooking(Request $request)
    {
        $validated = $request->validate([
            'razorpay_payment_id' => 'required',
            'razorpay_order_id' => 'required',
            'razorpay_signature' => 'required',
            'booking_for_id' => 'required',
            'date' => 'required',
            'timeSlots' => 'required|array',
            'amount' => 'required'
        ]);

        $paymentEnabled = config('services.razorpay.enabled', true);

        // Verify Signature (Only if enabled)
        if ($paymentEnabled) {
            $attributes = [
                'razorpay_order_id' => $validated['razorpay_order_id'],
                'razorpay_payment_id' => $validated['razorpay_payment_id'],
                'razorpay_signature' => $validated['razorpay_signature']
            ];

            if (!$this->paymentService->verifySignature($attributes)) {
                return redirect()->route('home')->with('error', 'Payment verification failed!');
            }
        }

        // Create Bookings
        $day = ucfirst(Carbon::parse($validated['date'])->format('D'));
        $totalAmount = $validated['amount'];

        // Backend validation: Ensure time slots are consecutive (double-check)
        $timeSlots = $validated['timeSlots'];
        if (count($timeSlots) > 1) {
            $allAvailableSlots = BookingSlot::where('booking_for_id', $validated['booking_for_id'])
                ->where('day', $day)
                ->orderBy('time')
                ->pluck('time')
                ->map(fn($time) => substr($time, 0, 5))
                ->toArray();

            $bookedSlots = BookedSlot::where('booking_for_id', $validated['booking_for_id'])
                ->whereDate('date', $validated['date'])
                ->where('status', '1')
                ->pluck('time')
                ->map(fn($time) => substr($time, 0, 5))
                ->toArray();

            $availableSlots = array_values(array_diff($allAvailableSlots, $bookedSlots));

            $normalizedSelected = array_map(fn($slot) => substr(trim($slot), 0, 5), $timeSlots);

            $selectedIndices = [];
            foreach ($normalizedSelected as $slot) {
                $index = array_search($slot, $availableSlots);
                if ($index !== false) {
                    $selectedIndices[] = $index;
                }
            }

            sort($selectedIndices);
            for ($i = 1; $i < count($selectedIndices); $i++) {
                if ($selectedIndices[$i] - $selectedIndices[$i - 1] !== 1) {
                    return redirect()->route('home')->with('error', 'Invalid booking: Non-consecutive time slots detected. Booking rejected.');
                }
            }
        }

        try {
            // Generate unique group_id for this booking
            $groupId = \Illuminate\Support\Str::uuid()->toString();

            // Create Transaction Record FIRST to get ID
            $transaction = Transaction::create([
                'user_id' => auth()->id(),
                'amount' => $totalAmount,
                'currency' => 'INR',
                'transaction_type' => 'payment',
                'status' => 'success',
                'razorpay_payment_id' => $validated['razorpay_payment_id'],
                'razorpay_order_id' => $validated['razorpay_order_id'],
                'description' => 'Booking Payment'
            ]);

            foreach ($validated['timeSlots'] as $hour) {
                $hour = trim($hour);

                // 1. Check Special Price
                $slotPrice = SpecialBookingSlot::where('booking_for_id', $validated['booking_for_id'])
                    ->where('date', $validated['date'])
                    ->where('time', $hour)
                    ->value('price');

                // 2. Fallback to Regular Price
                if ($slotPrice === null) {
                    $slotPrice = BookingSlot::where('booking_for_id', $validated['booking_for_id'])
                        ->where('day', $day)
                        ->where('time', $hour)
                        ->value('price') ?? ($totalAmount / count($validated['timeSlots']));
                }

                BookedSlot::create([
                    'group_id' => $groupId,
                    'booking_for_id' => $validated['booking_for_id'],
                    'user_id' => auth()->id(),
                    'date' => $validated['date'],
                    'time' => $hour,
                    'amount' => $slotPrice,
                    'status' => '1', // Confirmed
                    'payment_status' => '1', // Paid
                    'transaction_id' => $transaction->id
                ]);
            }

            return redirect()->route('my-booking.show')->with('success', 'Booking Confirmed! Payment Successful.');

        } catch (\Exception $e) {
            return redirect()->route('home')->with('error', 'Booking failed after payment. Please contact support. ' . $e->getMessage());
        }
    }

    public function getSlots(Request $request)
    {
        $date = $request->input('date');
        $service = $request->input('service'); // 'turf' or 'pool'
        $day = ucfirst(Carbon::parse($date)->format('D'));

        // If your DB differentiates between turf/pool using booking_for_id
        $bookingForId = $service === 'turf' ? 1 : 2;

        $allSlots = DB::table('booking_slots')
            ->where('day', $day)
            ->where('booking_for_id', $bookingForId)
            ->pluck('time')
            ->toArray();

        $bookedSlots = DB::table('booked_slots')
            ->where('booking_for_id', $bookingForId)
            ->whereDate('date', $date)
            ->where('status', '1')
            ->pluck('time')
            ->toArray();
        $bookedSlotsFormatted = array_map(function ($slot) {
            return substr($slot, 0, 5); // remove seconds
        }, $bookedSlots);


        $availableSlots = array_values(array_diff($allSlots, $bookedSlotsFormatted));

        return response()->json([
            'all_hours' => $allSlots,
            'booked_hours' => $bookedSlots,
            'hours' => $availableSlots, // still send this for compatibility
        ]);
    }


    public function bookedList(Request $request)
    {
        $bookList = BookedSlot::with('user', 'bookingFor')->latest()->get();

        return view('admin.booked_list')->with('bookList', $bookList);
    }

    public function bookingCancel($id)
    {
        try {
            $booking = BookedSlot::findOrFail($id);

            if (auth()->id() !== $booking->user_id) {
                return response()->json(['message' => 'Unauthorized action.'], 403);
            }

            // Cannot cancel past bookings
            if (Carbon::parse($booking->date)->lt(Carbon::today())) {
                return response()->json(['message' => 'Cannot cancel past bookings.'], 400);
            }

            $booking->status = '3'; // Cancelled
            $booking->save();

            return response()->json(['success' => true, 'message' => 'Your booking has been successfully cancelled.']);

        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'Unable to cancel booking. Please try again later.'], 500);
        }
    }

    public function reschedule($id)
    {
        $booking = BookedSlot::with('bookingFor')->findOrFail($id);

        // Authorization and Validation
        if (auth()->id() !== $booking->user_id) {
            return redirect()->route('home')->with('error', 'Unauthorized access.');
        }
        if ($booking->status == '3') {
            return redirect()->route('my-booking.show')->with('error', 'Cannot reschedule a cancelled booking.');
        }
        if (Carbon::parse($booking->date)->lt(Carbon::today())) {
            return redirect()->route('my-booking.show')->with('error', 'Cannot reschedule past bookings.');
        }

        // Reuse the logic from HomeController::index but pass the booking to edit
        // We will inject this into the view to trigger "Reschedule Mode"
        return view('user.home', [
            'rescheduleBooking' => $booking
        ]);
    }

    public function processReschedule(Request $request, $id)
    {
        $booking = BookedSlot::findOrFail($id);

        if (auth()->id() !== $booking->user_id) {
            return redirect()->route('home')->with('error', 'Unauthorized access.');
        }

        $validated = $request->validate([
            'date' => 'required|date',
            'hours' => 'required|string',
        ]);

        $newDate = $validated['date'];
        $newTime = trim(explode(',', $validated['hours'])[0]);
        $day = ucfirst(Carbon::parse($newDate)->format('D'));

        try {
            // 1. Check Availability
            $exists = BookedSlot::where('booking_for_id', $booking->booking_for_id)
                ->where('date', $newDate)
                ->where('time', $newTime)
                ->where('status', '1')
                ->exists();

            if ($exists) {
                return back()->with('error', 'The selected slot is already booked. Please choose another.');
            }

            // 2. Get New Price
            $specialPrice = SpecialBookingSlot::where('booking_for_id', $booking->booking_for_id)
                ->where('date', $newDate)
                ->where('time', $newTime)
                ->value('price');

            if ($specialPrice !== null) {
                $newPrice = $specialPrice;
            } else {
                $newPrice = BookingSlot::where('booking_for_id', $booking->booking_for_id)
                    ->where('day', $day)
                    ->where('time', $newTime)
                    ->value('price');
            }

            $newAmount = $newPrice ?? $booking->amount; // Fallback to current amount? Or error? Let's assume price exists.

            $oldAmount = $booking->amount;
            $diff = $newAmount - $oldAmount;

            if ($diff > 0) {
                // Must Pay Difference
                $paymentEnabled = config('services.razorpay.enabled', true);
                $orderId = null;

                if ($paymentEnabled) {
                    $orderId = $this->paymentService->createOrder($diff);
                } else {
                    $orderId = 'bypass_order_reschedule_' . \Illuminate\Support\Str::random(10);
                }

                return view('user.reschedule_payment', [
                    'bookingId' => $booking->id,
                    'newDate' => $newDate,
                    'newTime' => $newTime,
                    'oldAmount' => $oldAmount,
                    'newAmount' => $newAmount,
                    'diffAmount' => $diff,
                    'orderId' => $orderId,
                    'paymentEnabled' => $paymentEnabled
                ]);

            } elseif ($diff < 0) {
                // Refund Difference
                $refundAmount = abs($diff);

                // Attempt to find original transaction
                // We assume booked_slots has transaction_id now
                $transactionId = $booking->transaction_id;

                if ($transactionId) {
                    $originalTxn = Transaction::find($transactionId);
                    if ($originalTxn && $originalTxn->razorpay_payment_id) {
                        $this->paymentService->refund($originalTxn->razorpay_payment_id, $refundAmount);

                        // Record Refund Transaction
                        Transaction::create([
                            'user_id' => auth()->id(),
                            'booking_id' => $booking->id,
                            'amount' => $refundAmount,
                            'transaction_type' => 'reschedule_refund',
                            'status' => 'success',
                            'description' => 'Refund for Rescheduling Booking #' . $booking->id
                        ]);
                    } else {
                        // Log error or notify admin manually? For demo, we just proceed.
                        // Or fail? "Cannot process automatic refund".
                        return back()->with('error', 'Original transaction not found for refund. Please contact support.');
                    }
                } else {
                    // Legacy booking without transaction ID
                    // Maybe just update and show message
                }

                $booking->date = $newDate;
                $booking->time = $newTime;
                $booking->amount = $newAmount;
                $booking->save();

                return redirect()->route('my-booking.show')->with('success', 'Booking rescheduled! Refund of ₹' . $refundAmount . ' initiated.');

            } else {
                // No Price Change
                $booking->date = $newDate;
                $booking->time = $newTime;
                $booking->save();

                return redirect()->route('my-booking.show')->with('success', 'Booking successfully rescheduled!');
            }

        } catch (\Exception $e) {
            return back()->with('error', 'Reschedule failed: ' . $e->getMessage());
        }
    }

    public function confirmReschedule(Request $request)
    {
        $validated = $request->validate([
            'razorpay_payment_id' => 'required',
            'razorpay_order_id' => 'required',
            'razorpay_signature' => 'required',
            'new_date' => 'required',
            'amount_paid' => 'required',
            // Group reschedule fields
            'group_id' => 'required_if:is_group_reschedule,1',
            'new_time_slots' => 'required_if:is_group_reschedule,1',
            'is_group_reschedule' => 'nullable',
            // Single booking fields (backward compatibility)
            'booking_id' => 'required_without:group_id',
            'new_time' => 'required_without:new_time_slots'
        ]);

        $attributes = [
            'razorpay_order_id' => $validated['razorpay_order_id'],
            'razorpay_payment_id' => $validated['razorpay_payment_id'],
            'razorpay_signature' => $validated['razorpay_signature']
        ];

        if (config('services.razorpay.enabled', true)) {
            if (!$this->paymentService->verifySignature($attributes)) {
                return redirect()->route('my-booking.show')->with('error', 'Payment verification failed!');
            }
        }

        try {
            // Check if this is a group reschedule
            $isGroupReschedule = $request->input('is_group_reschedule') === '1';

            if ($isGroupReschedule) {
                // Group Reschedule Flow
                $groupId = $validated['group_id'];
                $newTimeSlots = array_map('trim', explode(',', $validated['new_time_slots']));
                $newDate = $validated['new_date'];
                $day = ucfirst(Carbon::parse($newDate)->format('D'));
                $amountPaid = $validated['amount_paid'];

                DB::transaction(function () use ($groupId, $newDate, $newTimeSlots, $day, $amountPaid, $validated) {
                    $now = now();

                    // Get old bookings
                    $oldBookings = BookedSlot::where('group_id', $groupId)
                        ->where('user_id', auth()->id())
                        ->get();

                    $firstOldBooking = $oldBookings->first();
                    $transactionId = $firstOldBooking->transaction_id ?? null;

                    // Step 1: Move old slots to old_booked_slots table with Rescheduled status
                    foreach ($oldBookings as $oldBooking) {
                        OldBookedSlot::create([
                            'group_id' => $oldBooking->group_id,
                            'booking_for_id' => $oldBooking->booking_for_id,
                            'user_id' => $oldBooking->user_id,
                            'date' => $oldBooking->date,
                            'time' => $oldBooking->time,
                            'amount' => $oldBooking->amount,
                            'status' => '2', // Rescheduled
                            'payment_status' => $oldBooking->payment_status,
                            'transaction_id' => $oldBooking->transaction_id,
                            'rescheduled_at' => $now,
                            'created_at' => $oldBooking->created_at,
                            'updated_at' => $oldBooking->updated_at
                        ]);
                    }

                    // Step 2: Delete old slots from booked_slots
                    BookedSlot::where('group_id', $groupId)
                        ->where('user_id', auth()->id())
                        ->delete();

                    // Step 3: Create new bookings with same group_id
                    foreach ($newTimeSlots as $slotTime) {
                        $slotPrice = SpecialBookingSlot::where('booking_for_id', $firstOldBooking->booking_for_id)
                            ->where('date', $newDate)
                            ->where('time', $slotTime)
                            ->value('price');

                        if ($slotPrice === null) {
                            $slotPrice = BookingSlot::where('booking_for_id', $firstOldBooking->booking_for_id)
                                ->where('day', $day)
                                ->where('time', $slotTime)
                                ->value('price') ?? 0;
                        }

                        BookedSlot::create([
                            'group_id' => $groupId,
                            'booking_for_id' => $firstOldBooking->booking_for_id,
                            'user_id' => auth()->id(),
                            'date' => $newDate,
                            'time' => $slotTime,
                            'amount' => $slotPrice,
                            'status' => '1',
                            'payment_status' => '1',
                            'transaction_id' => $transactionId
                        ]);
                    }

                    // Step 4: Record the additional payment transaction
                    Transaction::create([
                        'user_id' => auth()->id(),
                        'amount' => $amountPaid,
                        'currency' => 'INR',
                        'transaction_type' => 'reschedule_payment',
                        'status' => 'success',
                        'razorpay_payment_id' => $validated['razorpay_payment_id'],
                        'razorpay_order_id' => $validated['razorpay_order_id'],
                        'description' => 'Additional Charge for Group Reschedule - Group ID: ' . $groupId
                    ]);
                });

                session()->forget('reschedule_group');
                return redirect()->route('my-booking.show')->with('success', 'Reschedule Confirmed!');
            } else {
                // Single Booking Reschedule (backward compatibility)
                $booking = BookedSlot::findOrFail($validated['booking_id']);
                $booking->date = $validated['new_date'];
                $booking->time = $validated['new_time'];
                $booking->amount = $booking->amount + $validated['amount_paid'];
                $booking->save();

                Transaction::create([
                    'user_id' => auth()->id(),
                    'booking_id' => $booking->id,
                    'amount' => $validated['amount_paid'],
                    'currency' => 'INR',
                    'transaction_type' => 'reschedule_payment',
                    'status' => 'success',
                    'razorpay_payment_id' => $validated['razorpay_payment_id'],
                    'razorpay_order_id' => $validated['razorpay_order_id'],
                    'description' => 'Additional Charge for Rescheduling Booking #' . $booking->id
                ]);

                return redirect()->route('my-booking.show')->with('success', 'Reschedule Confirmed!');
            }

        } catch (\Exception $e) {
            return redirect()->route('my-booking.show')->with('error', 'Error updating booking: ' . $e->getMessage());
        }
    }

    /**
     * Cancel all bookings in a group
     */
    public function cancelBookingGroup($groupId)
    {
        try {
            // Find all bookings in this group belonging to current user
            $bookings = BookedSlot::where('group_id', $groupId)
                ->where('user_id', auth()->id())
                ->get();

            if ($bookings->isEmpty()) {
                return response()->json(['message' => 'Booking not found.'], 404);
            }

            // Check if any booking is in the past
            foreach ($bookings as $booking) {
                if (Carbon::parse($booking->date)->lt(Carbon::today())) {
                    return response()->json(['message' => 'Cannot cancel past bookings.'], 400);
                }
                if ($booking->status == '3') {
                    return response()->json(['message' => 'Booking is already cancelled.'], 400);
                }
            }

            // Use transaction to ensure all slots are cancelled together
            DB::transaction(function () use ($bookings) {
                foreach ($bookings as $booking) {
                    $booking->status = '3'; // Cancelled
                    $booking->save();
                }
            });

            return response()->json([
                'success' => true,
                'message' => 'All ' . $bookings->count() . ' slot(s) in your booking have been successfully cancelled.'
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Unable to cancel booking. Please try again later.'
            ], 500);
        }
    }

    /**
     * Show reschedule form for a group booking
     */
    public function rescheduleGroup($groupId)
    {
        // Find all bookings in this group belonging to current user
        $bookings = BookedSlot::where('group_id', $groupId)
            ->where('user_id', auth()->id())
            ->with('bookingFor')
            ->orderBy('time')
            ->get();

        if ($bookings->isEmpty()) {
            return redirect()->route('my-booking.show')->with('error', 'Booking not found.');
        }

        $firstBooking = $bookings->first();

        // Validation
        if ($firstBooking->status == '3') {
            return redirect()->route('my-booking.show')->with('error', 'Cannot reschedule a cancelled booking.');
        }
        if (Carbon::parse($firstBooking->date)->lt(Carbon::today())) {
            return redirect()->route('my-booking.show')->with('error', 'Cannot reschedule past bookings.');
        }

        // Create a booking object with group info
        $rescheduleBooking = (object) [
            'group_id' => $groupId,
            'id' => $firstBooking->id,
            'booking_for_id' => $firstBooking->booking_for_id,
            'bookingFor' => $firstBooking->bookingFor,
            'date' => $firstBooking->date,
            'time_slots' => $bookings->pluck('time')->toArray(),
            'slot_count' => $bookings->count(),
            'total_amount' => $bookings->sum('amount'),
            'status' => $firstBooking->status,
            'user_id' => $firstBooking->user_id
        ];

        return view('user.home', [
            'rescheduleBooking' => $rescheduleBooking,
            'isGroupReschedule' => true
        ]);
    }

    /**
     * Process reschedule for a group booking
     */
    public function processRescheduleGroup(Request $request, $groupId)
    {
        $validated = $request->validate([
            'date' => 'required|date|after_or_equal:today',
            'hours' => 'required|string',
        ]);

        // Find all bookings in this group
        $oldBookings = BookedSlot::where('group_id', $groupId)
            ->where('user_id', auth()->id())
            ->with('bookingFor')
            ->get();

        if ($oldBookings->isEmpty()) {
            return redirect()->route('my-booking.show')->with('error', 'Booking not found.');
        }

        $firstOldBooking = $oldBookings->first();
        $newTimeSlots = array_map('trim', explode(',', $validated['hours']));

        $newDate = $validated['date'];
        $day = ucfirst(Carbon::parse($newDate)->format('D'));

        // Validate consecutive slots
        if (count($newTimeSlots) > 1) {
            // Get all slots for the day (ordered by time)
            $allSlots = BookingSlot::where('booking_for_id', $firstOldBooking->booking_for_id)
                ->where('day', $day)
                ->orderBy('time')
                ->pluck('time')
                ->map(fn($time) => substr($time, 0, 5))
                ->toArray();

            $normalizedSelected = array_map(fn($slot) => substr(trim($slot), 0, 5), $newTimeSlots);

            // Find indices of selected slots within ALL slots (not just available)
            $selectedIndices = [];
            foreach ($normalizedSelected as $slot) {
                $index = array_search($slot, $allSlots);
                if ($index !== false) {
                    $selectedIndices[] = $index;
                }
            }

            // Check if selected slots are consecutive
            sort($selectedIndices);
            for ($i = 1; $i < count($selectedIndices); $i++) {
                if ($selectedIndices[$i] - $selectedIndices[$i - 1] !== 1) {
                    return back()->with('error', 'Invalid selection: You can only book consecutive time slots.');
                }
            }
        }

        // Calculate new total price
        $newTotalPrice = 0;
        foreach ($newTimeSlots as $slotTime) {
            $specialPrice = SpecialBookingSlot::where('booking_for_id', $firstOldBooking->booking_for_id)
                ->where('date', $newDate)
                ->where('time', $slotTime)
                ->value('price');

            if ($specialPrice !== null) {
                $newTotalPrice += $specialPrice;
            } else {
                $regularPrice = BookingSlot::where('booking_for_id', $firstOldBooking->booking_for_id)
                    ->where('day', $day)
                    ->where('time', $slotTime)
                    ->value('price') ?? 0;
                $newTotalPrice += $regularPrice;
            }
        }

        $oldTotalAmount = $oldBookings->sum('amount');
        $priceDifference = $newTotalPrice - $oldTotalAmount;

        // Store data in session for confirmation
        session([
            'reschedule_group' => [
                'group_id' => $groupId,
                'new_date' => $newDate,
                'new_time_slots' => $newTimeSlots,
                'new_total_price' => $newTotalPrice,
                'old_total_amount' => $oldTotalAmount,
                'price_difference' => $priceDifference,
                'booking_for_id' => $firstOldBooking->booking_for_id
            ]
        ]);

        if ($priceDifference > 0) {
            // Need to collect additional payment
            $paymentEnabled = config('services.razorpay.enabled', true);
            $orderId = null;

            if ($paymentEnabled) {
                try {
                    $orderId = $this->paymentService->createOrder($priceDifference);
                } catch (\Exception $e) {
                    return back()->with('error', 'Error initializing payment: ' . $e->getMessage());
                }
            } else {
                $orderId = 'bypass_order_' . \Illuminate\Support\Str::random(10);
            }

            return view('user.reschedule_payment', [
                'booking' => $firstOldBooking,
                'newDate' => $newDate,
                'newTimeSlots' => $newTimeSlots,
                'oldAmount' => $oldTotalAmount,
                'newAmount' => $newTotalPrice,
                'amountToPay' => $priceDifference,
                'orderId' => $orderId,
                'paymentEnabled' => $paymentEnabled,
                'isGroupReschedule' => true,
                'groupId' => $groupId
            ]);
        } elseif ($priceDifference < 0) {
            // Process refund and complete reschedule
            return $this->completeGroupReschedule($groupId, abs($priceDifference), 'refund');
        } else {
            // No price difference, complete reschedule
            return $this->completeGroupReschedule($groupId, 0, 'none');
        }
    }

    /**
     * Complete group reschedule (internal helper)
     * - Moves old slots to old_booked_slots table
     * - Creates new slots in booked_slots with SAME group_id
     * - Wraps everything in a transaction
     */
    private function completeGroupReschedule($groupId, $amount, $type)
    {
        $rescheduleData = session('reschedule_group');

        if (!$rescheduleData || $rescheduleData['group_id'] !== $groupId) {
            return redirect()->route('my-booking.show')->with('error', 'Invalid reschedule session.');
        }

        try {
            DB::transaction(function () use ($groupId, $rescheduleData, $amount, $type) {
                $newDate = $rescheduleData['new_date'];
                $newTimeSlots = $rescheduleData['new_time_slots'];
                $day = ucfirst(Carbon::parse($newDate)->format('D'));
                $now = now();

                // Get old bookings
                $oldBookings = BookedSlot::where('group_id', $groupId)
                    ->where('user_id', auth()->id())
                    ->get();

                $transactionId = $oldBookings->first()->transaction_id ?? null;

                // Step 1: Move old slots to old_booked_slots table (preserve history with Rescheduled status)
                foreach ($oldBookings as $oldBooking) {
                    OldBookedSlot::create([
                        'group_id' => $oldBooking->group_id,
                        'booking_for_id' => $oldBooking->booking_for_id,
                        'user_id' => $oldBooking->user_id,
                        'date' => $oldBooking->date,
                        'time' => $oldBooking->time,
                        'amount' => $oldBooking->amount,
                        'status' => '2', // Rescheduled
                        'payment_status' => $oldBooking->payment_status,
                        'transaction_id' => $oldBooking->transaction_id,
                        'rescheduled_at' => $now,
                        'created_at' => $oldBooking->created_at,
                        'updated_at' => $oldBooking->updated_at
                    ]);
                }

                // Step 2: Delete old slots from booked_slots
                BookedSlot::where('group_id', $groupId)
                    ->where('user_id', auth()->id())
                    ->delete();

                // Step 3: Create new bookings with SAME group_id (preserve booking identity)
                foreach ($newTimeSlots as $slotTime) {
                    $slotPrice = SpecialBookingSlot::where('booking_for_id', $rescheduleData['booking_for_id'])
                        ->where('date', $newDate)
                        ->where('time', $slotTime)
                        ->value('price');

                    if ($slotPrice === null) {
                        $slotPrice = BookingSlot::where('booking_for_id', $rescheduleData['booking_for_id'])
                            ->where('day', $day)
                            ->where('time', $slotTime)
                            ->value('price') ?? 0;
                    }

                    BookedSlot::create([
                        'group_id' => $groupId, // Reuse the SAME group_id
                        'booking_for_id' => $rescheduleData['booking_for_id'],
                        'user_id' => auth()->id(),
                        'date' => $newDate,
                        'time' => $slotTime,
                        'amount' => $slotPrice,
                        'status' => '1',
                        'payment_status' => '1',
                        'transaction_id' => $transactionId
                    ]);
                }

                // Step 4: Handle refund if needed
                if ($type === 'refund' && $amount > 0) {
                    Transaction::create([
                        'user_id' => auth()->id(),
                        'amount' => $amount,
                        'currency' => 'INR',
                        'transaction_type' => 'refund',
                        'status' => 'pending',
                        'description' => 'Refund for Reschedule - Group ID: ' . $groupId
                    ]);
                }
            });

            session()->forget('reschedule_group');
            return redirect()->route('my-booking.show')->with('success', 'Booking rescheduled successfully!');

        } catch (\Exception $e) {
            return redirect()->route('my-booking.show')->with('error', 'Error rescheduling: ' . $e->getMessage());
        }
    }
}
