<?php

namespace App\Http\Controllers\BookingEngine\V1;

use App\Core\Service\PropertyAddonService;
use App\Core\Service\PropertyChannelService;
use App\Core\Service\PropertyChannelMappingService;
use App\Core\Service\PropertyRoomRateChannelMappingService;
use App\Core\Service\PropertyRoomRatePriceService;
use App\Core\Service\PropertyRoomAvailabilityService;
use App\Core\Service\FindCountryCodeService;
use App\Core\Service\PropertyPromotionService;
use App\Core\Service\PropertyBookingEngineSearchService;
use App\Core\Service\PropertyPaymentService;
use App\Core\Service\CurrencyService;
use Carbon\Carbon;
use Illuminate\Http\Request;

use App;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
use Exception;
use App\Exceptions\ApiErrorException;

class SearchController extends BookingEngineBaseController
{


    private $request;
    private $propertyChannelService;
    private $propertyChannelMappingService;
    private $propertyRoomRatePriceService;
    private $findCountryCodeService;
    private $propertyAddonService;

    private $channelId;
    private $channelConnectedId;
    private $roomsByOccupancies;
    private $dateByDay;
    private $currencyService;


    public function __construct(
        Request $request,
        PropertyChannelService $propertyChannelService,
        PropertyChannelMappingService $propertyChannelMappingService,
        PropertyRoomRateChannelMappingService $propertyRoomRateChannelMappingService,
        PropertyRoomRatePriceService $propertyRoomRatePriceService,
        PropertyRoomAvailabilityService $propertyRoomAvailabilityService,
        FindCountryCodeService $findCountryCodeService,
        PropertyPromotionService $propertyPromotionService,
        PropertyAddonService $propertyAddonService,
        PropertyBookingEngineSearchService $propertyBookingEngineSearchService,
        PropertyPaymentService $propertyPaymentService,
        CurrencyService $currencyService
    )
    {
        $this->request = $request;
        $this->propertyChannelService = $propertyChannelService;
        $this->propertyChannelMappingService = $propertyChannelMappingService;
        $this->propertyRoomRateChannelMappingService = $propertyRoomRateChannelMappingService;
        $this->propertyRoomRatePriceService = $propertyRoomRatePriceService;
        $this->propertyRoomAvailabilityService = $propertyRoomAvailabilityService;

        $this->channelId = $this->request->channelId;
        $this->channelToken = $this->request->channelToken;
        $this->bookingEngineToken = $this->request->bookingEngineToken;
        $this->bookingEnginePropertyId = $this->request->bookingEnginePropertyId;
        $this->findCountryCodeService = $findCountryCodeService;
        $this->propertyPromotionService = $propertyPromotionService;
        $this->propertyAddonService = $propertyAddonService;
        $this->propertyBookingEngineSearchService = $propertyBookingEngineSearchService;
        $this->propertyPaymentService = $propertyPaymentService;
        $this->currencyService = $currencyService;

        $this->channelConnectedId = null;

        $this->cachePrefix = 'enwAPISearch:';
        $this->cacheExpireTime = 15;//minute

    }

