<?php

namespace App\Services;

use App\Models\Booking;
use App\Models\Guest;
use App\Models\BookingRoom;
use App\Models\RoomAvailability;
use App\Services\Client\BookingSessionService;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class BookingService
{

    public function __construct(
        protected RoomAvailabilityService $roomAvailabilityService
    ) {}

    /**  1. CREATE BOOKING (PENDING HOLD)  */
    public function makeBooking(array $data): Booking
    {
        return DB::transaction(function () use ($data) {
            $reference = 'TMP-' . uniqid();

            // ---------------------------------
            // 1. Create Guest
            // ---------------------------------
            $guest = Guest::create([
                'reference' => $reference,
                ...$data['guest']
            ]);

            // ---------------------------------
            // 2. Create Booking
            // ---------------------------------
            $booking = Booking::create([
                'reference' => $reference,
                'guest_id' => $guest->id,
                'check_in' => $data['check_in'],
                'check_out' => $data['check_out'],
                'total_price' => $data['total_price'],
                'base_currency' => $data['base_currency'],
                'display_total_price' => $data['display_total_price'] ?? ($data['total_price'] *  $data['exchange_rate'] ?? 1),
                'display_currency' => $data['display_currency'] ?? $data['base_currency'],
                'exchange_rate' => $data['exchange_rate'] ?? 1,
                'exchange_rate_id' => $data['exchange_rate_id'] ?? null,
                'payment_option' => $data['payment_option'] ?? null,
                'price_data' => $data['price_data'] ?? null,
                'status' => 'pending'
            ]);

            // ---------------------------------
            // 3. Create Rooms + Availability
            // ---------------------------------
            foreach ($data['rooms'] as $room) {

                $bookingRoom = BookingRoom::create([
                    'booking_id' => $booking->id,
                    'room_id' => $room['room_id'],

                    'room_title' => $room['title'],
                    'room_slug' => $room['slug'],
                    'room_number' => $room['room_number'],

                    'adults' => $room['adults'],
                    'children' => $room['children'],

                    'meal_package' => $room['meal_package'] ?? null,
                    'addons' => $room['addons'] ?? null,

                    'room_daily_prices' => $room['room_daily_prices'] ?? null,

                    'meal_total' => BookingSessionService::recalMealPckage($room['meal_package'] ?? [],  $data['nights'], ($room['adults'] + $room['children'])),
                    'grand_total' => BookingSessionService::recalRoomTotal($room,  $data['nights']),
                ]);

                // ---------------------------------
                // 4. HOLD availability (NO subDay)
                // ---------------------------------
                $this->roomAvailabilityService->holdAvailability($room['room_id'],  $booking->id,  $data['check_in'],  Carbon::parse($data['check_out'])->subDay());
            }

            return $booking->fresh();
        });
    }

    /** 2. CONFIRM BOOKING → BOOKED   */
    public function confirmBooking(Booking $booking)
    {
        DB::transaction(function () use ($booking) {

            foreach ($booking['rooms'] as $room) {
                $this->roomAvailabilityService->holdAvailability($room['room_id'],  $booking->id,  $booking['check_in'],  Carbon::parse($booking['check_out'])->subDay());
            }

            $booking->update(['status' => 'booked', 'booked_at' => now()]);
        });
    }

    public function cancelBooking(Booking $booking)
    {
        DB::transaction(function () use ($booking) {

            RoomAvailability::where('booking_id',   $booking->id)->delete();

            $booking->update(['status' => 'cancelled', 'cancelled_at' => now()]);
        });
    }

    public function checkIn(Booking $booking)
    {
        DB::transaction(function () use ($booking) {
            $booking->update(['status' => 'checked-in', 'checked_in_at' => now()]);
        });
    }

    public function checkOut(Booking $booking)
    {
        DB::transaction(function () use ($booking) {

            // availability just updated (history preserved)
            $this->roomAvailabilityService->checkedoutAvailability($booking->id);

            $booking->update(['status' => 'checked-out', 'checked_out_at' => now()]);
        });
    }
}
