<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Reservasi;
use App\Models\Meja;
use App\Models\User;
use Illuminate\Http\Request;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;

class ReservationController extends Controller
{
    public function index()
    {
        $reservations = Reservasi::with(['user', 'meja'])
            ->orderBy('date', 'desc')
            ->orderBy('start_time', 'desc')
            ->get();
        $users = User::where('role', 'user')->get();
        
        // Get all tables regardless of status
        $tables = Meja::orderBy('nomor_meja')->get();
        
        return view('admin.reservations', compact('reservations', 'users', 'tables'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'user_id' => 'required|exists:users,id',
            'meja_id' => 'required|exists:meja,id',
            'name' => 'required|string|max:255',
            'phone' => 'required|string|max:20',
            'date' => 'required|date|after_or_equal:today',
            'start_time' => 'required|date_format:H:i',
            'end_time' => 'required|date_format:H:i|after:start_time',
            'notes' => 'nullable|string',
            'total_harga' => 'required|numeric|min:0'
        ]);

        // Check if the time slot is available
        if (!Reservasi::isTimeSlotAvailable(
            $request->meja_id,
            $request->date,
            $request->start_time,
            $request->end_time
        )) {
            return back()->withErrors(['time' => 'Waktu yang dipilih sudah dipesan']);
        }

        try {
            // Create reservation
            $reservation = Reservasi::create([
                'user_id' => $request->user_id,
                'meja_id' => $request->meja_id,
                'name' => $request->name,
                'phone' => $request->phone,
                'date' => $request->date,
                'start_time' => $request->start_time,
                'end_time' => $request->end_time,
                'notes' => $request->notes,
                'status' => 'pending',
                'total_harga' => $request->total_harga
            ]);

            // Update table status if reservation is for today
            if ($request->date == now()->format('Y-m-d')) {
                Meja::where('id', $request->meja_id)
                    ->update(['status' => 'dipesan']);
            }

            return redirect()->back()->with('success', 'Reservasi berhasil ditambahkan');
        } catch (\Exception $e) {
            Log::error('Error creating reservation:', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            return back()->withErrors(['error' => 'Terjadi kesalahan saat membuat reservasi. Silakan coba lagi.'])->withInput();
        }
    }

    public function update(Request $request, Reservasi $reservation)
    {
        $request->validate([
            'status' => 'required|in:pending,confirmed,completed,cancelled',
            'meja_id' => 'required|exists:meja,id'
        ]);

        // Update both status and table
        $reservation->update([
            'status' => $request->status,
            'meja_id' => $request->meja_id
        ]);

        // Update table status based on reservation status
        if ($reservation->date == now()->format('Y-m-d')) {
            if ($request->status === 'confirmed') {
                $reservation->meja()->update(['status' => 'dipesan']);
            } elseif (in_array($request->status, ['completed', 'cancelled'])) {
                $reservation->meja()->update(['status' => 'tersedia']);
            }
        }

        if ($request->ajax()) {
            return response()->json([
                'success' => true,
                'message' => 'Reservasi berhasil diperbarui'
            ]);
        }

        return redirect()->back()->with('success', 'Reservasi berhasil diperbarui');
    }

    public function destroy(Reservasi $reservation)
    {
        try {
            // Set table status back to available if reservation was for today
            if ($reservation->date == now()->format('Y-m-d') && $reservation->meja) {
                $reservation->meja()->update(['status' => 'tersedia']);
            }
            
            $reservation->delete();
            return redirect()->back()->with('success', 'Reservasi berhasil dihapus');
        } catch (\Exception $e) {
            Log::error('Error deleting reservation:', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            return back()->withErrors(['error' => 'Terjadi kesalahan saat menghapus reservasi.']);
        }
    }

    public function getAvailableTimeSlots(Request $request)
    {
        try {
            Log::info('Admin getAvailableTimeSlots called with request:', [
                'all_params' => $request->all(),
                'date' => $request->date,
                'meja_id' => $request->meja_id
            ]);

            $request->validate([
                'meja_id' => 'required|exists:meja,id',
                'date' => 'required|date|after_or_equal:today',
            ]);

            Log::info('Validation passed, getting reservations');

            // Get existing reservations for this table and date
            $reservations = Reservasi::where('meja_id', $request->meja_id)
                ->whereDate('date', $request->date)
                ->whereNotIn('status', ['cancelled'])
                ->get();

            Log::info('Found existing reservations', [
                'count' => $reservations->count(),
                'reservations' => $reservations->toArray()
            ]);

            $timeSlots = [];
            $startHour = 10; // 10:00
            $endHour = 22;   // 22:00
            $interval = 30;   // 30 minutes interval

            Log::info('Starting to generate time slots');

            // Create a helper function to check if a time slot is reserved
            $isTimeSlotReserved = function($checkTime) use ($reservations) {
                $checkDateTime = Carbon::parse($checkTime);
                foreach ($reservations as $reservation) {
                    $reservationStart = Carbon::parse($reservation->start_time);
                    $reservationEnd = Carbon::parse($reservation->end_time);
                    if ($checkDateTime->between($reservationStart, $reservationEnd, true)) {
                        return true;
                    }
                }
                return false;
            };

            // Generate all possible time slots
            for ($hour = $startHour; $hour < $endHour; $hour++) {
                for ($minute = 0; $minute < 60; $minute += $interval) {
                    $currentTime = sprintf('%02d:%02d', $hour, $minute);
                    
                    // Check if this time slot is already reserved
                    $isReserved = $isTimeSlotReserved($currentTime);
                    
                    if (!$isReserved) {
                        $endTimeOptions = [];
                        // Generate possible end times (30 minutes to 4 hours after start time)
                        for ($duration = 30; $duration <= 240; $duration += 30) {
                            $potentialEndTime = Carbon::parse($currentTime)->addMinutes($duration);
                            
                            // Don't add end times past closing time
                            if ($potentialEndTime->format('H:i') > '22:00') {
                                continue;
                            }

                            // Check if any time between start and potential end time is reserved
                            $hasConflict = false;
                            $checkTime = Carbon::parse($currentTime);
                            while ($checkTime < $potentialEndTime) {
                                if ($isTimeSlotReserved($checkTime->format('H:i'))) {
                                    $hasConflict = true;
                                    break;
                                }
                                $checkTime->addMinutes(30);
                            }

                            if (!$hasConflict) {
                                $endTimeOptions[] = $potentialEndTime->format('H:i');
                            }
                        }

                        // Only add start time if it has at least one valid end time option
                        if (count($endTimeOptions) > 0) {
                            $timeSlots[] = [
                                'start_time' => $currentTime,
                                'end_time_options' => $endTimeOptions,
                                'is_available' => true
                            ];
                        }
                    } else {
                        // Add reserved time slot
                        $timeSlots[] = [
                            'start_time' => $currentTime,
                            'end_time_options' => [],
                            'is_available' => false
                        ];
                    }
                }
            }

            // If date is today, remove past time slots
            if ($request->date == Carbon::today()->format('Y-m-d')) {
                $currentTime = Carbon::now();
                Log::info('Filtering past time slots for today', [
                    'current_time' => $currentTime->format('H:i'),
                    'before_count' => count($timeSlots)
                ]);

                $timeSlots = array_filter($timeSlots, function($slot) use ($currentTime) {
                    return Carbon::parse($slot['start_time'])->gt($currentTime);
                });

                Log::info('After filtering past slots', [
                    'after_count' => count($timeSlots)
                ]);
            }

            $timeSlots = array_values($timeSlots);

            Log::info('Generated available time slots', [
                'count' => count($timeSlots),
                'first_few_slots' => array_slice($timeSlots, 0, 3)
            ]);

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

        } catch (\Exception $e) {
            Log::error('Error in admin getAvailableTimeSlots', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Terjadi kesalahan saat memuat jadwal: ' . $e->getMessage()
            ], 500);
        }
    }
} 