<?php

namespace App\Services\Client;

use App\Http\Requests\UpdateGuestRequest;
use App\Models\Booking;
use App\Models\BookingRoom;
use App\Models\Guest;
use App\Services\BookingService;
use Illuminate\Support\Facades\Session;

class BookingSessionService
{

    public static function init()
    {
        if (!Session::has('booking')) {
            Session::put('booking', self::defaults());
        }
    }

    public static function defaults()
    {
        $search = SearchSessionService::get();

        return [
            'check_in' => $search['check_in'],
            'check_out' => $search['check_out'],
            'nights' => $search['nights'],

            'guest' => [
                'first_name' => '',
                'last_name' => '',
                'email' => '',
                'phone' => '',
                'passport' => '',
                'country' => '',
                'special_requests' => '',
            ],

            'rooms' => [],
            'payment_option' => 'pay_now',

            'total_price' => 0,
            'price_data' => [],

            'base_currency' => null,
            'display_total_price' => null,
            'display_currency' => null,
            'exchange_rate' => null,
            'exchange_rate_id' => null,
        ];
    }

    public static function get()
    {
        return Session::get('booking', self::defaults());
    }


    public static function update(array $data)
    {
        // $booking = self::get();
        $booking = self::updatePriceData();

        $booking = array_merge($booking, $data);


        Session::put('booking', $booking);

        return $booking;
    }

    public static function updatePriceData()
    {
        $booking = self::get();
        $result = self::recalBookingTotal($booking);
        $booking['total_price'] = $result['total_price'];
        $booking['price_data'] = $result['price_data'];
        Session::put('booking', $booking);

        return $booking;
    }

    public static function addRoom(array $room)
    {
        $booking = self::get();
        $booking['rooms'][] = $room;
        Session::put('booking', $booking);
    }


    // ------------------------------------------------------------ Checkout
    // Add  Guest Details
    public static function updateGuest(array $guest)
    {
        self::update(['guest' => $guest]);
    }


    public static function updatePaymentMethod(string $method)
    {
        self::update(['payment_option' => $method]);
    }

    public static function updateCurrency()
    {
        $currency = CurrencyService::get();

        $data = [
            'base_currency' =>  $currency['system'],
            'display_currency' =>  $currency['selected'],
            'exchange_rate' =>  $currency['exchange_rate'],
            'exchange_rate_id' =>  $currency['exchange_rate_id'],
        ];

        self::update($data);
    }

    public static function makeBooking(BookingService $service)
    {

        $booking = self::get();

        return $service->makeBooking($booking);
    }



    public static function clear()
    {
        Session::forget('booking');
    }




    // Calculate the booking prices

    public static function recalMealPckage(array $meal_package, int $nights, int $guest): int
    {
        if (empty($meal_package)) return 0;

        $price = $meal_package['price'];

        if (!empty($meal_package['is_variant_selected']) && !empty($meal_package['variant'])) {
            $price = $meal_package['variant']['price'];
        }

        if (!empty($meal_package['is_entire_stay'])) {
            return $price * $nights * $guest;
        }

        return $price * count($meal_package['selected_days']) * $guest;
    }

    public static function recalRoomOnlyTotal(array $room_daily_prices)
    {
        return array_reduce($room_daily_prices, function ($sum, $date) {
            return $sum + $date['price'];
        }, 0);
    }

    public static function recalRoomTotal(array $room, int $nights): int
    {
        $guests = $room['adults'] + $room['children'];

        $mealPackageTotal = self::recalMealPckage(
            $room['meal_package'] ?? [],
            $nights,
            $guests
        );

        return self::recalRoomOnlyTotal($room['room_daily_prices']) + $mealPackageTotal;
    }

    public static function recalBookingSubTotal(array $booking): int
    {
        return array_reduce($booking['rooms'], function ($sum, $room) use ($booking) {
            return $sum + self::recalRoomTotal($room, $booking['nights']);
        }, 0);
    }

    public static function recalBookingTotal(array $booking): array
    {
        $subTotal = self::recalBookingSubTotal($booking);

        $rooms = count($booking['rooms']);
        $nights = $booking['nights'];

        $priceAdjustments = BookingPriceAdjustmentService::getForBooking($rooms, $nights, $subTotal, true);

        $adjustedTotal = $subTotal;
        $formattedAdjustments = [];

        foreach ($priceAdjustments as $adjustment) {

            $amount = $adjustment->calculateAmount($subTotal);

            $adjustedTotal = $adjustment->apply($amount, $adjustedTotal);

            $formattedAdjustments[] = [
                'id' => $adjustment->id,
                'name' => $adjustment->name,
                'type' => $adjustment->type,
                'direction' => $adjustment->direction,
                'value_type' => $adjustment->value_type,
                'value' => $adjustment->value,
            ];
        }

        return [
            // 'sub_total' => $subTotal,
            'total_price' => $adjustedTotal,
            'price_data' => $formattedAdjustments,
        ];
    }
}