    public function getPropertyRoomAndRoomRateMappingData($channelPropertyRoomRate = [])
    {

        $propertyRoomAndRoomRateMappingData = [];

        foreach ($channelPropertyRoomRate as $propertyRoomRate) {
            $propertyRoomFacts = [];
            foreach ($propertyRoomRate['property_room_rate_mapping']['property_room']['property_room_fact_mapping'] as $propertyRoomFact) {
                $propertyRoomFacts[$propertyRoomFact['fact_id']] = [
                    'name' => __($propertyRoomFact['property_fact']['language_key']),
                    'icon' => $propertyRoomFact['property_fact']['icon'],
                    'is_feature' => $propertyRoomFact['is_feature'],
                ];
            }

            if (!empty($propertyRoomFacts)) {
                unset($propertyRoomRate['property_room_rate_mapping']['property_room']['property_room_fact_mapping']);
                $propertyRoomRate['property_room_rate_mapping']['property_room']['attributes'] = $propertyRoomFacts;

            }

            $propertyRoomBedGroups = [];
            $propertyRoomBedGroupCollection = collect($propertyRoomRate['property_room_rate_mapping']['property_room']['property_room_bed_group'])->groupBy('bed_group')->sortBy('bed_group')->toArray();
            foreach ($propertyRoomBedGroupCollection as $propertyRoomBedGroupKey => $propertyRoomBedGroup) {
                foreach ($propertyRoomBedGroup as $bedGroup) {
                    $propertyRoomBedGroups[$propertyRoomBedGroupKey][$bedGroup['id']] = [
                        'count' => $bedGroup['count'],
                        'name' => __($bedGroup['property_room_bed_type']['language_key']),
                        'icon' => $bedGroup['property_room_bed_type']['bedTypeIcon'],
                    ];
                }
            }

            if (!empty($propertyRoomBedGroups)) {
                unset($propertyRoomRate['property_room_rate_mapping']['property_room']['property_room_bed_group']);
                $propertyRoomRate['property_room_rate_mapping']['property_room']['bedGroups'] = $propertyRoomBedGroups;

            }


            $propertyRoomPhotos = [];
            foreach ($propertyRoomRate['property_room_rate_mapping']['property_room']['property_room_photo_mapping'] as $propertyRoomPhoto) {
                $propertyRoomPhotos[$propertyRoomPhoto['property_room_photo']['id']] = [
                    'url' => $propertyRoomPhoto['property_room_photo']['photoUrl'],
                    'is_default' => $propertyRoomPhoto['property_room_photo']['is_default'],
                    'photo_order' => $propertyRoomPhoto['property_room_photo']['photo_order'],
                ];
            }

            $propertyRoomRate['property_room_rate_mapping']['property_room']['photos'] = $propertyRoomPhotos;
            if (!empty($propertyRoomPhotos)) {
                unset($propertyRoomRate['property_room_rate_mapping']['property_room']['property_room_photo_mapping']);
            }

            $propertyRoomAndRoomRateMappingData['room'][$propertyRoomRate['property_room_rate_mapping']['property_room']['id']] = $propertyRoomRate['property_room_rate_mapping']['property_room'];
            $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRate['property_room_rate_mapping']['id']] = $propertyRoomRate['property_room_rate_mapping'];


            //Child Policy
            $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRate['property_room_rate_mapping']['id']]['roomRateMappingChildPolicy'] = [];
            if (!empty($propertyRoomRate['property_room_rate_channel_pricing_child_policy'])) {

                $roomRateMappingChildPolicy = [];
                foreach ($propertyRoomRate['property_room_rate_channel_pricing_child_policy'] as $childPolicy) {
                    $roomRateMappingChildPolicy[$childPolicy['property_pricing_policy_child']['id']] = $childPolicy['property_pricing_policy_child'];
                }

                $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRate['property_room_rate_mapping']['id']]['roomRateMappingChildPolicy'] = $roomRateMappingChildPolicy;
            }


            //Adult Policy
            $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRate['property_room_rate_mapping']['id']]['roomRateMappingAdultPolicy'] = [];
            if (!empty($propertyRoomRate['property_room_rate_channel_pricing_adult_policy'])) {

                $roomRateMappingAdultPolicy = [];
                foreach ($propertyRoomRate['property_room_rate_channel_pricing_adult_policy'] as $adultPolicy) {
                    $roomRateMappingAdultPolicy[$adultPolicy['property_pricing_policy_adult']['id']] = $adultPolicy['property_pricing_policy_adult'];
                }

                $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRate['property_room_rate_mapping']['id']]['roomRateMappingAdultPolicy'] = $roomRateMappingAdultPolicy;
            }


            $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRate['property_room_rate_mapping']['id']]['roomRateDescription'] = $propertyRoomRate['property_room_rate_mapping']['property_room_rate']['descriptionArray'];


            $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRate['property_room_rate_mapping']['id']]['roomRateMappingCancellationPolicy'] = [];
            if (!empty($propertyRoomRate['property_room_rate_channel_cancellation_policy'])) {

                $roomRateMappingCancellationPolicy = [];
                foreach ($propertyRoomRate['property_room_rate_channel_cancellation_policy'] as $cancellationPolicy) {

                    if ($cancellationPolicy['property_cancellation_policy']['status'] == 0) {
                        continue;
                    }

                    $roomRateMappingCancellationPolicy[$cancellationPolicy['property_cancellation_policy']['id']] = [
                        'id' => $cancellationPolicy['cancellation_policy_id'],
                        'name' => $cancellationPolicy['property_cancellation_policy']['name'],
                        'beforeArrivalDay' => $cancellationPolicy['property_cancellation_policy']['before_arrival'],
                        'isNonRefundable' => $cancellationPolicy['property_cancellation_policy']['is_nonrefundable'],
                        'isFreeCancellation' => $cancellationPolicy['property_cancellation_policy']['is_free_cancellation'],
                        'type' => $cancellationPolicy['property_cancellation_policy']['type'],
                        'value' => $cancellationPolicy['property_cancellation_policy']['value'],
                        'isAffectedPrice' => $cancellationPolicy['property_cancellation_policy']['is_affected_price'],
                        'affectPriceActionType' => $cancellationPolicy['property_cancellation_policy']['affect_price_action_type'],
                        'affectPriceType' => $cancellationPolicy['property_cancellation_policy']['affect_price_type'],
                        'affectPriceValue' => $cancellationPolicy['property_cancellation_policy']['affect_price_value'],
                        'is_date_range' => $cancellationPolicy['property_cancellation_policy']['is_date_range'],
                        'start_date' => $cancellationPolicy['property_cancellation_policy']['start_date'],
                        'finish_date' => $cancellationPolicy['property_cancellation_policy']['finish_date'],
                    ];
                }

                $roomRateMappingCancellationPolicy = collect($roomRateMappingCancellationPolicy)->sortByDesc('beforeArrivalDay')->toArray();

                $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRate['property_room_rate_mapping']['id']]['roomRateMappingCancellationPolicy'] = $roomRateMappingCancellationPolicy;
            }

        }

        return $propertyRoomAndRoomRateMappingData;

    }

    public function getChannelProperty($property = [])
    {

        $response = ['status' => false, 'message' => ''];

        try {

            $requestParam = [
                'criteria' => [
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $this->channelId],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'with' => ['property.propertyBookingEngineToken', 'channelAvailabilityType', 'channelBookingType', 'channelRoomPricingType', 'channelBookingPaymentType.paymentType', 'channel']
            ];

            if (!empty($property)) {
                $requestParam['whereIn'][] = ['field' => 'property_id', 'value' => $property];
            }

            $getChannelProperty = $this->propertyChannelMappingService->select($requestParam);

            if ($getChannelProperty['status'] != 'success' || empty($getChannelProperty['data'])) {
                throw new ApiErrorException(lang('Property not found'));
            }

            //if (!empty($property)) {
            foreach ($getChannelProperty['data'] as $channelPropertyKey => $channelProperty) {
                if (!empty($property) && !in_array($channelProperty['property_id'], $property)) {
                    unset($getChannelProperty['data'][$channelPropertyKey]);
                } else {

                    $channelBookingPaymentType = [];
                    foreach ($channelProperty['channel_booking_payment_type'] as $paymentType) {
                        if ($paymentType['is_selected'] && $paymentType['status']) {
                            $channelBookingPaymentType[$paymentType['payment_type']['id']] = [
                                'paymentType' => __($paymentType['payment_type']['language_key']),
                                //'paymentTypeId' => $paymentType['payment_type_id'],
                                'paymentTypeCode' => $paymentType['payment_type']['code'],
                                'cancellationPolicy' => $paymentType['cancellationPolicyArray'],
                                'isAffectedPrice' => $paymentType['is_affected_price'],
                                'isGetPaymentData' => $paymentType['is_get_payment_data'],
                                'actionType' => $paymentType['action_type'],
                                'valueType' => $paymentType['value_type'],
                                'value' => $paymentType['value'],
                            ];
                        }
                    }

                    $getChannelProperty['data'][$channelPropertyKey]['channel_booking_payment_type'] = $channelBookingPaymentType;


                }
            }
            //}

            $getChannelProperty['data'] = array_values($getChannelProperty['data']);

            $response = [
                'status' => true,
                'data' => $getChannelProperty['data'],
            ];


        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }


        return $response;

    }

    public function getChannelPropertyRoomRate($propertyId)
    {

        $response = ['status' => false, 'message' => ''];

        try {

            $channelId = $this->channelId;
            if (!empty($this->channelConnectedId)) {
                $channelId = $this->channelConnectedId;
            }

            $requestParam = [
                'criteria' => [
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $channelId],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'with' => [
                    'propertyRoomRateMapping.propertyRoomRate.propertyRoomRateAccommodation',
                    'propertyRoomRateMapping.propertyRoom.propertyRoomType',
                    'propertyRoomRateMapping.propertyRoom.propertyRoomFactMapping.propertyFact',
                    'propertyRoomRateMapping.propertyRoom.propertyRoomPhotoMapping.propertyRoomPhoto',
                    'propertyRoomRateMapping.propertyRoom.propertyRoomBedGroup.propertyRoomBedType',
                    'propertyRoomRateChannelPricingAdultPolicy.propertyPricingPolicyAdult',
                    'propertyRoomRateChannelPricingChildPolicy.propertyPricingPolicyChild',
                    'propertyRoomRateChannelCancellationPolicy.propertyCancellationPolicy',
                    //'propertyRoomRateChannelActivePromotion',
                ]
            ];

            $getChannelPropertyRoomRate = $this->propertyRoomRateChannelMappingService->select($requestParam);

            if ($getChannelPropertyRoomRate['status'] != 'success' || empty($getChannelPropertyRoomRate['data'])) {
                throw new ApiErrorException(lang('Property Room Rate not found'));
            }

            $getChannelPropertyRoomRateCollect = collect($getChannelPropertyRoomRate['data']);


            //Date Filtered
            $channelPropertyRoomRateCollectNonDateFiltered = $getChannelPropertyRoomRateCollect
                ->where('has_date', '=', 0);


            $channelPropertyRoomRateCollectDateFiltered = $getChannelPropertyRoomRateCollect
                ->where('has_date', '=', 1)
                ->where('start_date', '<=', Carbon::now()->format('Y-m-d'))
                ->where('end_date', '>=', Carbon::now()->format('Y-m-d'));

            $channelPropertyRoomRateCollectFiltered = $channelPropertyRoomRateCollectNonDateFiltered->merge($channelPropertyRoomRateCollectDateFiltered);
            //Date Filtered


            //Channel Room Rate Active Filtered
            $channelPropertyRoomRateCollectFiltered = $channelPropertyRoomRateCollectFiltered->where('property_room_rate_mapping.status', 1);

            //Room Rate Filtered
            $channelPropertyRoomRateCollectFiltered = $channelPropertyRoomRateCollectFiltered->where('property_room_rate_mapping.property_room.status', 1);

            $channelPropertyRoomRateCollectFiltered = $channelPropertyRoomRateCollectFiltered->toArray();


            $response = [
                'status' => true,
                'data' => $channelPropertyRoomRateCollectFiltered
            ];


        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }


        return $response;

    }

    public function getPropertyRoomRatePrice($param = [])
    {

        $response = ['status' => false, 'message' => ''];

        try {

            $requestParam = [
                'criteria' => [
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $param['channel_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $param['property_id']],
                    ['field' => 'stop_sell', 'condition' => '=', 'value' => 0],
                    ['field' => 'date', 'condition' => '>=', 'value' => $param['checkIn']],
                    ['field' => 'date', 'condition' => '<', 'value' => $param['checkOut']],
                    ['field' => 'amount', 'condition' => '<>', 'value' => null],
                    ['field' => 'amount', 'condition' => '<>', 'value' => 0],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'orderBy' => [
                    ['field' => 'availability_type_id', 'value' => 'ASC'],
                    ['field' => 'property_room_id', 'value' => 'ASC'],
                    ['field' => 'room_rate_mapping_id', 'value' => 'ASC'],
                    ['field' => 'date', 'value' => 'ASC']
                ],
            ];

            $getPropertyRoomRatePrice = $this->propertyRoomRatePriceService->select($requestParam);

            if ($getPropertyRoomRatePrice['status'] != 'success' || empty($getPropertyRoomRatePrice['data'])) {
                throw new ApiErrorException(lang('PropertyRoomRatePrice not found'));
            }


            //dd($getPropertyRoomRatePrice['data']);

            $response = [
                'status' => true,
                'data' => $getPropertyRoomRatePrice['data']
            ];


        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }


        return $response;

    }

    public function getPropertyRoomAndRoomRateAvailability($param = [])
    {

        $response = ['status' => false, 'message' => ''];

        try {

            $requestParam = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $param['property_id']],
                    ['field' => 'availability', 'condition' => '>', 'value' => 0],
                    ['field' => 'stop_sell', 'condition' => '=', 'value' => 0],
                    ['field' => 'date', 'condition' => '>=', 'value' => $param['checkIn']],
                    ['field' => 'date', 'condition' => '<', 'value' => $param['checkOut']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'orderBy' => [
                    ['field' => 'availability_type_id', 'value' => 'ASC'],
                    ['field' => 'property_room_id', 'value' => 'ASC'],
                    ['field' => 'room_rate_mapping_id', 'value' => 'ASC'],
                    ['field' => 'date', 'value' => 'ASC']
                ],
            ];

            $getPropertyRoomAndRoomRateAvailability = $this->propertyRoomAvailabilityService->select($requestParam);

            if ($getPropertyRoomAndRoomRateAvailability['status'] != 'success' || empty($getPropertyRoomAndRoomRateAvailability['data'])) {
                throw new ApiErrorException(lang('PropertyRoomAndRoomRateAvailability not found'));
            }

            $response = [
                'status' => true,
                'data' => $getPropertyRoomAndRoomRateAvailability['data']
            ];


        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }


        return $response;

    }


    public function search(Request $request)
    {

        //dd(Cache::get($this->cachePrefix.'4d354fd2-8fc3-0725-38bc-1f2f7e749ea8'));

        $minStayCheckProperty = null;
        $response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500, 'errorCode' => null];
        try {

            $this->channelToken = empty($this->channelToken) ? $request->header('channelToken') : $this->channelToken;
            $this->bookingEngineToken = empty($this->bookingEngineToken) ? $request->header('bookingEngineToken') : $this->bookingEngineToken;
            $this->channelId = empty($this->channelId) ? $request->header('channelId') : $this->channelId;
            $this->bookingEnginePropertyId = empty($this->bookingEnginePropertyId) ? $request->header('bookingEnginePropertyId') : $this->bookingEnginePropertyId;
            $this->language = empty($this->language) ? $request->header('language') : $this->language;

            $searchKey = md5(getGuid());

            if (is_null($request->getContent())) {
                throw new ApiErrorException(lang('Parameter Error.'));
            }

            $params = json_decode($request->getContent(), 1);

            //TODO: Burada validator olacak, date zorunlu, en az 1 oda zorunlu

            if ($params['date']['checkIn'] < Carbon::now()->toDateString()) {
                throw new ApiErrorException(lang('Check-in time cannot be earlier than today'));
            }

            $isMinStayDisabled = (isset($params['min_stay_disabled']) && $params['min_stay_disabled']) ? true : false;

            if (Carbon::parse($params['date']['checkIn'])->diff(Carbon::parse($params['date']['checkOut']))->days > 60) {
                throw new ApiErrorException(lang('You can book up to 60 days'));
            }


            $roomsByOccupancies = $this->getRoomsByOccupancies($params['rooms']);
            $this->roomsByOccupancies = $roomsByOccupancies;

            $dateByDay = $this->getDateByDay($params['date']);
            $this->dateByDay = $dateByDay;

            $channelAvailabilityType = $this->propertyRoomRateChannelMappingService->selectChannelAvailabilityType([]);
            $channelAvailabilityType = $channelAvailabilityType['status'] == 'success' ? $channelAvailabilityType['data'] : [];
            $channelAvailabilityType = collect($channelAvailabilityType)->groupBy(['id'])->toArray();

            $daysLeftForCheckin = Carbon::parse($params['date']['checkIn'])->diff(Carbon::now()->toDateString())->days;

            //Eğer $this->bookingEngineToken var ise bu token a ait prporty çekilip gönderilen veriler ezilcek ve sadece o property için fiyat verieclek
            if (!is_null($this->bookingEngineToken) && isset($this->bookingEnginePropertyId)) {
                $params['property'] = [];
                $params['property'][] = $this->bookingEnginePropertyId;
            }

            //Wholesaler
            if (in_array($request->bookingEngineChannelCategoryId, [7])) {
                //$params['property'] = [];
                return $response;
            }

            $channelProperty = $this->getChannelProperty($params['property']);

            if (!$channelProperty['status']) {
                throw new ApiErrorException($channelProperty['message']);
            }


            $searchPricesCacheWithKey = [];
            $calculatedRoomPriceFormatted = [];


            //Channel ile maplenmiş tüm oteller
            foreach ($channelProperty['data'] as $channelProperty) {

                $payAtHotelCreditCardCheck = collect($channelProperty['channel_booking_payment_type'])->where('isGetPaymentData',1)->isNotEmpty();

                //Wholesaler MARKUP
                $channelPropertyMarkup = [];
                if (in_array($channelProperty['channel']['channel_category_id'], [7])) {

                    if (!is_null($channelProperty['markup']) && !empty($channelProperty['channel']['default_currency'])) {

                        $channelPropertyMarkup['markup'] = 1;
                        if (!is_null($channelProperty['markup'])) {
                            $channelPropertyMarkup['markup'] = (($channelProperty['markup'] + 100) / 100);
                        }

                        $lastExchangeRate = 1;
                        if ($channelProperty['currency_code'] != $channelProperty['channel']['default_currency']) {
                            $lastExchangeRate = $this->currencyService->lastExchangeRate($channelProperty['currency_code'], $channelProperty['channel']['default_currency']);
                            if ($lastExchangeRate['status'] == 'success') {
                                $lastExchangeRate = $lastExchangeRate['data'];
                            }
                        }
                        $channelPropertyMarkup['exchange'] = $lastExchangeRate;
                        $channelPropertyMarkup['currency_code'] = $channelProperty['channel']['default_currency'];
                    } else {
                        $channelPropertyMarkup = [];
                    }
                }
                //Wholesaler MARKUP

                //Bağlı kanala ait özelliklerin alınması
                if (!is_null($channelProperty['connected_channel_id']) && $channelProperty['connected_channel_id'] != 5) {

                    $requestConnectedChannelParam = [
                        'criteria' => [
                            ['field' => 'property_id', 'condition' => '=', 'value' => $channelProperty['property_id']],
                            ['field' => 'channel_id', 'condition' => '=', 'value' => $channelProperty['connected_channel_id']],
                        ],
                        'with' => ['channelAvailabilityType', 'channelBookingType', 'channelRoomPricingType', 'channelBookingPaymentType.paymentType'],
                        'firstRow' => true
                    ];

                    $getConnectedChannel = $this->propertyChannelMappingService->select($requestConnectedChannelParam);

                    if ($getConnectedChannel['status'] != 'success' || empty($getConnectedChannel['data'])) {
                        continue;
                    }

                    $channelProperty['currency_code'] = $getConnectedChannel['data']['currency_code'];
                    $channelProperty['property_booking_type_id'] = $getConnectedChannel['data']['property_booking_type_id'];
                    $channelProperty['property_availability_type_id'] = $getConnectedChannel['data']['property_availability_type_id'];
                    $channelProperty['property_room_pricing_type_id'] = $getConnectedChannel['data']['property_room_pricing_type_id'];

                    $channelProperty['channel_availability_type'] = $getConnectedChannel['data']['channel_availability_type'];
                    $channelProperty['channel_booking_type'] = $getConnectedChannel['data']['channel_booking_type'];
                    $channelProperty['channel_room_pricing_type'] = $getConnectedChannel['data']['channel_room_pricing_type'];


                }

                //$channelBookingPaymentTypePolicy
                $channelBookingPaymentTypePolicy = [];
                if (!empty($channelProperty['channel_booking_payment_type'])) {

                    foreach ($channelProperty['channel_booking_payment_type'] as $channelBookingPaymentTypeId => $channelBookingPaymentType) {

                        $channelBookingPaymentTypePolicy[$channelBookingPaymentTypeId] = [
                            'name' => $channelBookingPaymentType['paymentType'],
                            'code' => $channelBookingPaymentType['paymentTypeCode'],
                            'isAffectedPrice' => $channelBookingPaymentType['isAffectedPrice'],
                            'isGetPaymentData' => $channelBookingPaymentType['isGetPaymentData'],
                            'affectPriceActionType' => $channelBookingPaymentType['actionType'],
                            'affectPriceType' => $channelBookingPaymentType['valueType'],
                            'affectPriceValue' => $channelBookingPaymentType['value'],
                            'cancellationPolicy' => $channelBookingPaymentType['cancellationPolicy'],
                            'paymentTypeMapping' => null,
                        ];

                        if ($channelBookingPaymentType['paymentTypeCode'] == 'CRD') {
                            $paymentMappingRequest = $this->propertyPaymentService->getPaymentMappingList(['property_id' => $channelProperty['property_id']]);
                            $paymentMappingRequest = $paymentMappingRequest['status'] == 'success' ? collect($paymentMappingRequest['data'])->pluck('pos_code')->toArray() : null;
                            $channelBookingPaymentTypePolicy[$channelBookingPaymentTypeId]['paymentTypeMapping'] = $paymentMappingRequest;
                        }

                    }

                }


                //Eğer bağlı bir kanal ise ve bu kanal acente tipinde ise
                if (!is_null($channelProperty['connected_channel_id']) && $channelProperty['connected_channel_id'] != 5 && in_array($channelProperty['channel']['channel_category_id'], [2, 7])) {
                    $this->channelConnectedId = $channelProperty['connected_channel_id'];
                }


                //Kanala ait otelin aktif olan room rate leri
                $getChannelPropertyRoomRate = $this->getChannelPropertyRoomRate($channelProperty['property_id']);
                if ($getChannelPropertyRoomRate['status'] != 'success' || empty($getChannelPropertyRoomRate['data'])) {
                    continue;
                }


                //Kanala ait otelin aktif olan room rate fiyatları
                $propertyRoomRatePriceParam = [
                    'channel_id' => $channelProperty['channel_id'],
                    'property_id' => $channelProperty['property_id'],
                    'checkIn' => $params['date']['checkIn'],
                    'checkOut' => $params['date']['checkOut'],
                ];

                //connected_channel_id manipulation
                if (!is_null($channelProperty['connected_channel_id']) && $channelProperty['connected_channel_id'] != 5) {
                    $propertyRoomRatePriceParam['channel_id'] = $channelProperty['connected_channel_id'];
                }

                // if($request->getClientIp() == '185.137.215.118') {
                //dd($propertyRoomRatePriceParam);
                //}

                $getPropertyRoomRatePrice = $this->getPropertyRoomRatePrice($propertyRoomRatePriceParam);

                if ($getPropertyRoomRatePrice['status'] != 'success' || empty($getPropertyRoomRatePrice['data'])) {
                    continue;
                }

                //connected_channel_id manipulation
                if (!is_null($channelProperty['connected_channel_id']) && !is_null($channelProperty['connected_channel_action']) && $channelProperty['connected_channel_id'] != 5) {

                    $connectedChannelAction = json_decode($channelProperty['connected_channel_action'], 1);

                    foreach ($getPropertyRoomRatePrice['data'] as $roomRatePriceKey => $roomRatePrice) {

                        $roomRatePriceAffected = 0;

                        if ($connectedChannelAction['type'] == 'PER') {
                            $roomRatePriceAffected = ($roomRatePrice['amount'] * $connectedChannelAction['value']) / 100;
                        } elseif ($connectedChannelAction['type'] == 'FIX') {
                            $roomRatePriceAffected = $connectedChannelAction['value'];
                        }

                        if ($connectedChannelAction['action_type'] == 'INC') {
                            $getPropertyRoomRatePrice['data'][$roomRatePriceKey]['amount'] = $roomRatePrice['amount'] + $roomRatePriceAffected;
                        }

                        if ($connectedChannelAction['action_type'] == 'DEC') {
                            $getPropertyRoomRatePrice['data'][$roomRatePriceKey]['amount'] = $roomRatePrice['amount'] - $roomRatePriceAffected;
                        }

                    }
                }
                //connected_channel_id manipulation


                $propertyRoomAndRoomRateAvailabilityParam = [
                    'property_id' => $channelProperty['property_id'],
                    'checkIn' => $params['date']['checkIn'],
                    'checkOut' => $params['date']['checkOut'],
                ];

                $getPropertyRoomAndRoomRateAvailability = $this->getPropertyRoomAndRoomRateAvailability($propertyRoomAndRoomRateAvailabilityParam);

                if ($getPropertyRoomAndRoomRateAvailability['status'] != 'success' || empty($getPropertyRoomAndRoomRateAvailability['data'])) {
                    continue;
                }


                //Room ve Room Date Mapping datası
                $propertyRoomAndRoomRateMappingData = $this->getPropertyRoomAndRoomRateMappingData($getChannelPropertyRoomRate['data']);


                /**** PROMOTION START ****/
                $promotionGroupByDay = [];
                $propertyPromotionMappingCriteria = [
                    'criteria' => [
                        ['field' => 'property_id', 'condition' => '=', 'value' => $channelProperty['property_id']],
                        ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ],
                    'with' => ['propertyPromotion.promotionType', 'propertyRoomRateChannelMapping']
                ];


                $propertyPromotionMapping = $this->propertyPromotionService->selectPropertyPromotionMapping($propertyPromotionMappingCriteria);
                if ($propertyPromotionMapping['status'] == 'success' && !empty($propertyPromotionMapping['data'])) {
                    $propertyPromotionMapping = $propertyPromotionMapping['data'];
                } else {
                    $propertyPromotionMapping = [];
                }

                //Eğer bağlı bir kanal var ise ve booking engine e bağlıysa burada promosyon çalıştırılmaz!
                if (!is_null($channelProperty['connected_channel_id']) && $channelProperty['connected_channel_id'] == 1 && !in_array($channelProperty['channel']['channel_category_id'], [2, 3, 7])) {
                    $propertyPromotionMapping = [];
                }

                //Hangi room rate channel datası için komisyon verilecek...
                $roomRateChannelMappingIdList = array_values(array_unique(pickItemFromArray('room_rate_channel_mapping_id', $propertyPromotionMapping)));

                $propertyPromotionMapping = collect($propertyPromotionMapping);
                $propertyPromotionMappingGrouped = $propertyPromotionMapping->groupBy(['property_promotion.promotion_type.type_code'])->toArray();

                //dd($propertyPromotionMappingGrouped);

                foreach ($roomRateChannelMappingIdList as $roomRateChannelMappingId) {
                    foreach ($propertyPromotionMappingGrouped as $promotionType => $promotions) {

                        $promotionsCollect = collect($promotions)->sortByDesc('property_promotion.amount');

                        foreach ($dateByDay as $day) {

                            $promotionsCollectFiltered = null;

                            if ($promotionType == 'PRD') {

                                //burada promosyonun işleneceği eşleştirmeinin de oluşturulması lazım gün bazında
                                //"1-1-1-2021-12-28"
                                /*
                                        "property_id" => 1
                                        "room_rate_mapping_id" => 1
                                        "channel_id" => 1
                                        "date" => "2021-12-28"
                                 * */

                                $promotionsCollectFiltered = $promotionsCollect
                                    ->where('room_rate_channel_mapping_id', '=', $roomRateChannelMappingId)
                                    ->where('property_promotion.start_date', '<=', Carbon::now()->toDateString())
                                    ->where('property_promotion.end_date', '>=', Carbon::now()->toDateString())
                                    ->where('property_promotion.reservation_start_date', '<=', $day)
                                    ->where('property_promotion.reservation_end_date', '>=', $day)
                                    ->where('property_promotion.min_stay', '<=', count($dateByDay))
                                    ->filter(function ($propertyPromotion) use ($day) {
                                        $weekDay = Carbon::parse($day)->weekday() == 0 ? 7 : Carbon::parse($day)->weekday();
                                        if (is_array($propertyPromotion['property_promotion']['daysArray']) && in_array($weekDay, $propertyPromotion['property_promotion']['daysArray'])) {
                                            return $propertyPromotion;
                                        }
                                    });

                                if (count($promotionsCollectFiltered) > 1) {
                                    if (isset($params['isMobile']) && $params['isMobile'] == 1) {
                                        $promotionsCollectFiltered = $promotionsCollectFiltered->where('property_promotion.is_mobile', '=', 1);
                                    } else {
                                        $promotionsCollectFiltered = $promotionsCollectFiltered->where('property_promotion.is_mobile', '!=', 1);
                                    }

                                } else {
                                    if ($promotionsCollectFiltered->pluck('property_promotion.is_mobile')->first() == 1) {
                                        if (!isset($params['isMobile']) || $params['isMobile'] != 1) {
                                            $promotionsCollectFiltered = $promotionsCollectFiltered->where('property_promotion.is_mobile', '!=', 1);
                                        }
                                    }
                                }

                                $promotionsCollectFiltered = $promotionsCollectFiltered->sortByDesc('property_promotion.min_stay')->first();

                                $promotionHashKey = null;
                                if (!is_null($promotionsCollectFiltered)) {

                                    /*$isPromotionJustMobile = $promotionsCollectFiltered['property_promotion']['is_mobile'];
                                    if($isPromotionJustMobile && (!isset($params['isMobile']) || empty($params['isMobile']))) {
                                        continue;
                                    }*/

                                    $promotionKey = $promotionsCollectFiltered['property_room_rate_channel_mapping']['property_id'] . '-' .
                                        $promotionsCollectFiltered['property_room_rate_channel_mapping']['room_rate_mapping_id'] . '-' .
                                        $promotionsCollectFiltered['property_room_rate_channel_mapping']['channel_id'] . '-' .
                                        Carbon::parse($day)->format('Ymd');


                                    if (!isset($promotionGroupByDay[$promotionKey]) && $promotionsCollectFiltered['property_promotion']['amount'] < 100) {
                                        $promotionGroupByDay[$promotionKey] = [
                                            'discountRate' => $promotionsCollectFiltered['property_promotion']['amount'],
                                            'type_code' => $promotionsCollectFiltered['property_promotion']['promotion_type']['type_code'],
                                            'id' => $promotionsCollectFiltered['property_promotion']['id']
                                        ];
                                    } elseif (isset($promotionGroupByDay[$promotionKey]) && $promotionsCollectFiltered['property_promotion']['amount'] > $promotionGroupByDay[$promotionKey]['discountRate']) {
                                        $promotionGroupByDay[$promotionKey] = [
                                            'discountRate' => $promotionsCollectFiltered['property_promotion']['amount'],
                                            'type_code' => $promotionsCollectFiltered['property_promotion']['promotion_type']['type_code'],
                                            'id' => $promotionsCollectFiltered['property_promotion']['id']
                                        ];
                                    }

                                }

                            }

                            if ($promotionType == 'BFD') {

                                //dd($dateByDay[0], Carbon::now()->toDateString(), Carbon::parse($dateByDay[0])->diff(Carbon::now())->days);

                                $promotionsCollectFiltered = $promotionsCollect
                                    ->where('room_rate_channel_mapping_id', '=', $roomRateChannelMappingId)
                                    ->where('property_promotion.day_before', '<=', Carbon::parse($dateByDay[0])->diff(Carbon::now()->toDateString())->days)
                                    ->where('property_promotion.min_stay', '<=', count($dateByDay))
                                    ->filter(function ($propertyPromotion) use ($day) {
                                        $weekDay = Carbon::parse($day)->weekday() == 0 ? 7 : Carbon::parse($day)->weekday();
                                        if (is_array($propertyPromotion['property_promotion']['daysArray']) && in_array($weekDay, $propertyPromotion['property_promotion']['daysArray'])) {
                                            return $propertyPromotion;
                                        }
                                    })->sortByDesc('property_promotion.day_before');

                                if (count($promotionsCollectFiltered) > 1) {
                                    if (isset($params['isMobile']) && $params['isMobile'] == 1) {
                                        $promotionsCollectFiltered = $promotionsCollectFiltered->where('property_promotion.is_mobile', '=', 1);
                                    } else {
                                        $promotionsCollectFiltered = $promotionsCollectFiltered->where('property_promotion.is_mobile', '!=', 1);
                                    }
                                } else {
                                    if ($promotionsCollectFiltered->pluck('property_promotion.is_mobile')->first() == 1) {
                                        if (!isset($params['isMobile']) || $params['isMobile'] != 1) {
                                            $promotionsCollectFiltered = $promotionsCollectFiltered->where('property_promotion.is_mobile', '!=', 1);
                                        }
                                    }
                                }

                                $promotionsCollectFiltered = $promotionsCollectFiltered->first();

                                $promotionHashKey = null;
                                if (!is_null($promotionsCollectFiltered)) {

                                    /*$isPromotionJustMobile = $promotionsCollectFiltered['property_promotion']['is_mobile'];
                                    if($isPromotionJustMobile && (!isset($params['isMobile']) || empty($params['isMobile']))) {
                                        continue;
                                    }*/

                                    //excludeDatesArray
                                    if (isset($promotionsCollectFiltered['property_promotion']['excludeDatesArray']) && in_array($day, $promotionsCollectFiltered['property_promotion']['excludeDatesArray'])) {
                                        continue;
                                    }

                                    $promotionKey = $promotionsCollectFiltered['property_room_rate_channel_mapping']['property_id'] . '-' .
                                        $promotionsCollectFiltered['property_room_rate_channel_mapping']['room_rate_mapping_id'] . '-' .
                                        $promotionsCollectFiltered['property_room_rate_channel_mapping']['channel_id'] . '-' .
                                        Carbon::parse($day)->format('Ymd');

                                    if (!isset($promotionGroupByDay[$promotionKey]) && $promotionsCollectFiltered['property_promotion']['amount'] < 100) {
                                        $promotionGroupByDay[$promotionKey] = [
                                            'discountRate' => $promotionsCollectFiltered['property_promotion']['amount'],
                                            'type_code' => $promotionsCollectFiltered['property_promotion']['promotion_type']['type_code'],
                                            'id' => $promotionsCollectFiltered['property_promotion']['id']
                                        ];
                                    } elseif (isset($promotionGroupByDay[$promotionKey]) && $promotionsCollectFiltered['property_promotion']['amount'] > $promotionGroupByDay[$promotionKey]['discountRate']) {
                                        $promotionGroupByDay[$promotionKey] = [
                                            'discountRate' => $promotionsCollectFiltered['property_promotion']['amount'],
                                            'type_code' => $promotionsCollectFiltered['property_promotion']['promotion_type']['type_code'],
                                            'id' => $promotionsCollectFiltered['property_promotion']['id']
                                        ];
                                    }
                                }
                            }

                            if ($promotionType == 'LST') {

                                //dd($dateByDay[0], Carbon::now()->toDateString(), Carbon::parse($dateByDay[0])->diff(Carbon::now())->days);
                                $promotionsCollectFiltered = $promotionsCollect
                                    ->where('room_rate_channel_mapping_id', '=', $roomRateChannelMappingId)
                                    ->where('property_promotion.day_before', '>=', Carbon::parse($dateByDay[0])->diff(Carbon::now()->toDateString())->days)
                                    ->where('property_promotion.min_stay', '<=', count($dateByDay))
                                    ->where('property_promotion.is_time', null)
                                    ->filter(function ($propertyPromotion) use ($day) {
                                        $weekDay = Carbon::parse($day)->weekday() == 0 ? 7 : Carbon::parse($day)->weekday();
                                        if (is_array($propertyPromotion['property_promotion']['daysArray']) && in_array($weekDay, $propertyPromotion['property_promotion']['daysArray'])) {
                                            return $propertyPromotion;
                                        }
                                    })->sortBy('property_promotion.day_before');

                                if (count($promotionsCollectFiltered) > 1) {
                                    if (isset($params['isMobile']) && $params['isMobile'] == 1) {
                                        $promotionsCollectFiltered = $promotionsCollectFiltered->where('property_promotion.is_mobile', '=', 1);
                                    } else {
                                        $promotionsCollectFiltered = $promotionsCollectFiltered->where('property_promotion.is_mobile', '!=', 1);
                                    }
                                } else {
                                    if ($promotionsCollectFiltered->pluck('property_promotion.is_mobile')->first() == 1) {
                                        if (!isset($params['isMobile']) || $params['isMobile'] != 1) {
                                            $promotionsCollectFiltered = $promotionsCollectFiltered->where('property_promotion.is_mobile', '!=', 1);
                                        }
                                    }
                                }

                                //If there is a promotion with a fixed time, it gets priority.
                                $promotionsCollectFilteredCertainTime = $promotionsCollect
                                    ->where('room_rate_channel_mapping_id', '=', $roomRateChannelMappingId)
                                    ->where('property_promotion.day_before', '>=', Carbon::parse($dateByDay[0])->diff(Carbon::now()->toDateString())->days)
                                    ->where('property_promotion.min_stay', '<=', count($dateByDay))
                                    ->where('property_promotion.is_time', 1)
                                    ->where('property_promotion.start_time', '<=', Carbon::now()->format('H:i:s'))
                                    ->where('property_promotion.end_time', '>=', Carbon::now()->format('H:i:s'))
                                    ->filter(function ($propertyPromotion) use ($day) {
                                        $weekDay = Carbon::parse($day)->weekday() == 0 ? 7 : Carbon::parse($day)->weekday();
                                        if (is_array($propertyPromotion['property_promotion']['daysArray']) && in_array($weekDay, $propertyPromotion['property_promotion']['daysArray'])) {
                                            return $propertyPromotion;
                                        }
                                    })->sortByDesc('property_promotion.amount');


                                if (!is_null($promotionsCollectFilteredCertainTime->first())) {
                                    $promotionsCollectFiltered = $promotionsCollectFilteredCertainTime->first();
                                } else {
                                    $promotionsCollectFiltered = $promotionsCollectFiltered->first();
                                }


                                $promotionHashKey = null;
                                if (!is_null($promotionsCollectFiltered)) {

                                    /*$isPromotionJustMobile = $promotionsCollectFiltered['property_promotion']['is_mobile'];
                                    if($isPromotionJustMobile && (!isset($params['isMobile']) || empty($params['isMobile']))) {
                                        continue;
                                    }*/

                                    $promotionKey = $promotionsCollectFiltered['property_room_rate_channel_mapping']['property_id'] . '-' .
                                        $promotionsCollectFiltered['property_room_rate_channel_mapping']['room_rate_mapping_id'] . '-' .
                                        $promotionsCollectFiltered['property_room_rate_channel_mapping']['channel_id'] . '-' .
                                        Carbon::parse($day)->format('Ymd');

                                    if (!isset($promotionGroupByDay[$promotionKey]) && $promotionsCollectFiltered['property_promotion']['amount'] < 100) {
                                        $promotionGroupByDay[$promotionKey] = [
                                            'discountRate' => $promotionsCollectFiltered['property_promotion']['amount'],
                                            'type_code' => $promotionsCollectFiltered['property_promotion']['promotion_type']['type_code'],
                                            'id' => $promotionsCollectFiltered['property_promotion']['id']
                                        ];
                                    } elseif (isset($promotionGroupByDay[$promotionKey]) && $promotionsCollectFiltered['property_promotion']['amount'] > $promotionGroupByDay[$promotionKey]['discountRate']) {
                                        $promotionGroupByDay[$promotionKey] = [
                                            'discountRate' => $promotionsCollectFiltered['property_promotion']['amount'],
                                            'type_code' => $promotionsCollectFiltered['property_promotion']['promotion_type']['type_code'],
                                            'id' => $promotionsCollectFiltered['property_promotion']['id']
                                        ];
                                    }
                                }

                            }


                            if ($promotionType == 'DSC') {

                                //Default
                                $defaultPromotionDiscount = $promotionsCollect
                                    ->where('room_rate_channel_mapping_id', '=', $roomRateChannelMappingId)
                                    ->where('property_promotion.is_time', null)
                                    ->where('property_promotion.min_stay', '<=', count($dateByDay))
                                    ->filter(function ($propertyPromotion) use ($day) {
                                        $weekDay = Carbon::parse($day)->weekday() == 0 ? 7 : Carbon::parse($day)->weekday();
                                        if (is_array($propertyPromotion['property_promotion']['daysArray']) && in_array($weekDay, $propertyPromotion['property_promotion']['daysArray'])) {
                                            return $propertyPromotion;
                                        }
                                    })->sortByDesc('property_promotion.amount');

                                if (isset($params['isMobile']) && $params['isMobile'] == 1) {
                                    $defaultPromotionDiscountMobile = $defaultPromotionDiscount->where('property_promotion.is_mobile', '=', 1);
                                    if ($defaultPromotionDiscountMobile->isNotEmpty()) {
                                        $defaultPromotionDiscount = $defaultPromotionDiscountMobile;
                                    }
                                } else {
                                    $defaultPromotionDiscount = $defaultPromotionDiscount->where('property_promotion.is_mobile', '!=', 1);
                                }


                                $promotionsCollectFiltered = $promotionsCollect
                                    ->where('room_rate_channel_mapping_id', '=', $roomRateChannelMappingId)
                                    ->where('property_promotion.is_time', 1)
                                    ->where('property_promotion.start_time', '<=', Carbon::now()->format('H:i:s'))
                                    ->where('property_promotion.end_time', '>=', Carbon::now()->format('H:i:s'))
                                    ->where('property_promotion.min_stay', '<=', count($dateByDay))
                                    ->filter(function ($propertyPromotion) use ($day) {
                                        $weekDay = Carbon::parse($day)->weekday() == 0 ? 7 : Carbon::parse($day)->weekday();
                                        if (is_array($propertyPromotion['property_promotion']['daysArray']) && in_array($weekDay, $propertyPromotion['property_promotion']['daysArray'])) {
                                            return $propertyPromotion;
                                        }
                                    })->sortByDesc('property_promotion.amount');


                                if (isset($params['isMobile']) && $params['isMobile'] == 1) {
                                    $promotionsCollectFiltered = $promotionsCollectFiltered->where('property_promotion.is_mobile', '=', 1);
                                    if ($promotionsCollectFiltered->isNotEmpty()) {
                                        $promotionsCollectFiltered = $promotionsCollectFiltered;
                                    }
                                } else {
                                    $promotionsCollectFiltered = $promotionsCollectFiltered->where('property_promotion.is_mobile', '!=', 1);
                                }


                                if ($promotionsCollectFiltered->isEmpty()) {
                                    $promotionsCollectFiltered = $defaultPromotionDiscount;
                                }


                                $promotionsCollectFiltered = $promotionsCollectFiltered->first();

                                $promotionHashKey = null;
                                if (!is_null($promotionsCollectFiltered)) {

                                    /*$isPromotionJustMobile = $promotionsCollectFiltered['property_promotion']['is_mobile'];
                                    if($isPromotionJustMobile && (!isset($params['isMobile']) || empty($params['isMobile']))) {
                                        continue;
                                    }*/

                                    //excludeDatesArray
                                    if (isset($promotionsCollectFiltered['property_promotion']['excludeDatesArray']) && in_array($day, $promotionsCollectFiltered['property_promotion']['excludeDatesArray'])) {
                                        continue;
                                    }

                                    $promotionKey = $promotionsCollectFiltered['property_room_rate_channel_mapping']['property_id'] . '-' .
                                        $promotionsCollectFiltered['property_room_rate_channel_mapping']['room_rate_mapping_id'] . '-' .
                                        $promotionsCollectFiltered['property_room_rate_channel_mapping']['channel_id'] . '-' .
                                        Carbon::parse($day)->format('Ymd');

                                    if (!isset($promotionGroupByDay[$promotionKey]) && $promotionsCollectFiltered['property_promotion']['amount'] < 100) {
                                        $promotionGroupByDay[$promotionKey] = [
                                            'discountRate' => $promotionsCollectFiltered['property_promotion']['amount'],
                                            'type_code' => $promotionsCollectFiltered['property_promotion']['promotion_type']['type_code'],
                                            'id' => $promotionsCollectFiltered['property_promotion']['id']
                                        ];
                                    } elseif (isset($promotionGroupByDay[$promotionKey]) && $promotionsCollectFiltered['property_promotion']['amount'] > $promotionGroupByDay[$promotionKey]['discountRate']) {
                                        $promotionGroupByDay[$promotionKey] = [
                                            'discountRate' => $promotionsCollectFiltered['property_promotion']['amount'],
                                            'type_code' => $promotionsCollectFiltered['property_promotion']['promotion_type']['type_code'],
                                            'id' => $promotionsCollectFiltered['property_promotion']['id']
                                        ];
                                    }
                                }

                            }

                            //Log::debug($promotionGroupByDay);

                        }

                    }
                }
                //dd($promotionGroupByDay, $propertyPromotionMapping);
                /**** PROMOTION FINISH ****/

                //dd($promotionGroupByDay);


                $getPropertyRoomRatePrice = collect($getPropertyRoomRatePrice['data']);


                $minStayCheckProperty = $getPropertyRoomRatePrice->sortByDesc('min_stay')->groupBy('min_stay')->keys()->first();

                //Kanala ait otelin aktif olan room rate lerin gruplanarak gün bazında fiyat var mı hesalanması
                // Availability Type - Property Room - Room Rate Mapping
                $getPropertyRoomRatePriceGrouped = $getPropertyRoomRatePrice->groupBy(['availability_type_id', 'property_room_id', 'room_rate_mapping_id', 'date'])->toArray();

                foreach ($getPropertyRoomRatePriceGrouped as $getPropertyRoomRatePriceAvailabilityKey => $getPropertyRoomRatePriceAvailability) {
                    foreach ($getPropertyRoomRatePriceAvailability as $getPropertyRoomRatePriceAvailabilityRoomKey => $getPropertyRoomRatePriceAvailabilityRoom) {

                        foreach ($getPropertyRoomRatePriceAvailabilityRoom as $getPropertyRoomRatePriceAvailabilityRoomRateKey => $getPropertyRoomRatePriceAvailabilityRoomRate) {

                            unset($getPropertyRoomRatePriceGrouped[$getPropertyRoomRatePriceAvailabilityKey][$getPropertyRoomRatePriceAvailabilityRoomKey][$getPropertyRoomRatePriceAvailabilityRoomRateKey]);

                            if (!empty(array_diff($this->dateByDay, array_keys($getPropertyRoomRatePriceAvailabilityRoomRate)))) {
                                unset($getPropertyRoomRatePriceGrouped[$getPropertyRoomRatePriceAvailabilityKey][$getPropertyRoomRatePriceAvailabilityRoomKey][$getPropertyRoomRatePriceAvailabilityRoomRateKey]);
                            } else {

                                $getPropertyRoomRatePriceAvailabilityRoomRate = array_map(function ($propertyRoomRatePriceAvailabilityRoomRate) {
                                    return reset($propertyRoomRatePriceAvailabilityRoomRate);
                                }, $getPropertyRoomRatePriceAvailabilityRoomRate);


                                //MIN_STAY CHECK
                                $minStayCheckCollect = collect($getPropertyRoomRatePriceAvailabilityRoomRate);
                                $minStayCheck = $minStayCheckCollect->sortByDesc('min_stay')->first();

                                //$isMinStayDisabled
                                if ($isMinStayDisabled) {
                                    $minStayCheck['min_stay'] = 0;
                                }

                                if (intval($minStayCheck['min_stay']) > count($this->dateByDay)) {
                                    unset($getPropertyRoomRatePriceGrouped[$getPropertyRoomRatePriceAvailabilityKey][$getPropertyRoomRatePriceAvailabilityRoomKey][$getPropertyRoomRatePriceAvailabilityRoomRateKey]);
                                } else {

                                    //PROMOTION CALCULATE
                                    foreach ($getPropertyRoomRatePriceAvailabilityRoomRate as $day => $dailyDetail) {

                                        $getPropertyRoomRatePriceAvailabilityRoomRate[$day]['baseAmount'] = $dailyDetail['amount'];
                                        $getPropertyRoomRatePriceAvailabilityRoomRate[$day]['discountRate'] = 0;

                                        //TODO : Delete
                                        /*$dailyDetailPromoCheckKey = $dailyDetail['property_id'] . '-' .
                                            $dailyDetail['room_rate_mapping_id'] . '-' .
                                            $dailyDetail['channel_id'] . '-' .
                                            Carbon::parse($day)->format('Ymd');

                                        if (array_key_exists($dailyDetailPromoCheckKey, $promotionGroupByDay)) {
                                            $getPropertyRoomRatePriceAvailabilityRoomRate[$day]['discountRate'] = $promotionGroupByDay[$dailyDetailPromoCheckKey]['discountRate'];
                                            $getPropertyRoomRatePriceAvailabilityRoomRate[$day]['amount'] = moneyDoubleFormatDecimal($dailyDetail['amount'] - ($dailyDetail['amount'] * ($promotionGroupByDay[$dailyDetailPromoCheckKey]['discountRate'] / 100)));
                                        }*/

                                    }

                                    $getPropertyRoomRatePriceGrouped[$getPropertyRoomRatePriceAvailabilityKey][$getPropertyRoomRatePriceAvailabilityRoomKey][$getPropertyRoomRatePriceAvailabilityRoomRateKey] = $getPropertyRoomRatePriceAvailabilityRoomRate;

                                }

                            }

                        }

                        if (empty($getPropertyRoomRatePriceGrouped[$getPropertyRoomRatePriceAvailabilityKey][$getPropertyRoomRatePriceAvailabilityRoomKey])) {
                            unset($getPropertyRoomRatePriceGrouped[$getPropertyRoomRatePriceAvailabilityKey][$getPropertyRoomRatePriceAvailabilityRoomKey]);
                        }

                    }

                    if (empty($getPropertyRoomRatePriceGrouped[$getPropertyRoomRatePriceAvailabilityKey])) {
                        unset($getPropertyRoomRatePriceGrouped[$getPropertyRoomRatePriceAvailabilityKey]);
                    }
                }
                //Kanala ait otelin aktif olan room rate lerin gruplanarak gün bazında fiyat var mı hesaplanması


                //Kanalın müsaitlik type ına göre kullanılacak olanların seçilmesi
                $selectedPropertyRoomRatePriceGrouped = [];
                if (isset($getPropertyRoomRatePriceGrouped[$channelProperty['channel_availability_type']['id']])) {
                    $selectedPropertyRoomRatePriceGrouped[$channelProperty['channel_availability_type']['id']] = $getPropertyRoomRatePriceGrouped[$channelProperty['channel_availability_type']['id']];
                }


                if ($channelProperty['channel_availability_type']['code'] == 'GRT') {
                    if (isset($getPropertyRoomRatePriceGrouped[1])) {
                        $selectedPropertyRoomRatePriceGrouped[1] = $getPropertyRoomRatePriceGrouped[1];
                    }
                }
                //Kanalın müsaitlik type ına göre kullanılacak olanların seçilmesi


                if (empty($selectedPropertyRoomRatePriceGrouped)) {
                    //Hiç fiyat çekilememiş ise diğer proprty ye geç
                    continue;
                }


                //TODO: burada her istenen oda tipi için fiyat hesaplanacak ve
                $calculatedRoomPrice = [];

                // Availability Type - Property Room - Room Rate Mapping
                foreach ($selectedPropertyRoomRatePriceGrouped as $propertyAvailabilityKey => $propertyAvailability) {
                    foreach ($propertyAvailability as $propertyRoomKey => $propertyRoom) {

                        //Olmayan bir oda için fiyat gelirse devam et
                        if (!in_array($propertyRoomKey, array_keys($propertyRoomAndRoomRateMappingData['room']))) {
                            continue;
                        }

                        foreach ($propertyRoom as $propertyRoomRateKey => $propertyRoomRate) {

                            $roomsByOccupancyPrices = [];
                            foreach ($this->roomsByOccupancies as $roomsByOccupancyKey => $roomsByOccupancy) {


                                if ($roomsByOccupancy['adultCount'] > $propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey]['max_adult']) {
                                    //Bu oda için istenen yetişkin sayısı kadar kapasite yok
                                    continue;
                                }

                                if ($roomsByOccupancy['childCount'] > $propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey]['max_child']) {
                                    //Bu oda için istenen çocuk sayısı kadar kapasite yok
                                    continue;
                                }

                                if ($roomsByOccupancy['occupancy'] > $propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey]['max_occupancy']) {
                                    //Bu oda için istenen misafir sayısı kadar kapasite yok
                                    continue;
                                }

                                if (isset($roomsByOccupancy['childAges']) && !is_null($propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey]['max_child_number'])) {
                                    foreach ($roomsByOccupancy['childAges'] as $childAge) {
                                        if ($childAge > $propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey]['max_child_number']) {
                                            continue 2;
                                        }
                                    }
                                }


                                $roomRateExcludeOccupancy = !is_null($propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey]['exclude_occupancy']) ? json_decode($propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey]['exclude_occupancy'], 1) : [];

                                if (in_array($roomsByOccupancy['occupancyCode'], $roomRateExcludeOccupancy)) {
                                    //Bu odada istenmeyen bir occupancy grubu olduğu için kullanılmıyor
                                    continue;
                                }


                                if (!isset($propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey])) {
                                    //Mapping olmayan bir rate gelirse devam et
                                    continue 2;
                                }

                                if ($propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['property_room']['occupancy_lock']) {
                                    if ($propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['included_occupancy'] != $roomsByOccupancy['adultCount']) {
                                        //Occupancy Lock Durumu
                                        continue 1;
                                    }
                                }


                                //Fiyatlama kısmı baş
                                $propertyRoomAndRoomRateAvailability = collect($getPropertyRoomAndRoomRateAvailability['data']);

                                $roomRateDaily = [];
                                foreach ($propertyRoomRate as $dailyKey => $dailyRoomRate) {

                                    //Pool için genel kontenjan
                                    if ($propertyAvailabilityKey == 1) {
                                        $roomAndRoomRateAvailability = $propertyRoomAndRoomRateAvailability
                                            ->where('date', $dailyRoomRate['date'])
                                            ->where('property_room_id', $dailyRoomRate['property_room_id'])
                                            ->where('availability_type_id', $dailyRoomRate['availability_type_id'])
                                            ->where('status', 1)
                                            ->first();

                                    } else {
                                        $roomAndRoomRateAvailability = $propertyRoomAndRoomRateAvailability
                                            ->where('date', $dailyRoomRate['date'])
                                            ->where('property_room_id', $dailyRoomRate['property_room_id'])
                                            ->where('availability_type_id', $dailyRoomRate['availability_type_id'])
                                            ->where('room_rate_mapping_id', $dailyRoomRate['room_rate_mapping_id'])
                                            ->where('channel_id', $channelProperty['channel_id'])
                                            ->where('status', 1)
                                            ->first();
                                    }


                                    if ($channelProperty['channel_room_pricing_type']['code'] == 'ROM') {

                                        $dailyRoomRateRackPrice = $dailyRoomRate['amount'];
                                        $propertyRoomRateIncludedOccupancy = $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['included_occupancy'];
                                        $oneAdultRoomRateRackPrice = $dailyRoomRateRackPrice / $propertyRoomRateIncludedOccupancy;

                                        //NEW Promotoin Affect
                                        $dailyDetailPromoCheckKey = $dailyRoomRate['property_id'] . '-' .
                                            $dailyRoomRate['room_rate_mapping_id'] . '-' .
                                            $dailyRoomRate['channel_id'] . '-' .
                                            Carbon::parse($dailyKey)->format('Ymd');

                                        if (array_key_exists($dailyDetailPromoCheckKey, $promotionGroupByDay)) {
                                            $dailyRoomRate['discountRate'] = $promotionGroupByDay[$dailyDetailPromoCheckKey]['discountRate'];
                                            $dailyRoomRateRackPrice = moneyDoubleFormatDecimal($dailyRoomRateRackPrice - ($dailyRoomRateRackPrice * ($promotionGroupByDay[$dailyDetailPromoCheckKey]['discountRate'] / 100)));
                                        }
                                        //NEW Promotoin Affect

                                        $roomRateDaily[$dailyKey] = [
                                            'date' => $dailyKey,
                                            'amount' => $dailyRoomRateRackPrice,
                                            'allotment' => fillOnUndefined($roomAndRoomRateAvailability, 'availability', 0),
                                            'rackRateAmount' => $dailyRoomRateRackPrice,
                                            'rackRateBaseAmount' => $dailyRoomRate['baseAmount'],
                                            'discountRate' => $dailyRoomRate['discountRate'],
                                            'oneAdultRackRateAmount' => $oneAdultRoomRateRackPrice,
                                            'min_stay' => $dailyRoomRate['min_stay']
                                        ];

                                    } elseif ($channelProperty['channel_room_pricing_type']['code'] == 'PRS') {

                                        $roomPrice = 0;
                                        $adultPrice = 0;
                                        $childPrice = 0;

                                        $dailyRoomRateRackPrice = $dailyRoomRate['amount'];
                                        $propertyRoomRateIncludedOccupancy = $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['included_occupancy'];
                                        $oneAdultRoomRateRackPrice = $dailyRoomRateRackPrice / $propertyRoomRateIncludedOccupancy;

                                        //ADULT, CHILD POLICIES
                                        $roomRateMappingAdultPolicy = $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['roomRateMappingAdultPolicy'];
                                        $roomRateMappingChildPolicy = $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['roomRateMappingChildPolicy'];


                                        //ADULT PRICE
                                        $adultPrice = $dailyRoomRateRackPrice;

                                        if (!empty($roomRateMappingAdultPolicy)) {

                                            $roomRateMappingAdultPolicyCollect = collect($roomRateMappingAdultPolicy);

                                            $roomOccupancyAdultActionType = null;
                                            $roomOccupancyAdultActionDiff = null;
                                            if ($roomsByOccupancy['adultCount'] > $propertyRoomRateIncludedOccupancy) {
                                                $roomOccupancyAdultActionType = 'INC';
                                                $roomOccupancyAdultActionDiff = $roomsByOccupancy['adultCount'] - $propertyRoomRateIncludedOccupancy;
                                                $roomOccupancyAdultActionDiff = ceil($roomOccupancyAdultActionDiff);
                                            } elseif ($roomsByOccupancy['adultCount'] < $propertyRoomRateIncludedOccupancy) {
                                                $roomOccupancyAdultActionType = 'DEC';
                                                $roomOccupancyAdultActionDiff = $propertyRoomRateIncludedOccupancy - $roomsByOccupancy['adultCount'];
                                                $roomOccupancyAdultActionDiff = floor($roomOccupancyAdultActionDiff);
                                            }

                                            if (!is_null($roomOccupancyAdultActionType)) {

                                                $roomOccupancyAdultPolicy = $roomRateMappingAdultPolicyCollect
                                                    ->where('adult_action_type', $roomOccupancyAdultActionType)
                                                    ->where('adult', $roomOccupancyAdultActionDiff)
                                                    ->where('reservation_start_date', null)
                                                    ->where('reservation_end_date', null)
                                                    ->sortByDesc('id')
                                                    ->first();

                                                $roomOccupancyAdultPolicyDate = $roomRateMappingAdultPolicyCollect
                                                    ->where('adult_action_type', $roomOccupancyAdultActionType)
                                                    ->where('adult', $roomOccupancyAdultActionDiff)
                                                    ->where('reservation_start_date', '<=', $dailyKey)
                                                    ->where('reservation_end_date', '>=', $dailyKey)
                                                    ->sortByDesc('id')
                                                    ->first();

                                                if ($roomOccupancyAdultPolicyDate) {
                                                    $roomOccupancyAdultPolicy = $roomOccupancyAdultPolicyDate;
                                                }


                                                if (!empty($roomOccupancyAdultPolicy)) {

                                                    if ($roomOccupancyAdultPolicy['type'] == 'PER') {
                                                        $roomOccupancyAdultActionDiffAffected = ($dailyRoomRateRackPrice * $roomOccupancyAdultPolicy['value']) / 100;
                                                    } elseif ($roomOccupancyAdultPolicy['type'] == 'FIX') {
                                                        $roomOccupancyAdultActionDiffAffected = $roomOccupancyAdultPolicy['value'];
                                                    }

                                                    if ($roomOccupancyAdultPolicy['action_type'] == 'INC') {
                                                        $adultPrice = $dailyRoomRateRackPrice + $roomOccupancyAdultActionDiffAffected;
                                                    }

                                                    if ($roomOccupancyAdultPolicy['action_type'] == 'DEC') {
                                                        $adultPrice = $dailyRoomRateRackPrice - $roomOccupancyAdultActionDiffAffected;
                                                    }

                                                }


                                            }


                                        }


                                        //dd($adultPrice);


                                        if ($adultPrice <= 0) {
                                            //Eğer günlük fiyat 0 ya da - ye düşerse bu rate için hesaplama yapmayacak
                                            continue 2;
                                        }

                                        //CHILD PRICE
                                        $childPriceRaw = [];
                                        $roomRateMappingChildPolicyCollect = collect($roomRateMappingChildPolicy);

                                        //dd($roomRateMappingChildPolicyCollect);

                                        $childOrder = 1;
                                        for ($i = 0; $i < $roomsByOccupancy['childCount']; $i++) {

                                            $childPriceRaw[$i] = $oneAdultRoomRateRackPrice;


                                            if (!empty($roomRateMappingChildPolicy)) {

                                                $childAgePolicyAffected = $oneAdultRoomRateRackPrice;

                                                $childAgePolicy = $roomRateMappingChildPolicyCollect
                                                    ->where('adult', 0)
                                                    ->where('child_order', $childOrder)
                                                    ->where('child_age_start', '<=', $roomsByOccupancy['childAges'][$i])
                                                    ->where('child_age_end', '>', $roomsByOccupancy['childAges'][$i])
                                                    ->where('reservation_start_date', null)
                                                    ->where('reservation_end_date', null)
                                                    ->sortByDesc('id')
                                                    ->first();

                                                $childAgePolicyPeriod = $roomRateMappingChildPolicyCollect
                                                    ->where('adult', 0)
                                                    ->where('child_order', $childOrder)
                                                    ->where('child_age_start', '<=', $roomsByOccupancy['childAges'][$i])
                                                    ->where('child_age_end', '>', $roomsByOccupancy['childAges'][$i])
                                                    ->where('reservation_start_date', '<=', $dailyKey)
                                                    ->where('reservation_end_date', '>=', $dailyKey)
                                                    ->sortByDesc('id')
                                                    ->first();

                                                if ($childAgePolicyPeriod) {
                                                    $childAgePolicy = $childAgePolicyPeriod;
                                                }

                                                $childAgePolicyAdult = $roomRateMappingChildPolicyCollect
                                                    ->where('adult', $roomsByOccupancy['adultCount'])
                                                    ->where('child_order', $childOrder)
                                                    ->where('child_age_start', '<=', $roomsByOccupancy['childAges'][$i])
                                                    ->where('child_age_end', '>', $roomsByOccupancy['childAges'][$i])
                                                    ->where('reservation_start_date', null)
                                                    ->where('reservation_end_date', null)
                                                    ->sortByDesc('id')
                                                    ->first();

                                                if ($childAgePolicyAdult) {
                                                    $childAgePolicy = $childAgePolicyAdult;
                                                }

                                                $childAgePolicyDate = $roomRateMappingChildPolicyCollect
                                                    ->where('adult', $roomsByOccupancy['adultCount'])
                                                    ->where('child_order', $childOrder)
                                                    ->where('child_age_start', '<=', $roomsByOccupancy['childAges'][$i])
                                                    ->where('child_age_end', '>', $roomsByOccupancy['childAges'][$i])
                                                    ->where('reservation_start_date', '<=', $dailyKey)
                                                    ->where('reservation_end_date', '>=', $dailyKey)
                                                    ->sortByDesc('id')
                                                    ->first();

                                                if ($childAgePolicyDate) {
                                                    $childAgePolicy = $childAgePolicyDate;
                                                }

                                                if (!empty($childAgePolicy)) {
                                                    if ($childAgePolicy['type'] == 'PER') {
                                                        $childAgePolicyAffected = ($oneAdultRoomRateRackPrice * $childAgePolicy['value']) / 100;
                                                    } elseif ($childAgePolicy['type'] == 'FIX') {
                                                        $childAgePolicyAffected = $childAgePolicy['value'];
                                                    }

                                                    $childOrder++;
                                                }

                                                $childPriceRaw[$i] = $childAgePolicyAffected;

                                            }


                                        }


                                        $childPrice = array_sum($childPriceRaw);

                                        $roomPrice = $adultPrice + $childPrice;


                                        //NEW Promotoin Affect
                                        $dailyDetailPromoCheckKey = $dailyRoomRate['property_id'] . '-' .
                                            $dailyRoomRate['room_rate_mapping_id'] . '-' .
                                            $dailyRoomRate['channel_id'] . '-' .
                                            Carbon::parse($dailyKey)->format('Ymd');

                                        if (array_key_exists($dailyDetailPromoCheckKey, $promotionGroupByDay)) {
                                            $dailyRoomRate['discountRate'] = $promotionGroupByDay[$dailyDetailPromoCheckKey]['discountRate'];
                                            $roomPrice = moneyDoubleFormatDecimal($roomPrice - ($roomPrice * ($promotionGroupByDay[$dailyDetailPromoCheckKey]['discountRate'] / 100)));
                                        }
                                        //NEW Promotoin Affect


                                        $roomRateDaily[$dailyKey] = [
                                            'date' => $dailyKey,
                                            'amount' => $roomPrice,
                                            'allotment' => fillOnUndefined($roomAndRoomRateAvailability, 'availability', 0),
                                            'rackRateAmount' => $dailyRoomRateRackPrice,
                                            'rackRateBaseAmount' => $dailyRoomRate['baseAmount'],
                                            'discountRate' => $dailyRoomRate['discountRate'],
                                            'oneAdultRackRateAmount' => $oneAdultRoomRateRackPrice,
                                            'min_stay' => $dailyRoomRate['min_stay']
                                        ];

                                    }

                                }


                                //Eğer günlere ait kontenjanlardan olmadığı bir gün gelir ise
                                $dailyRoomRateAvailabilityCheck = collect($roomRateDaily)->where('allotment', '<=', '0')->toArray();
                                if (!empty($dailyRoomRateAvailabilityCheck)) {
                                    continue;
                                }

                                //Günler için de minimum doluluk oranına göre müsaitliğin alınması
                                $dailyRoomRateAvailabilityMin = collect($roomRateDaily)->sortBy('allotment')->first();
                                $dailyRoomRateAllotment = $dailyRoomRateAvailabilityMin['allotment'];


                                //POLICY PRICES
                                $baseTotalPrice = array_sum(array_column($roomRateDaily, 'amount'));
                                $dailyAverageDiscount = floatval(array_sum(array_column($roomRateDaily, 'discountRate')) / count($roomRateDaily));
                                $roomRateMappingCancellationPolicy = $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['roomRateMappingCancellationPolicy'];

                                if (!empty($roomRateMappingCancellationPolicy)) {
                                    foreach ($roomRateMappingCancellationPolicy as $roomRateMappingCancellationPolicyKey => $roomRateMappingCancellationPolicyValue) {
                                        //Do not take into account if the number of rule days is greater than the remaining days.
                                        /*if ($roomRateMappingCancellationPolicyValue['beforeArrivalDay'] > $daysLeftForCheckin && $roomRateMappingCancellationPolicyValue['isNonRefundable'] == 0) {
                                            unset($roomRateMappingCancellationPolicy[$roomRateMappingCancellationPolicyKey]);
                                        }*/

                                        if ($roomRateMappingCancellationPolicyValue['is_date_range']) {

                                            $isDateInCancellationPolicyRange = false;
                                            foreach ($this->dateByDay as $date) {
                                                if ($date >= $roomRateMappingCancellationPolicyValue['start_date'] && $date <= $roomRateMappingCancellationPolicyValue['finish_date']) {
                                                    $isDateInCancellationPolicyRange = true;
                                                    break;
                                                }
                                            }

                                            if (!$isDateInCancellationPolicyRange) {
                                                unset($roomRateMappingCancellationPolicy[$roomRateMappingCancellationPolicyKey]);
                                            }
                                        }

                                    }
                                }

                                if (empty($roomRateMappingCancellationPolicy)) {
                                    $roomRateMappingCancellationPolicy[] = [
                                        'isAffectedPrice' => false,
                                        'isFreeCancellation' => true,
                                        'isNonRefundable' => false
                                    ];
                                }

                                //Wholesalers can only use CHN payment type
                                if (in_array($channelProperty['channel']['channel_category_id'], [7])) {

                                    if (empty($channelBookingPaymentTypePolicy)) {
                                        $channelBookingPaymentTypePolicy[2] = [
                                            'name' => 'Channel Manager',
                                            'code' => 'CHN',
                                            'isAffectedPrice' => false
                                        ];
                                    }

                                } else {

                                    if (empty($channelBookingPaymentTypePolicy)) {
                                        $channelBookingPaymentTypePolicy[2] = [
                                            'name' => 'Pay at Hotel',
                                            'code' => 'HTL',
                                            'isAffectedPrice' => false
                                        ];
                                    }

                                }


                                //dd($roomRateMappingCancellationPolicy, $channelBookingPaymentTypePolicy);

                                $policyPrices = [];
                                foreach ($roomRateMappingCancellationPolicy as $roomRateMappingCancellationPolicyKey => $roomRateMappingCancellationPolicy) {
                                    foreach ($channelBookingPaymentTypePolicy as $channelBookingPaymentTypeKey => $channelBookingPaymentType) {

                                        //dd($channelBookingPaymentType['cancellationPolicy'], $roomRateMappingCancellationPolicyKey);


                                        if (!empty($channelBookingPaymentType['cancellationPolicy'])) {
                                            if (!in_array($roomRateMappingCancellationPolicyKey, $channelBookingPaymentType['cancellationPolicy'])) {
                                                continue;
                                            }
                                        }


                                        $cancellationPolicyAffectPrice = 0;
                                        if ($roomRateMappingCancellationPolicy['isAffectedPrice']) {

                                            if ($roomRateMappingCancellationPolicy['affectPriceType'] == 'PER') {
                                                $cancellationPolicyAffectPrice = ($baseTotalPrice * $roomRateMappingCancellationPolicy['affectPriceValue']) / 100;
                                            } elseif ($roomRateMappingCancellationPolicy['affectPriceType'] == 'FIX') {
                                                $cancellationPolicyAffectPrice = $roomRateMappingCancellationPolicy['affectPriceValue'];
                                            }

                                            $cancellationPolicyAffectPrice = $roomRateMappingCancellationPolicy['affectPriceActionType'] == 'DEC' ? (-1 * $cancellationPolicyAffectPrice) : $cancellationPolicyAffectPrice;

                                        }

                                        $cancellationPolicyAffectPriceName = fillOnUndefined($roomRateMappingCancellationPolicy, 'name');
                                        if ($roomRateMappingCancellationPolicy['isNonRefundable']) {
                                            $cancellationPolicyAffectPriceName = 'NonRefundable';
                                        } elseif ($roomRateMappingCancellationPolicy['isFreeCancellation']) {
                                            $cancellationPolicyAffectPriceName = 'FreeCancellation';
                                        }

                                        $bookingPaymentTypeAffectPrice = 0;
                                        if ($channelBookingPaymentType['isAffectedPrice']) {

                                            if ($channelBookingPaymentType['affectPriceType'] == 'PER') {
                                                $bookingPaymentTypeAffectPrice = ($baseTotalPrice * $channelBookingPaymentType['affectPriceValue']) / 100;
                                            } elseif ($channelBookingPaymentType['affectPriceType'] == 'FIX') {
                                                $bookingPaymentTypeAffectPrice = $channelBookingPaymentType['affectPriceValue'];
                                            }

                                            $bookingPaymentTypeAffectPrice = $channelBookingPaymentType['affectPriceActionType'] == 'DEC' ? (-1 * $bookingPaymentTypeAffectPrice) : $bookingPaymentTypeAffectPrice;

                                        }

                                        $bookingPaymentTypeAffectPriceName = fillOnUndefined($channelBookingPaymentType, 'name');


                                        //Bu dataları 10dk lık cache de tutacaksın, search_id ve $policyPriceKeyHashed bazında
                                        $policyPriceKey = $channelProperty['property_id'] . '-' . $channelProperty['channel_id'] . '-' . $propertyAvailabilityKey . '-' . $propertyRoomKey . '-' . $propertyRoomRateKey . '-' . $roomsByOccupancyKey . '-' . Carbon::parse($params['date']['checkIn'])->format('Ymd') . '-' . Carbon::parse($params['date']['checkOut'])->format('Ymd') . '-' . $roomRateMappingCancellationPolicyKey . '-' . $channelBookingPaymentTypeKey;
                                        $policyPriceKeyHashed = md5($policyPriceKey);
                                        $policyPriceTotal = $baseTotalPrice + $cancellationPolicyAffectPrice + $bookingPaymentTypeAffectPrice;

                                        $policyPriceDaily = [];
                                        $policyPriceRate = ($policyPriceTotal / $baseTotalPrice);

                                        foreach ($roomRateDaily as $daily) {
                                            $policyPriceDaily[] = [
                                                'date' => $daily['date'],
                                                'amount' => moneyDoubleFormatDecimal($daily['amount'] * $policyPriceRate),
                                                'currency_code' => $channelProperty['currency_code'],
                                                'min_stay' => fillOnUndefined($daily, 'min_stay', 0),
                                            ];
                                        }

                                        $policyPrices[$policyPriceKeyHashed] = [
                                            'rateKey' => $policyPriceKeyHashed,
                                            'rateKeyCode' => $policyPriceKey,
                                            'occupancyCode' => $roomsByOccupancyKey,
                                            'name' => $cancellationPolicyAffectPriceName . ' - ' . $bookingPaymentTypeAffectPriceName,
                                            'total' => moneyDoubleFormatDecimal($policyPriceTotal),
                                            'currency' => $channelProperty['currency_code'],
                                            'availability' => [
                                                'name' => __($channelAvailabilityType[$propertyAvailabilityKey][0]['language_key']),
                                                'code' => $channelAvailabilityType[$propertyAvailabilityKey][0]['code'],
                                            ],
                                            'room' => [
                                                'name' => $propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey]['name'],
                                                'type' => __($propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey]['property_room_type']['language_key']),
                                                'allotment' => ($propertyAvailabilityKey == 1) ? $dailyRoomRateAllotment : null,
                                            ],
                                            'rate' => [
                                                'name' => $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['property_room_rate']['name'],
                                                'boardCode' => $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['property_room_rate']['id'],
                                                'boardName' => __($propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['property_room_rate']['property_room_rate_accommodation']['language_key']),
                                                'accommodationCode' => $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['property_room_rate']['property_room_rate_accommodation']['id'],
                                                'allotment' => ($propertyAvailabilityKey != 1) ? $dailyRoomRateAllotment : null,
                                            ],
                                            'cancellationPolicy' => $roomRateMappingCancellationPolicy,
                                            'bookingPaymentType' => $channelBookingPaymentType,
                                            'policyPriceRate' => $policyPriceRate,
                                            'policyPriceDaily' => $policyPriceDaily,
                                        ];

                                        //Add to Cache
                                        $searchPricesCacheWithKey['requestParams'] = $params;
                                        $searchPricesCacheWithKey['roomPrices'][$policyPriceKeyHashed] = $policyPrices[$policyPriceKeyHashed];

                                    }

                                }

                                $policyPrices = collect($policyPrices)->sortBy('total')->toArray();
                                //POLICY PRICES

                                $dailyCalculatedPrices = [
                                    'prices' => $policyPrices,
                                    'baseTotalPrice' => $baseTotalPrice,
                                    'dailyAverageDiscount' => number_format($dailyAverageDiscount, 0, '', ''),
                                    'allotment' => $dailyRoomRateAllotment,
                                    'room' => [
                                        'adults' => $roomsByOccupancy['adultCount'],
                                        'children' => $roomsByOccupancy['childCount'],
                                        'childAges' => $roomsByOccupancy['childAges'],
                                    ],
                                    'daily' => $roomRateDaily,
                                ];

                                $calculatedRoomPrice
                                [$propertyAvailabilityKey]
                                [$propertyRoomKey]
                                [$propertyRoomRateKey]
                                [$roomsByOccupancyKey] = $dailyCalculatedPrices;

                                //Fiyatlama kısmı son


                            }

                            //dd($roomsByOccupancy, $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['included_occupancy']);

                        }
                    }
                }


                //TODO: Burayı taşıyabilirz'));
                foreach ($calculatedRoomPrice as $propertyAvailabilityKey => $propertyAvailability) {

                    $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['name'] = $channelProperty['property']['name'];
                    $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['currency'] = $channelProperty['currency_code'];
                    $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['token'] = $channelProperty['token'];
                    $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['booking_engine_token'] = $channelProperty['property']['property_booking_engine_token']['token'];
                    $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['credit_card_required'] = $payAtHotelCreditCardCheck;



                    //Wholesaler Currency SET
                    if (!empty($channelPropertyMarkup)) {
                        $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['currency'] = $channelPropertyMarkup['currency_code'];
                    }
                    //Wholesaler Currency SET


                    //$calculatedRoomPriceFormatted[$channelProperty['property']['id']]['paymentType'] = $channelProperty['channel_booking_payment_type'];

                    $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['name'] = __($channelAvailabilityType[$propertyAvailabilityKey][0]['language_key']);
                    $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['code'] = $channelAvailabilityType[$propertyAvailabilityKey][0]['code'];


                    //En düşük fiyata göre sıralama
                    $propertyAvailability = collect($propertyAvailability);
                    $propertyAvailabilitySorted = $propertyAvailability->sortBy(function ($room, $roomKey) {
                        $firstRate = reset($room);
                        $firstRateOccupancy = reset($firstRate);
                        return $firstRateOccupancy['baseTotalPrice'];
                    });

                    $propertyAvailability = $propertyAvailabilitySorted->toArray();


                    foreach ($propertyAvailability as $propertyRoomKey => $propertyRoom) {

                        $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['name'] = $propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey]['name'];
                        $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['type'] = __($propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey]['property_room_type']['language_key']);

                        $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['attributes'] = fillOnUndefined($propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey], 'attributes', []);
                        $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['bedGroups'] = fillOnUndefined($propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey], 'bedGroups', []);
                        $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['photos'] = fillOnUndefined($propertyRoomAndRoomRateMappingData['room'][$propertyRoomKey], 'photos', []);

                        //Wholesaler
                        if (in_array($channelProperty['channel']['channel_category_id'], [7]) && empty($this->bookingEngineToken) || fillOnUndefined($params, 'justPriceValues')) {
                            unset($calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['attributes']);
                            unset($calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['bedGroups']);
                            unset($calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['photos']);
                        }

                        foreach ($propertyRoom as $propertyRoomRateKey => $propertyRoomRate) {


                            if ($propertyAvailabilityKey == 1) {
                                $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['allotment'] = reset($propertyRoomRate)['allotment'];
                            }

                            $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['rates'][$propertyRoomRateKey]['name'] = $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['property_room_rate']['name'];
                            $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['rates'][$propertyRoomRateKey]['boardCode'] = $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['property_room_rate']['property_room_rate_accommodation']['id'];
                            $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['rates'][$propertyRoomRateKey]['boardName'] = __($propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['property_room_rate']['property_room_rate_accommodation']['language_key']);
                            $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['rates'][$propertyRoomRateKey]['rateDescription'] = isset($propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['property_room_rate']['descriptionArray'][$this->language]) ? $propertyRoomAndRoomRateMappingData['roomRateMapping'][$propertyRoomRateKey]['property_room_rate']['descriptionArray'][$this->language]: null;

                            if ($propertyAvailabilityKey != 1) {
                                $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['rates'][$propertyRoomRateKey]['allotment'] = reset($propertyRoomRate)['allotment'];
                            }

                            foreach ($propertyRoomRate as $propertyRoomOccupancyKey => $propertyRoomOccupancy) {

                                $propertyRoomOccupancy['baseTotalPrice'] = moneyDoubleFormatDecimal($propertyRoomOccupancy['baseTotalPrice']);
                                foreach ($propertyRoomOccupancy['daily'] as $dailyKey => $daily) {
                                    $propertyRoomOccupancy['daily'][$dailyKey]['amount'] = moneyDoubleFormatDecimal($daily['amount']);
                                    $propertyRoomOccupancy['daily'][$dailyKey]['rackRateAmount'] = moneyDoubleFormatDecimal($daily['rackRateAmount']);
                                    $propertyRoomOccupancy['daily'][$dailyKey]['oneAdultRackRateAmount'] = moneyDoubleFormatDecimal($daily['oneAdultRackRateAmount']);
                                }


                                //Wholesaler MARKUP CALCULATE
                                if (!empty($channelPropertyMarkup)) {

                                    foreach ($propertyRoomOccupancy['prices'] as $rateKey => $propertyRoomOccupancyPrice) {

                                        $currency = $channelPropertyMarkup['currency_code'];
                                        $propertyRoomOccupancy['prices'][$rateKey]['currency'] = $currency;

                                        foreach ($propertyRoomOccupancyPrice['policyPriceDaily'] as $policyPriceDailyKey => $policyPriceDaily) {

                                            $policyPriceDailyAmount = moneyDoubleFormatDecimal($policyPriceDaily['amount'] * $channelPropertyMarkup['markup'] * $channelPropertyMarkup['exchange']);

                                            $propertyRoomOccupancy['prices'][$rateKey]['policyPriceDaily'][$policyPriceDailyKey]['amount'] = $policyPriceDailyAmount;
                                            $propertyRoomOccupancy['prices'][$rateKey]['policyPriceDaily'][$policyPriceDailyKey]['currency_code'] = $currency;

                                        }

                                        $propertyRoomOccupancy['prices'][$rateKey]['total'] = collect($propertyRoomOccupancy['prices'][$rateKey]['policyPriceDaily'])->sum('amount');
                                        $propertyRoomOccupancy['prices'][$rateKey]['total'] = moneyDoubleFormatDecimal($propertyRoomOccupancy['prices'][$rateKey]['total']);


                                    }

                                    foreach ($propertyRoomOccupancy['daily'] as $propertyRoomOccupancyDateKey => $propertyRoomOccupancyDate) {

                                        $propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['amount'] = $propertyRoomOccupancyDate['amount'] * $channelPropertyMarkup['markup'];
                                        $propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['amount'] *= $channelPropertyMarkup['exchange'];
                                        $propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['amount'] = moneyDoubleFormatDecimal($propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['amount']);

                                        $propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['rackRateAmount'] = $propertyRoomOccupancyDate['rackRateAmount'] * $channelPropertyMarkup['markup'];
                                        $propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['rackRateAmount'] *= $channelPropertyMarkup['exchange'];
                                        $propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['rackRateAmount'] = moneyDoubleFormatDecimal($propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['rackRateAmount']);

                                        $propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['rackRateBaseAmount'] = $propertyRoomOccupancyDate['rackRateBaseAmount'] * $channelPropertyMarkup['markup'];
                                        $propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['rackRateBaseAmount'] *= $channelPropertyMarkup['exchange'];
                                        $propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['rackRateBaseAmount'] = moneyDoubleFormatDecimal($propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['rackRateBaseAmount']);


                                        $propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['oneAdultRackRateAmount'] = $propertyRoomOccupancyDate['oneAdultRackRateAmount'] * $channelPropertyMarkup['markup'];
                                        $propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['oneAdultRackRateAmount'] *= $channelPropertyMarkup['exchange'];
                                        $propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['oneAdultRackRateAmount'] = moneyDoubleFormatDecimal($propertyRoomOccupancy['daily'][$propertyRoomOccupancyDateKey]['oneAdultRackRateAmount']);

                                    }

                                    $propertyRoomOccupancy['baseTotalPrice'] = collect($propertyRoomOccupancy['daily'])->sum('amount');
                                    $propertyRoomOccupancy['baseTotalPrice'] = moneyDoubleFormatDecimal($propertyRoomOccupancy['baseTotalPrice']);

                                }
                                //Wholesaler MARKUP CALCULATE

                                $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['availabilities'][$propertyAvailabilityKey]['rooms'][$propertyRoomKey]['rates'][$propertyRoomRateKey]['requestedRoomPrice'][$propertyRoomOccupancyKey] = $propertyRoomOccupancy;

                            }
                        }
                    }
                }


                //ADDON Setup
                if (!empty($calculatedRoomPriceFormatted)) {
                    $propertyChannelAddonCriteria = [
                        'criteria' => [
                            ['field' => 'property_id', 'condition' => '=', 'value' => $channelProperty['property_id']],
                            ['field' => 'channel_id', 'condition' => '=', 'value' => $channelProperty['channel_id']],
                            ['field' => 'status', 'condition' => '=', 'value' => 1],
                        ],
                        'with' => ['propertyAddon.fact']
                    ];
                    $columns = ['id', 'property_id', 'channel_id', 'property_addon_id', 'amount', 'type', 'title', 'description', 'min_stay'];
                    $selectPropertyChannelAddon = $this->propertyAddonService->selectPropertyChannelAddon($propertyChannelAddonCriteria, $columns);

                    $nightOfStay = Carbon::parse($params['date']['checkIn'])->diff(Carbon::parse($params['date']['checkOut']))->days;

                    $propertyChannelAddon = [];
                    if ($selectPropertyChannelAddon['status'] == 'success') {
                        $propertyChannelAddon = $selectPropertyChannelAddon['data'];
                    }

                    $propertyChannelAddonList = [];
                    foreach ($propertyChannelAddon as $addon) {


                        if (!is_null($addon['min_stay']) && $addon['min_stay'] <= $nightOfStay) {
                            $addon['amount'] = 0;
                        }

                        $propertyChannelAddonList[$addon['property_addon_id']][] = [
                            'id' => $addon['id'],
                            'property_addon_id' => $addon['property_addon_id'],
                            'property_channel_addon_id' => $addon['id'],
                            'title' => $addon['title'],
                            'description' => $addon['description'],
                            'descriptionArray' => $addon['descriptionArray'],
                            'amount' => $addon['amount'],
                            'currency_code' => $channelProperty['currency_code'],
                            'name' => $addon['property_addon']['title'],
                            'language_key' => $addon['property_addon']['fact']['language_key'],
                            'icon' => $addon['property_addon']['fact']['icon'],
                            'attribute' => $addon['property_addon']['attribute'],
                            'attributeArray' => $addon['property_addon']['attributeArray'],
                            'type' => $addon['type'],
                            'count' => $addon['type'] == 'ONT' ? 1 : 10,
                            'min_stay' => $addon['min_stay'],
                        ];
                    }

                    $propertyChannelAddonList = array_values($propertyChannelAddonList);

                    $calculatedRoomPriceFormatted[$channelProperty['property']['id']]['addon'] = $propertyChannelAddonList;
                }
                //ADDON Setup


            }

            //Add Prices to Cache With SearchKey
            //If this parameter (noneCacheSearch) exists, it is not cached.
            if (!isset($params['noneCacheSearch'])) {
                $this->setCacheDataWithSearchKey($searchKey, $searchPricesCacheWithKey);
            }


            $ip = isset($params['ipAddress']) ? $params['ipAddress'] : config("app.myIP");
            $countryCodeWithIP = $this->findCountryCodeService->findCountryWithIpAddress($ip);

            $responseData = [
                'searchKey' => $searchKey,
                'properties' => $calculatedRoomPriceFormatted,
                'requestParams' => $params,
                'countryCodeWithIP' => isset($countryCodeWithIP['data']['code']) ? $countryCodeWithIP['data']['code'] : ''
            ];

            if (empty($calculatedRoomPriceFormatted) && (integer)$minStayCheckProperty > 1 && count($dateByDay) < (integer)$minStayCheckProperty) {
                throw new ApiErrorException(__('be-minstay-warning', ['minStay' => $minStayCheckProperty], $this->language), 201);
            }

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'errorCode' => null, 'data' => $responseData];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
            $response['statusCode'] = 400;
            $response['errorCode'] = $e->getCode();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            $response['statusCode'] = 500;
        }

        //201: be-minstay-warning

        //For Booking Engine
        if (isset($channelProperty['channel']['channel_category_id']) && in_array($channelProperty['channel']['channel_category_id'], [3, 7])) {

            $createSearchStatus = 0;
            if (isset($response['data']['properties'])) {
                $calculatedRoomPriceFormattedReset = reset($calculatedRoomPriceFormatted);
                if (isset($calculatedRoomPriceFormattedReset['name'])) {
                    $createSearchStatus = 1;
                }
            }

            $createSearchExcludeIps = ['127.0.0.1', '185.137.215.118'];
            if ((isset($params['ipAddress']) && !in_array($params['ipAddress'], $createSearchExcludeIps)) || in_array($channelProperty['channel_id'], [393])) {

                $isRobot = fillOnUndefined($params, 'isRobot');

                if (isset($params['noneCacheSearch'])) {
                    $isRobot = true;
                }

                if (!$isRobot) {

                    $createSearchParam = [
                        'search_key' => $searchKey,
                        'property_id' => fillOnUndefined($channelProperty, 'property_id'),
                        'channel_id' => fillOnUndefined($channelProperty, 'channel_id', 1),
                        'checkin_date' => $params['date']['checkIn'],
                        'checkout_date' => $params['date']['checkOut'],
                        'pax' => array_key_first($this->roomsByOccupancies),
                        'rooms' => json_encode($params['rooms']),
                        'booking_code' => fillOnUndefined($params, 'booking_code'),
                        'best_amount' => fillOnUndefined($params, 'best_amount'),
                        'currency_code' => fillOnUndefined($channelProperty, 'currency_code'),
                        'ip_address' => fillOnUndefined($params, 'ipAddress'),
                        'country_code' => isset($countryCodeWithIP['data']['code']) ? $countryCodeWithIP['data']['code'] : null,
                        'language_code' => $this->language,
                        'detail' => json_encode($params),
                        'referrer' => fillOnUndefined($params, 'referrer'),
                        'status' => $createSearchStatus,
                    ];

                    if (in_array($channelProperty['channel_id'], [393])) {
                        $createSearchParam['property_id'] = null;
                    }


                    $createSearch = $this->propertyBookingEngineSearchService->create($createSearchParam);
                }

            }

        }

        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode'], $response['errorCode']);


    }


    public function bestAvailableRate(Request $request)
    {

        $response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];

        try {

            $excludePropertyIds = [643,644,645,738,163,164,165,166,236,366];

            $this->channelToken = empty($this->channelToken) ? $request->header('channelToken') : $this->channelToken;
            $this->bookingEngineToken = empty($this->bookingEngineToken) ? $request->header('bookingEngineToken') : $this->bookingEngineToken;
            $this->channelId = empty($this->channelId) ? $request->header('channelId') : $this->channelId;
            $this->bookingEnginePropertyId = empty($this->bookingEnginePropertyId) ? $request->header('bookingEnginePropertyId') : $this->bookingEnginePropertyId;
            $this->language = empty($this->language) ? $request->header('language') : $this->language;

            $params = json_decode($request->getContent(), 1);

            $cacheKeyParam[] = $this->bookingEnginePropertyId;
            $cacheKeyParam[] = $params['period'];
            $cacheKey = 'CRR:' . md5(implode(',', $cacheKeyParam));

            if(in_array($this->bookingEnginePropertyId, $excludePropertyIds)) {
                throw new ApiErrorException('Property Channel not found');
            }

            //Cache::forget($cacheKey);
            if (Cache::has($cacheKey)) {
                $responseData = Cache::get($cacheKey);
            } else {

                $requestParam = [
                    'criteria' => [
                        ['field' => 'channel_id', 'condition' => '=', 'value' => $this->channelId],
                        ['field' => 'property_id', 'condition' => '=', 'value' => $this->bookingEnginePropertyId],
                        ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ],
                    'with' => ['currency'],
                    'firstRow' => true
                ];

                $getChannelProperty = $this->propertyChannelMappingService->select($requestParam);
                $getChannelProperty = $getChannelProperty['status'] == 'success' && !empty($getChannelProperty['data']) ? $getChannelProperty['data'] : null;

                if (!$getChannelProperty) {
                    throw new ApiErrorException('Property Channel not found');
                }

                $requestParam = [
                    'criteria' => [
                        ['field' => 'channel_id', 'condition' => '=', 'value' => 5],
                        ['field' => 'property_id', 'condition' => '=', 'value' => $this->bookingEnginePropertyId],
                        ['field' => 'stop_sell', 'condition' => '=', 'value' => 0],
                        ['field' => 'date', 'condition' => '>=', 'value' => Carbon::parse($params['period'])->format('Y-m-d')],
                        ['field' => 'date', 'condition' => '<', 'value' => Carbon::parse($params['period'])->addMonth()->format('Y-m-d')],
                        ['field' => 'amount', 'condition' => '<>', 'value' => null],
                        ['field' => 'amount', 'condition' => '<>', 'value' => 0],
                        ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ],
                    'with' => [
                        'roomRateMapping.propertyRoomRate'
                    ],
                    'orderBy' => [
                        ['field' => 'date', 'value' => 'ASC'],
                        ['field' => 'amount', 'value' => 'ASC']
                    ],
                ];

                $getPropertyRoomRatePrice = $this->propertyRoomRatePriceService->select($requestParam);


                if ($getPropertyRoomRatePrice['status'] != 'success' || empty($getPropertyRoomRatePrice['data'])) {
                    throw new ApiErrorException(lang('PropertyRoomRatePrice not found'));
                }

                $getPropertyRoomRatePrice = $getPropertyRoomRatePrice['status'] == 'success' && !empty($getPropertyRoomRatePrice['data']) ? $getPropertyRoomRatePrice['data'] : [];

                $firstDate = Carbon::parse($params['period'])->format('Y-m-d');
                $lastDate = Carbon::parse($params['period'])->addMonth()->format('Y-m-d');
                $dateDiff = Carbon::parse($firstDate)->diffInDays(Carbon::parse($lastDate));

                $rateAndAvailability = [];
                for ($i = 0; $i < $dateDiff; $i++) {
                    $date = Carbon::parse($firstDate)->addDays($i)->toDateString();

                    $bestPrice = collect($getPropertyRoomRatePrice)
                        ->where('date', $date)
                        ->where('room_rate_mapping.property_room_rate.name', 'Best Available Rate')
                        ->sortBy('amount')->first();
                    $bestPrice = $bestPrice ? $bestPrice['amount'] : null;

                    $rateAndAvailability[$date] = [
                        'rate' => round($bestPrice),
                        'available' => $bestPrice ? true : false,
                    ];

                }

                $responseData = [
                    'currency' => $getChannelProperty['currency']['code'],
                    'currency_icon' => $getChannelProperty['currency']['symbol'],
                    'date' => $rateAndAvailability
                ];

                if (count($rateAndAvailability) == collect($rateAndAvailability)->where('available', false)->count()) {
                    $responseData = null;
                }

                Cache::put($cacheKey, $responseData, 60 * 60);//1h 60 * 60

            }

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $responseData];

        } catch (ApiErrorException $e) {
            $response['message'] = implode(', ', $e->getMessageArr());
            $response['statusCode'] = 400;
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
            $response['statusCode'] = 500;
        }

        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);


    }


}
