<?php

namespace App\Http\Controllers\Bookings;

use App\Http\Controllers\Controller;
use App\Models\Booking;
use App\Models\BookingPriceAdjustment;
use App\Models\MealPackage;
use App\Models\RoomCategory;
use App\Services\BookingService;
use App\Services\Client\BookingPriceAdjustmentService;
use App\Services\Client\MealPackageAvailabilityService;
use App\Services\Client\PricingService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Inertia\Inertia;

class BookingController extends Controller
{

    public function index()
    {
        $bookings = Booking::with('guest', 'rooms')
            ->latest()
            ->paginate(10);

        return Inertia::render('dashboard/bookings/index', [
            'bookings' => $bookings
        ]);
    }
    public function updateStatus(Request $request, int $id,  BookingService $bookingService)
    {
        $booking = Booking::findOrFail($id);

        $validated = $request->validate(['status' => ['required', 'in:booked,checked-in,checked-out,cancelled']]);

        $status = $validated['status'];

        match ($status) {
            'booked' =>  $bookingService->confirmBooking($booking),
            'checked-in' =>  $bookingService->checkIn($booking),
            'checked-out' =>  $bookingService->checkOut($booking),
            'cancelled' =>  $bookingService->cancelBooking($booking),
        };

        return back();
    }

    public function create(Request $request)
    {

        $request->merge([
            'check_in' => $request->check_in ?? now()->format('Y-m-d'),
            'check_out' => $request->check_out ?? now()->addDay()->format('Y-m-d'),

            'adults' => $request->adults ?? 1,
            'children' => $request->children ?? 0,
        ]);

        $validated = $request->validate([
            'check_in' => ['required',  'date',  'after_or_equal:today'],
            'check_out' => ['required',  'date',  'after:check_in'],
            'adults' => ['nullable',  'integer',  'min:1',  'max:20'],
            'children' => ['nullable',  'integer',  'min:0',  'max:20'],
        ]);

        $checkIn = $validated['check_in'];
        $checkOut = $validated['check_out'];
        $nights = Carbon::parse($checkIn)->diffInDays(Carbon::parse($checkOut));
        $adults = $validated['adults'] ?? 1;
        $children = $validated['children'] ?? 0;


        $categories = RoomCategory::query()
            ->where('max_adults', '>=', $adults)
            ->where('max_children', '>=', $children)
            ->with([
                'mealPackages' => fn($q) => $q->where('is_published', true)->get(),
                'rooms' => function ($q) use ($checkIn, $checkOut) {
                    $q->availableFor($checkIn, $checkOut)->with(['mealPackages']);
                },
            ])
            ->withCount(['rooms as available_rooms_count' => function ($q) use ($checkIn, $checkOut) {
                $q->availableFor($checkIn, $checkOut);
            }])
            ->orderBy('sort_order', 'asc')
            ->having('available_rooms_count', '>', 0)
            ->get(['id', 'name', 'short_name', 'slug', 'description', 'base_price', 'currency', 'max_adults', 'max_children']);

        $pricingService = new PricingService();

        foreach ($categories as $category) {

            foreach ($category->rooms as $room) {

                // Room price calculation
                $room->room_daily_prices = $pricingService->roomDailyPrices($room, $checkIn, $checkOut, $category);

                // Final availability
                $room->isAvailable =  $category->max_adults >= $adults && $category->max_children >= $children;

                // Filter addons amd meals for room
                $room->setRelation('mealPackages',  MealPackageAvailabilityService::filterAvailbleItems($room->mealPackages, $checkIn, $checkOut));
            }

            $category->setRelation('mealPackages', MealPackageAvailabilityService::filterAvailbleItems($category->mealPackages, $checkIn, $checkOut));
        }


        $allRoomMealPackages = MealPackage::where('scope', 'all_rooms')->where('is_published', true)->get();
        $allRoomMealPackages = MealPackageAvailabilityService::filterAvailbleItems($allRoomMealPackages, $checkIn, $checkOut);

        $priceAdjustments =  BookingPriceAdjustment::active()->validToday()->get();

        return Inertia::render('dashboard/bookings/booking', [
            'categories' => $categories,
            'check_in' => $checkIn,
            'check_out' => $checkOut,
            'nights' => $nights,
            'allRoomMealPackages' => $allRoomMealPackages,
            'price_adjustments' => $priceAdjustments
        ]);
    }

    public function store(Request $request,  BookingService $bookingService)
    {

        $validated = $request->validate([
            'guest.first_name' => 'required|string|max:255',
            'guest.last_name'  => 'required|string|max:255',
            'guest.email'      => 'required|email|max:255',
            'guest.phone'      => 'required|string|max:50',
            'guest.passport'   => 'nullable|string|max:50',
            'guest.country'    => 'required|string|max:100',
            'guest.special_requests' => 'nullable|string|max:1000',
            'payment_option'   => 'required|in:pay_now,pay_at_hotel',

            'check_in'  => 'required|date|after_or_equal:today',
            'check_out' => 'required|date|after:check_in',
            'nights'    => 'required|integer|min:1',
            'note' => 'nullable|string|max:2000',
            'base_currency' => 'required|string',
            'total_price' => 'required|numeric|min:0',

            'price_data' => 'nullable|array|min:0',
            'exchange_rate' => 'nullable|numeric|min:0',

            'rooms' => 'required|array|min:1',
            'rooms.*.meal_package' => 'nullable|array|min:0',

            'rooms.*.room_id' => 'required|exists:rooms,id',
            'rooms.*.title' => 'required|string|max:255',
            'rooms.*.slug' => 'required|string|max:255',
            'rooms.*.room_number' => 'nullable|string|max:50',

            'rooms.*.adults' => 'required|integer|min:1',
            'rooms.*.children' => 'required|integer|min:0',

            'rooms.*.room_daily_prices' => 'required|array|min:1',

            'rooms.*.room_daily_prices.*.date' => 'required|date',
            'rooms.*.room_daily_prices.*.price' => 'required|numeric|min:0',

        ], [
            'guest.first_name.required' => 'Please enter your first name.',
            'guest.first_name.string'   => 'First name must be a valid text.',
            'guest.first_name.max'      => 'First name cannot be longer than 255 characters.',

            'guest.last_name.required'  => 'Please enter your last name.',
            'guest.last_name.string'    => 'Last name must be a valid text.',
            'guest.last_name.max'       => 'Last name cannot be longer than 255 characters.',

            'guest.email.required'      => 'Please enter your email address.',
            'guest.email.email'         => 'Please enter a valid email address.',
            'guest.email.max'           => 'Email cannot be longer than 255 characters.',

            'guest.phone.required'      => 'Please provide your phone number.',
            'guest.phone.string'        => 'Phone number must be valid.',
            'guest.phone.max'           => 'Phone number cannot exceed 50 characters.',

            'guest.passport.string'     => 'Passport must be a valid text.',
            'guest.passport.max'        => 'Passport cannot be longer than 50 characters.',

            'guest.country.required'    => 'Please select your country.',
            'guest.country.string'      => 'Country must be valid text.',
            'guest.country.max'         => 'Country cannot exceed 100 characters.',

            'guest.special_requests.string' => 'Special requests must be valid text.',
            'guest.special_requests.max'    => 'Special requests cannot exceed 1000 characters.',

            'payment_option.required'   => 'Please select a payment option.',
            'payment_option.in'         => 'Payment option must be either "Pay Now" or "Pay at Hotel".',
        ]);


        // validate all data
        // dd($validated);
        // make booking
        $bookingService->makeBooking($validated);

        return self::index();
    }

    public function findRooms(Request $request) {}
}
