<?php

namespace App\Core\Service;

use App\Core\Repository\PropertyRoom\PropertyRoomRepository;
use App\Core\Repository\PropertyChannelMapping\PropertyChannelMappingRepository;
use App\Core\Repository\PropertyRoomBed\PropertyRoomBedRepository;
use App\Core\Repository\PropertyRoomRatePrice\PropertyRoomRatePriceRepository;
use App\Core\Repository\Property\PropertyRepository;
use App\Core\Repository\PropertyRoomAvailability\PropertyRoomAvailabilityRepository;
use App\Core\Repository\PropertyRoomViewMapping\PropertyRoomViewMappingRepository;
use App\Core\Repository\PropertyRoomConnected\PropertyRoomConnectedRepository;
use App\Core\Service\PropertyRoomTypeService;
use App\Core\Validator\PropertyRoom\PropertyRoomAddValidator;
use App\Core\Validator\PropertyRoom\PropertyRoomAndBedAddValidator;
use App\Core\Validator\PropertyRoom\PropertyRoomUpdateValidator;
use App\Core\Validator\PropertyRoom\PropertyRoomDeleteValidator;
use App\Core\Validator\PropertyRoom\PropertyRoomInventoryValidator;
use App\Core\Validator\PropertyRoom\PropertyRoomAndBedUpdateValidator;
use App\Core\Service\LanguageService;
use App\Core\Repository\PropertyAvailabilityType\PropertyAvailabilityTypeRepository;


use App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
use Exception;
use App\Exceptions\ApiErrorException;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class PropertyRoomService
{

    private $propertyRoomRepository;
    private $propertyChannelMappingRepository;
    private $propertyRoomBedRepository;
    private $propertyRoomRatePriceRepository;
    private $propertyRoomAvailabilityRepository;
    private $propertyRoomAddValidator;
    private $propertyRoomUpdateValidator;
    private $propertyRoomDeleteValidator;
    private $propertyRoomAndBedAddValidator;
    private $propertyRoomInventoryValidator;
    private $propertyRepository;
    private $propertyRoomTypeService;
    private $propertyRoomViewMappingRepository;
    private $propertyRoomAndBedUpdateValidator;
    private $languageService;
    private $propertyAvailabilityTypeRepository;


    public function __construct(

        PropertyRoomRepository $propertyRoomRepository,
        LanguageService $languageService,
        PropertyChannelMappingRepository $propertyChannelMappingRepository,
        PropertyRoomBedRepository $propertyRoomBedRepository,
        PropertyRoomRatePriceRepository $propertyRoomRatePriceRepository,
        PropertyRoomAvailabilityRepository $propertyRoomAvailabilityRepository,
        PropertyRoomUpdateValidator $propertyRoomUpdateValidator,
        PropertyRoomDeleteValidator $propertyRoomDeleteValidator,
        PropertyRoomAddValidator $propertyRoomAddValidator,
        PropertyRoomInventoryValidator $propertyRoomInventoryValidator,
        PropertyRepository $propertyRepository,
        PropertyRoomAndBedAddValidator $propertyRoomAndBedAddValidator,
        PropertyRoomTypeService $propertyRoomTypeService,
        PropertyRoomViewMappingRepository $propertyRoomViewMappingRepository,
        PropertyRoomAndBedUpdateValidator $propertyRoomAndBedUpdateValidator,
        PropertyAvailabilityTypeRepository $propertyAvailabilityTypeRepository,
        PropertyRoomConnectedRepository $propertyRoomConnectedRepository
    )
    {

        $this->propertyRoomRepository = $propertyRoomRepository;
        $this->propertyChannelMappingRepository = $propertyChannelMappingRepository;
        $this->propertyRoomBedRepository = $propertyRoomBedRepository;
        $this->propertyRoomRatePriceRepository = $propertyRoomRatePriceRepository;
        $this->propertyRoomAvailabilityRepository = $propertyRoomAvailabilityRepository;
        $this->propertyRoomAddValidator = $propertyRoomAddValidator;
        $this->propertyRoomAndBedAddValidator = $propertyRoomAndBedAddValidator;
        $this->propertyRoomUpdateValidator = $propertyRoomUpdateValidator;
        $this->propertyRoomDeleteValidator = $propertyRoomDeleteValidator;
        $this->propertyRoomInventoryValidator = $propertyRoomInventoryValidator;
        $this->propertyRepository = $propertyRepository;
        $this->propertyRoomTypeService = $propertyRoomTypeService;
        $this->propertyRoomViewMappingRepository = $propertyRoomViewMappingRepository;
        $this->propertyRoomAndBedUpdateValidator = $propertyRoomAndBedUpdateValidator;
        $this->languageService = $languageService;
        $this->propertyAvailabilityTypeRepository = $propertyAvailabilityTypeRepository;
        $this->propertyRoomConnectedRepository = $propertyRoomConnectedRepository;


    }

    public function create($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $validationResult = $this->propertyRoomAddValidator->validate($params);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }
            $description = [];
            foreach (fillOnUndefined($params, "description", []) as $title) {
                $description[$title['language_code']] = $title['description'];
            }

            $insertData =
                [
                    'property_id' => fillOnUndefined($params, 'property_id'),
                    'name' => fillOnUndefined($params, 'name'),
                    'room_type_id' => fillOnUndefined($params, 'room_type_id'),
                    'max_occupancy' => fillOnUndefined($params, 'max_occupancy'),
                    'max_adult' => fillOnUndefined($params, 'max_adult'),
                    'max_child' => fillOnUndefined($params, 'max_child'),
                    'room_size' => fillOnUndefined($params, 'room_size'),
                    'room_size_type' => fillOnUndefined($params, 'room_size_type'),
                    'room_type_count' => fillOnUndefined($params, 'room_type_count', 1),
                    'room_count' => fillOnUndefined($params, 'room_count'),
                    'bathroom_count' => fillOnUndefined($params, 'bathroom_count'),
                    'toilet_count' => fillOnUndefined($params, 'toilet_count'),
                    'lounge_count' => fillOnUndefined($params, 'lounge_count'),
                    'max_child_number' => fillOnUndefined($params, 'max_child_number'),
                    'description' => json_encode($description),
                    "status" => fillOnUndefined($params, "status", 1),
                    "created_by" => fillOnUndefined($params, "created_by"),
                    "updated_by" => fillOnUndefined($params, "updated_by"),
                ];

            $userCreateResult = $this->propertyRoomRepository->create($insertData);

            if ($userCreateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $userData = $userCreateResult["data"];
            $response = [
                'status' => true,
                'data' => $userData,
            ];

        } 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 output($response);
    }

    public function select($param = [], $column = ['*'])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $data = $this->propertyRoomRepository->findByCriteria($param, $column);

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

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

        return output($response);
    }

    public function update($id, $param = [])
    {


        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {


            $updateResult = $this->propertyRoomRepository->update($id, $param);
            if ($updateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $updateData = $updateResult["data"];
            $response = [
                'status' => true,
                'data' => $updateData,
            ];

        } 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 output($response);
    }

    public function updateOrCreate($criteria = [], $saveData = [])
    {


        $response = ['status' => -1, 'message' => '', 'data' => null];

        try {

            $data = $this->propertyRoomRepository->updateOrCreate($criteria, $saveData);
            if ($data['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $response = [
                'status' => true,
                'data' => $data,
            ];

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

        return output($response);


    }

    public function addPropertyRoom($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $insertData =
                [
                    'property_id' => fillOnUndefined($params, 'property_id'),
                    'name' => fillOnUndefined($params, 'name'),
                    'room_type_id' => fillOnUndefined($params, 'room_type_id'),
                    'max_occupancy' => fillOnUndefined($params, 'max_occupancy'),
                    'max_adult' => fillOnUndefined($params, 'max_adult'),
                    'max_child' => fillOnUndefined($params, 'max_child'),
                    'occupancy_lock' => fillOnUndefined($params, 'occupancy_lock'),
                    'room_size' => fillOnUndefined($params, 'room_size'),
                    'room_size_type' => fillOnUndefined($params, 'room_size_type'),
                    'room_type_count' => fillOnUndefined($params, 'room_type_count', 1),
                    'room_count' => fillOnUndefined($params, 'room_count'),
                    'bathroom_count' => fillOnUndefined($params, 'bathroom_count'),
                    'toilet_count' => fillOnUndefined($params, 'toilet_count'),
                    'lounge_count' => fillOnUndefined($params, 'lounge_count'),
                    'max_child_number' => fillOnUndefined($params, 'max_child_number'),
                    'description' => fillOnUndefined($params, 'description'),
                    "status" => fillOnUndefined($params, "status", 1),
                    "created_by" => fillOnUndefined($params, "user_id"),
                    "updated_by" => fillOnUndefined($params, "user_id")
                ];

            $userCreateResult = $this->create($insertData);
            if ($userCreateResult['status'] != 'success') {
                throw new ApiErrorException($userCreateResult['message']);
            }
            $userData = $userCreateResult["data"];
            $response = [
                'status' => true,
                'data' => $userData,
            ];

        } 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 output($response);
    }

    public function getPropertyRooms($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $criteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['propertyRoomType', 'propertyRoomBedGroup.propertyRoomBedType']
            ];

            $data = $this->propertyRoomRepository->findByCriteria($criteria, ['id', 'name', 'room_type_id', 'max_occupancy', 'max_adult', 'max_child', 'room_size', 'room_size_type', 'room_type_count', 'room_count', 'bathroom_count', 'toilet_count', 'lounge_count', 'max_child_number']);

            $newRoomMapping = [];
            foreach ($data as $room) {
                $bedGroups = collect($room['property_room_bed_group'])->keyBy('bed_group')->keys();
                $group = [];
                foreach ($bedGroups as $bedGroup) {
                    $thisGroup = collect($room['property_room_bed_group'])->where('bed_group', '=', $bedGroup)->map(function ($bedItem) use ($bedGroup) {
                        $responseMapping = $bedItem;
                        $responseMapping['bed_type_name'] = $bedItem['property_room_bed_type']['name'];
                        unset($responseMapping['property_room_bed_type']);
                        return $responseMapping;
                    })->toArray();
                    $newItem = [];
                    foreach ($thisGroup as $item) {
                        $newItem[] = $item;
                    }
                    $group[] = $newItem;
                }
                $room['property_room_bed_group'] = $group;
                $newRoomMapping[] = $room;

            }

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

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

        return output($response);
    }

    public function updatePropertyRoom($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $validationResult = $this->propertyRoomUpdateValidator->validate($params);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $description = [];
            foreach (fillOnUndefined($params, "description", []) as $title) {
                $description[$title['language_code']] = $title['description'];
            }
            $updateData =
                [
                    'name' => fillOnUndefined($params, 'name'),
                    'room_type_id' => fillOnUndefined($params, 'room_type_id'),
                    'max_occupancy' => fillOnUndefined($params, 'max_occupancy'),
                    'max_adult' => fillOnUndefined($params, 'max_adult'),
                    'max_child' => fillOnUndefined($params, 'max_child'),
                    'occupancy_lock' => fillOnUndefined($params, 'occupancy_lock'),
                    'exclude_occupancy' => json_encode($params['exclude_occupancy'], true),
                    'room_size' => fillOnUndefined($params, 'room_size', null),
                    'room_size_type' => fillOnUndefined($params, 'room_size_type', null),
                    'room_type_count' => fillOnUndefined($params, 'room_type_count', 1),
                    'room_count' => fillOnUndefined($params, 'room_count', null),
                    'bathroom_count' => fillOnUndefined($params, 'bathroom_count', null),
                    'toilet_count' => fillOnUndefined($params, 'toilet_count', null),
                    'lounge_count' => fillOnUndefined($params, 'lounge_count', null),
                    'max_child_number' => fillOnUndefined($params, 'max_child_number', null),
                    'description' => json_encode($description),
                    "updated_by" => fillOnUndefined($params, "user_id")
                ];

            $updateResult = $this->update($params['id'], $updateData);
            if ($updateResult['status'] != 'success') {
                throw new ApiErrorException($updateResult['message']);
            }
            $userData = $updateResult["data"];
            $response = [
                'status' => true,
                'data' => $userData,
            ];

        } 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 output($response);
    }

    public function deletePropertyRoom($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $validationResult = $this->propertyRoomDeleteValidator->validate($params);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }
            $updateData =
                [
                    'status' => 0,
                    "updated_by" => fillOnUndefined($params, "user_id")
                ];

            $updateResult = $this->update($params['id'], $updateData);
            if ($updateResult['status'] != 'success') {
                throw new ApiErrorException($updateResult['message']);
            }
            $userData = $updateResult["data"];
            $response = [
                'status' => true,
                'data' => $userData,
            ];

        } 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 output($response);
    }

    public function getPropertyRoomRateChannel($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $criteria = [
                'criteria' => [
                    //['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => [
                    'propertyRoomType', 'propertyRoomRateMapping.propertyRoomRateChannel', 'propertyRoomRateMapping.connectedRate',
                    'propertyRoomRateMapping.propertyRoomRate', 'propertyRoomBedGroup.propertyRoomBedType',
                    'propertyRoomViewMapping.propertyRoomViewType', 'propertyRoomConnected'
                ]
            ];

            $columns = [
                'id', 'name', 'room_type_id', 'max_occupancy', 'max_adult', 'max_child', 'exclude_occupancy', 'room_size',
                'room_size_type', 'room_type_count', 'room_count', 'bathroom_count', 'toilet_count', 'lounge_count',
                'max_child_number', 'description', 'is_connected_room', 'is_connected_room_price', 'is_connected_room_availability',
                'occupancy_lock', 'status'
            ];

            $roomData = $this->propertyRoomRepository->findByCriteria($criteria, $columns);

            foreach ($roomData as $roomKey => $room) {
                $roomData[$roomKey]['is_connected_room'] = $room['is_connected_room'] == 1 ? true : false;
                $roomData[$roomKey]['is_connected_room_price'] = $room['is_connected_room_price'] == 1 ? true : false;
                $roomData[$roomKey]['is_connected_room_availability'] = $room['is_connected_room_availability'] == 1 ? true : false;
            }

            $criteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($params, 'property_id')],
                ],
                'with' => ['channel']
            ];

            $channelData = $this->propertyChannelMappingRepository->findByCriteria($criteria, ['id', 'property_id', 'channel_id']);

            $getApplicationLanguages = $this->languageService->getApplicationLanguages();
            if ($getApplicationLanguages['status'] != 'success') {
                throw new ApiErrorException($getApplicationLanguages['message']);
            }
            $applicationLanguages = $getApplicationLanguages['data'];

            $return = [];
            foreach ($roomData as $room) {

                $item = $room;
                $descriptionLangContents = json_decode($item['description'], 1);
                $responseLangDescription = [];
                foreach ($applicationLanguages as $applicationLanguage) {
                    $langKey = $applicationLanguage['code'];
                    $responseLangDescription[] = [
                        'language_code' => $langKey,
                        'description' => isset($descriptionLangContents[$langKey]) ? $descriptionLangContents[$langKey] : null
                    ];
                }
                $item['description'] = $responseLangDescription;
                $item['property_room_bed_group'] = [];
                $item['exclude_occupancy'] = json_decode($room['exclude_occupancy']);
                if (isset($room['property_room_rate_mapping'])) {
                    $roomRateMappings = $room['property_room_rate_mapping'];
                    $mapping = [];

                    foreach ($roomRateMappings as $roomRateMapping) {

                        if (isset($roomRateMapping['property_room_rate_channel'])) {

                            $newChannelData = [];
                            $roomRateChannels = $roomRateMapping['property_room_rate_channel'];
                            $rateChannelKey = [];
                            foreach ($roomRateChannels as $roomRateChannel) {
                                if ($roomRateChannel['status'] == 1) {
                                    $rateChannelKey[$roomRateChannel['channel_id'] . '|' . $roomRateChannel['room_rate_mapping_id']] = $roomRateChannel['id'];
                                }
                            }

                            foreach ($channelData as $channel) {
                                $newChannelData[] = [
                                    'id' => $channel['channel']['id'],
                                    'name' => $channel['channel']['name'],
                                    'channel_category_id' => $channel['channel']['channel_category_id'],
                                    'country_code' => $channel['channel']['country_code'],
                                    'currency_code' => $channel['channel']['currency_code'],
                                    'logo' => $channel['channel']['logo'],
                                    'is_checked' => isset($rateChannelKey[$channel['channel_id'] . '|' . $roomRateMapping['id']]),
                                ];
                            }
                            $roomRateMapping['property_room_rate_channel'] = $newChannelData;
                        }
                        $roomRateMapping['name'] = $roomRateMapping['property_room_rate']['name'];
                        $roomRateMapping['min_stay'] = $roomRateMapping['property_room_rate']['min_stay'];
                        $roomRateMapping['max_stay'] = $roomRateMapping['property_room_rate']['max_stay'];
                        unset($roomRateMapping['property_room_rate']);
                        $mapping[] = $roomRateMapping;

                    }

                    $item['property_room_rate_mapping'] = $mapping;

                }
                $bedGroups = collect($room['property_room_bed_group'])->keyBy('bed_group')->keys();
                $group = [];
                foreach ($bedGroups as $bedGroup) {
                    $thisGroup = collect($room['property_room_bed_group'])->where('bed_group', '=', $bedGroup)->map(function ($bedItem) use ($bedGroup) {
                        $responseMapping = $bedItem;
                        $responseMapping['bed_type_name'] = $bedItem['property_room_bed_type']['name'];
                        $responseMapping['bed_type_language_key'] = $bedItem['property_room_bed_type']['language_key'];
                        unset($responseMapping['property_room_bed_type']);
                        return $responseMapping;
                    })->toArray();
                    $newItem = [];
                    foreach ($thisGroup as $bedItem) {
                        $newItem[] = $bedItem;
                    }
                    $group[] = $newItem;
                }
                $item['property_room_bed_group'] = $group;
                $item['property_room_view_mapping'] = collect($room['property_room_view_mapping'])->map(function ($value) {

                    return $value['property_room_view_type'];

                })->all();


                $return[] = $item;
            }


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

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

        return output($response);
    }

    public function getPropertyRoomInventory($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {


            $validationResult = $this->propertyRoomInventoryValidator->validate($params);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $propertyRequest = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'firstRow' => 1

            ];
            $property = $this->propertyRepository->findByCriteria($propertyRequest);

            if (!$property) {
                throw new ApiErrorException(lang('Property not found'));
            }

            // Get Channel Mapping Information
            $criteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($params, 'property_id')],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => fillOnUndefined($params, 'channel_id')],
                ],
                'with' => ['channel'],
                'firstRow' => 1
            ];

            $channelData = $this->propertyChannelMappingRepository->findByCriteria($criteria, ['id', 'property_id', 'channel_id', 'currency_code']);
            if (!$channelData) {
                throw new ApiErrorException('Channel mapping not found');
            }


            $inventoryGetParams = $params;
            $inventoryGetParams['channelData'] = $channelData;
            $roomRatePrices = $this->getInventory($inventoryGetParams);

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

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

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

        return output($response);
    }


    public function checkPropertyRoomMapping($param = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $request = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $param['property_id']],
                ],
                'whereIn' => [
                    ['field' => 'id', 'value' => $param['room_ids']],
                ],
                'count' => 1
            ];
            $data = $this->propertyRoomRepository->findByCriteria($request);
            if ($data < count($param['room_ids'])) {
                throw new ApiErrorException('Property - Room Mapping not validate.');
            }
            $response = [
                'status' => true,
                'data' => $data,
            ];
        } catch (ApiErrorException $e) {
            $response['message'] = $e->getMessage();
        } catch (Exception $e) {
            $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
            Log::error($message);
            $response['message'] = $e->getMessage();
        }
        return output($response);
    }

    public function addPropertyRoomAndBed($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            DB::beginTransaction();

            // check room name, it is null set room type name.
            if ($params['name'] == null) {
                $propertyRoomTypeCriteria = [
                    'criteria' => [
                        ['field' => 'id', 'condition' => '=', 'value' => $params['room_type_id']],
                    ],
                    'firstRow' => true,
                ];
                $propertyType = $this->propertyRoomTypeService->select($propertyRoomTypeCriteria);
                $params['name'] = $propertyType['data']['name'];
            }

            $validationResult = $this->propertyRoomAndBedAddValidator->validate($params);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }

            $description = [];
            foreach (fillOnUndefined($params, "description", []) as $title) {
                $description[$title['language_code']] = $title['description'];
            }


            if (!$params['is_connected_room']) {
                $params['is_connected_room_price'] = null;
                $params['is_connected_room_availability'] = null;
                $params['connected_rooms'] = [];
            }

            $insertRoomData =
                [
                    'property_id' => fillOnUndefined($params, 'property_id'),
                    'name' => fillOnUndefined($params, 'name'),
                    'room_type_id' => fillOnUndefined($params, 'room_type_id'),
                    'max_occupancy' => fillOnUndefined($params, 'max_occupancy'),
                    'max_adult' => fillOnUndefined($params, 'max_adult'),
                    'max_child' => fillOnUndefined($params, 'max_child'),
                    'occupancy_lock' => fillOnUndefined($params, 'occupancy_lock'),
                    'exclude_occupancy' => json_encode($params['exclude_occupancy'], true),
                    'room_size' => fillOnUndefined($params, 'room_size', null),
                    'room_size_type' => fillOnUndefined($params, 'room_size_type', null),
                    'room_type_count' => fillOnUndefined($params, 'room_type_count', 1),
                    'room_count' => fillOnUndefined($params, 'room_count', null),
                    'bathroom_count' => fillOnUndefined($params, 'bathroom_count', null),
                    'toilet_count' => fillOnUndefined($params, 'toilet_count', null),
                    'lounge_count' => fillOnUndefined($params, 'lounge_count', null),
                    'max_child_number' => fillOnUndefined($params, 'max_child_number', null),
                    'description' => json_encode($description),
                    'is_connected_room' => fillOnUndefined($params, 'is_connected_room', null) ? 1 : null,
                    'is_connected_room_price' => fillOnUndefined($params, 'is_connected_room_price', null) ? 1 : null,
                    'is_connected_room_availability' => fillOnUndefined($params, 'is_connected_room_availability', null) ? 1 : null,
                    "status" => fillOnUndefined($params, "status", 1),
                    "created_by" => fillOnUndefined($params, "user_id"),
                    "updated_by" => fillOnUndefined($params, "user_id")
                ];

            $insertRoomDataResult = $this->propertyRoomRepository->create($insertRoomData);

            if ($insertRoomDataResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }

            $roomId = $insertRoomDataResult['data']['id'];
            $roomBedGroup = fillOnUndefined($params, 'room_bed_group', []);
            $bedGroupIndex = 1;
            $insertBedData = [];


            $isBedGroupInsert = true;

            if (count($roomBedGroup) == 1) {
                if (count($roomBedGroup[0]) == 1) {
                    if (empty($roomBedGroup[0][0]['bed_type_id'])) {
                        $isBedGroupInsert = false;
                    }

                }
            }


            if ($isBedGroupInsert) {

                $roomBedGroups = [];
                collect($roomBedGroup)->map(function ($value) use (&$roomBedGroups) {
                    $roomBedGroups[] = collect($value)
                        ->groupBy('bed_type_id')
                        ->map(function ($val) {
                            return $val->count();
                        })->toArray();
                });

                foreach ($roomBedGroups as $bedGroup) {
                    foreach ($bedGroup as $bedTypeId => $bedTypeCount) {
                        if (!empty($bedTypeId)) {
                            $insertBedData[] =
                                [
                                    'room_id' => $roomId,
                                    'bed_group' => $bedGroupIndex,
                                    'count' => $bedTypeCount,
                                    'bed_type_id' => $bedTypeId,
                                    "status" => fillOnUndefined($params, "status", 1),
                                    "created_by" => fillOnUndefined($params, "user_id", 0),
                                    "updated_by" => fillOnUndefined($params, "user_id", 0),
                                    'created_at' => Carbon::now()->timestamp,
                                    'updated_at' => Carbon::now()->timestamp,
                                ];
                        }
                    }
                    $bedGroupIndex++;
                }
                $insertBedResult = $this->propertyRoomBedRepository->insert($insertBedData);
                if ($insertBedResult['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

            }


            if (!empty($params['room_view_type'])) {

                foreach ($params['room_view_type'] as $roomViewType) {

                    $datas[] = [
                        'room_id' => $roomId,
                        'room_view_type_id' => $roomViewType,
                        "created_by" => fillOnUndefined($params, "user_id", 0),
                        "updated_by" => fillOnUndefined($params, "user_id", 0),
                        "created_at" => time(),
                        "updated_at" => time(),
                    ];
                }

                $propertyRoomViewMappingResult = $this->propertyRoomViewMappingRepository->createAll($datas);

                if ($propertyRoomViewMappingResult['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

            }

            //Connected Rooms
            if ($params['is_connected_room']) {
                $syncPropertyConnectedRoomParam = [
                    'property_id' => $params['property_id'],
                    'room_id' => $roomId,
                    'connected_rooms' => $params['connected_rooms'],
                    'user_id' => fillOnUndefined($params, 'user_id')
                ];

                $syncPropertyConnectedRoom = $this->syncPropertyConnectedRoom($syncPropertyConnectedRoomParam);

                if ($syncPropertyConnectedRoom['status'] != 'success') {
                    throw new Exception($syncPropertyConnectedRoom['message']);
                }
            }

            //$userData = $insertBedResult["data"];
            $response = [
                'status' => true,
                //'data' => $userData,
            ];

            DB::commit();

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

        return output($response);
    }

    public function updatePropertyRoomAndBed($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            DB::beginTransaction();

            // check room name, it is null set room type name.
            if ($params['name'] == null) {
                $propertyRoomTypeCriteria = [
                    'criteria' => [
                        ['field' => 'id', 'condition' => '=', 'value' => $params['room_type_id']],
                    ],
                    'firstRow' => true,
                ];
                $propertyType = $this->propertyRoomTypeService->select($propertyRoomTypeCriteria);
                $params['name'] = $propertyType['data']['name'];
            }


            $validationResult = $this->propertyRoomAndBedUpdateValidator->validate($params);

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }


            $description = [];
            foreach (fillOnUndefined($params, "description", []) as $title) {
                $description[$title['language_code']] = $title['description'];
            }

            if (!$params['is_connected_room']) {
                $params['is_connected_room_price'] = null;
                $params['is_connected_room_availability'] = null;
                $params['connected_rooms'] = [];
            }

            $insertRoomData =
                [
                    'property_id' => fillOnUndefined($params, 'property_id'),
                    'name' => fillOnUndefined($params, 'name'),
                    'room_type_id' => fillOnUndefined($params, 'room_type_id'),
                    'max_occupancy' => fillOnUndefined($params, 'max_occupancy'),
                    'max_adult' => fillOnUndefined($params, 'max_adult'),
                    'max_child' => fillOnUndefined($params, 'max_child'),
                    'occupancy_lock' => fillOnUndefined($params, 'occupancy_lock'),
                    'exclude_occupancy' => json_encode($params['exclude_occupancy'], true),
                    'room_size' => fillOnUndefined($params, 'room_size', null),
                    'room_size_type' => fillOnUndefined($params, 'room_size_type', null),
                    'room_type_count' => fillOnUndefined($params, 'room_type_count', 1),
                    'room_count' => fillOnUndefined($params, 'room_count', null),
                    'bathroom_count' => fillOnUndefined($params, 'bathroom_count', null),
                    'toilet_count' => fillOnUndefined($params, 'toilet_count', null),
                    'lounge_count' => fillOnUndefined($params, 'lounge_count', null),
                    'max_child_number' => fillOnUndefined($params, 'max_child_number', null),
                    'is_connected_room' => fillOnUndefined($params, 'is_connected_room', null) ? 1 : null,
                    'is_connected_room_price' => fillOnUndefined($params, 'is_connected_room_price', null) ? 1 : null,
                    'is_connected_room_availability' => fillOnUndefined($params, 'is_connected_room_availability', null) ? 1 : null,
                    'description' => json_encode($description),
                    "status" => fillOnUndefined($params, "status", 1),
                    "updated_by" => fillOnUndefined($params, "user_id")
                ];

            $insertRoomDataResult = $this->propertyRoomRepository->update(fillOnUndefined($params, 'room_id'), $insertRoomData);

            if ($insertRoomDataResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }

            $roomId = $insertRoomDataResult['data']['id'];
            $roomBedGroup = fillOnUndefined($params, 'room_bed_group', []);
            $bedGroupIndex = 1;
            $insertBedData = [];


            $roomBedCriteria = [
                'criteria' => [
                    ['field' => 'room_id', 'condition' => '=', 'value' => $params['room_id']],
                ]
            ];
            $roomBeds = $this->propertyRoomBedRepository->findByCriteria($roomBedCriteria);

            $roomBeds = collect($roomBeds)->keyBy('id')->keys()->all();
            if ($roomBeds) {
                $destroyStatus = $this->propertyRoomBedRepository->destroy($roomBeds);
                if ($destroyStatus['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

            }

            $roomViewCriteria = [
                'criteria' => [
                    ['field' => 'room_id', 'condition' => '=', 'value' => $params['room_id']],
                ]
            ];
            $roomViews = $this->propertyRoomViewMappingRepository->findByCriteria($roomViewCriteria);
            $roomViews = collect($roomViews)->keyBy('id')->keys()->all();

            if ($roomViews) {
                $destroyStatus = $this->propertyRoomViewMappingRepository->destroy($roomViews);
                if ($destroyStatus['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }
            }


            $isBedGroupInsert = true;

            if (count($roomBedGroup) == 1) {
                if (count($roomBedGroup[0]) == 1) {
                    if (empty($roomBedGroup[0][0]['bed_type_id'])) {
                        $isBedGroupInsert = false;
                    }

                }
            }


            if ($isBedGroupInsert) {

                $roomBedGroups = [];
                collect($roomBedGroup)->map(function ($value) use (&$roomBedGroups) {
                    $roomBedGroups[] = collect($value)
                        ->groupBy('bed_type_id')
                        ->map(function ($val) {
                            return $val->count();
                        })->toArray();
                });

                foreach ($roomBedGroups as $bedGroup) {
                    foreach ($bedGroup as $bedTypeId => $bedTypeCount) {
                        if (!empty($bedTypeId)) {
                            $insertBedData[] =
                                [
                                    'room_id' => $roomId,
                                    'bed_group' => $bedGroupIndex,
                                    'count' => $bedTypeCount,
                                    'bed_type_id' => $bedTypeId,
                                    "status" => fillOnUndefined($params, "status", 1),
                                    "created_by" => fillOnUndefined($params, "user_id", 0),
                                    "updated_by" => fillOnUndefined($params, "user_id", 0),
                                    'created_at' => Carbon::now()->timestamp,
                                    'updated_at' => Carbon::now()->timestamp,
                                ];
                        }
                    }
                    $bedGroupIndex++;
                }

                $insertBedResult = $this->propertyRoomBedRepository->insert($insertBedData);
                if ($insertBedResult['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

            }


            if (!empty($params['room_view_type'])) {

                foreach ($params['room_view_type'] as $roomViewType) {

                    $datas[] = [
                        'room_id' => $roomId,
                        'room_view_type_id' => $roomViewType,
                        "created_by" => fillOnUndefined($params, "user_id", 0),
                        "updated_by" => fillOnUndefined($params, "user_id", 0),
                        "created_at" => time(),
                        "updated_at" => time(),
                    ];
                }

                $propertyRoomViewMappingResult = $this->propertyRoomViewMappingRepository->insert($datas);

                if ($propertyRoomViewMappingResult['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

            }


            //Connected Rooms
            $syncPropertyConnectedRoomParam = [
                'property_id' => $params['property_id'],
                'room_id' => $roomId,
                'connected_rooms' => $params['connected_rooms'],
                'user_id' => fillOnUndefined($params, 'user_id')
            ];


            $syncPropertyConnectedRoom = $this->syncPropertyConnectedRoom($syncPropertyConnectedRoomParam);

            if ($syncPropertyConnectedRoom['status'] != 'success') {
                throw new Exception($syncPropertyConnectedRoom['message']);
            }


            //$userData = $insertBedResult["data"];
            $response = [
                'status' => true,
                //'data' => $userData,
            ];

            DB::commit();

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

        return output($response);
    }

    public function getPropertyRoomAndBed($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $criteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => $params['room_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['propertyRoomBedGroup', 'propertyRoomViewMapping'],
                'firstRow' => true
            ];

            $data = $this->propertyRoomRepository->findByCriteria($criteria, ['id', 'name', 'room_type_id', 'max_occupancy', 'max_adult', 'max_child', 'room_size', 'room_size_type', 'room_type_count', 'room_count', 'bathroom_count', 'toilet_count', 'lounge_count', 'max_child_number', 'description']);
            $room = $data;

            $getApplicationLanguages = $this->languageService->getApplicationLanguages();
            if ($getApplicationLanguages['status'] != 'success') {
                throw new ApiErrorException($getApplicationLanguages['message']);
            }
            $applicationLanguages = $getApplicationLanguages['data'];
            $descriptionLangContents = json_decode($data['description'], 1);
            $responseLangDescription = [];
            foreach ($applicationLanguages as $applicationLanguage) {
                $langKey = $applicationLanguage['code'];
                $responseLangDescription[] = [
                    'language_code' => $langKey,
                    'description' => isset($descriptionLangContents[$langKey]) ? $descriptionLangContents[$langKey] : null
                ];
            }
            $room['description'] = $responseLangDescription;


            $bedGroups = collect($room['property_room_bed_group'])->keyBy('bed_group')->keys();
            $group = [];

            foreach ($bedGroups as $bedGroup) {
                $bedTypes = [];
                $thisGroup = collect($room['property_room_bed_group'])->where('bed_group', '=', $bedGroup)->map(function ($bedItem) use ($bedGroup) {
                    $responseMapping = $bedItem;
                    return $responseMapping;
                })->toArray();

                foreach ($thisGroup as $groupItem) {
                    for ($i = 1; $i <= $groupItem['count']; $i++) {
                        $bedTypes[] = ['bed_type_id' => $groupItem['bed_type_id']];
                    }
                }
                $group[] = $bedTypes;
            }
            $room['property_room_bed_group'] = $group;
            $room['property_room_view_mapping'] = collect($room['property_room_view_mapping'])->keyBy('room_view_type_id')->keys()->all();

            $newRoomMapping = $room;

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

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

        return output($response);
    }

    public function getChannelRoomRateMapping($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $criteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['propertyRoomType', 'propertyRoomRateMapping.propertyRoomRateChannel', 'propertyRoomRateMapping.propertyRoomRate'],
                'orderBy' => [
                    ['field' => 'id', 'value' => 'ASC']
                ]
            ];

            $roomData = $this->propertyRoomRepository->findByCriteria($criteria, ['id', 'name', 'room_type_id', 'max_occupancy', 'max_adult', 'max_child', 'exclude_occupancy', 'room_size', 'room_size_type', 'room_type_count', 'room_count', 'bathroom_count', 'toilet_count', 'lounge_count', 'max_child_number']);

            $return = [];
            foreach ($roomData as $room) {
                $item = $room;
                $item['exclude_occupancy'] = json_decode($room['exclude_occupancy']);
                if ($room['property_room_rate_mapping']) {
                    $roomRateMappings = $room['property_room_rate_mapping'];
                    $mapping = [];
                    foreach ($roomRateMappings as $roomRateMapping) {
                        $propertyRoomRateChannel = null;
                        if (isset($roomRateMapping['property_room_rate_channel'])) {
                            $propertyRoomRateChannel = collect($roomRateMapping['property_room_rate_channel'])
                                ->where('channel_id', '=', $params['channel_id'])
                                ->where('room_rate_mapping_id', '=', $roomRateMapping['id'])
                                ->first();
                        }
                        $mappingStatus = false;
                        if ($propertyRoomRateChannel) {
                            if ($propertyRoomRateChannel['status'] == 1) {
                                $mappingStatus = true;
                            }
                        }
                        $roomRateMapping['name'] = $roomRateMapping['property_room_rate']['name'];
                        $roomRateMapping['min_stay'] = $roomRateMapping['property_room_rate']['min_stay'];
                        $roomRateMapping['max_stay'] = $roomRateMapping['property_room_rate']['max_stay'];
                        $roomRateMapping['is_selected'] = $mappingStatus;
                        $roomRateMapping['has_date'] = $propertyRoomRateChannel['has_date'] == 0 ? false : true;
                        $roomRateMapping['end_date'] = $propertyRoomRateChannel['end_date'];
                        $roomRateMapping['start_date'] = $propertyRoomRateChannel['start_date'];
                        unset($roomRateMapping['property_room_rate']);
                        unset($roomRateMapping['property_room_rate_channel']);
                        $mapping[] = $roomRateMapping;
                    }
                    $item['property_room_rate_mapping'] = $mapping;
                    $return[] = $item;
                }

            }

            $collection = collect($return);
            $sorted = $collection->sortBy('id')->values()->all();

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

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

        return output($response);
    }

    public function inventoryRoomList($params = [])
    {
        $criteria = [
            'criteria' => [
                ['field' => 'status', 'condition' => '=', 'value' => 1],
                ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                isset($params['room_id']) ? ['field' => 'id', 'condition' => '=', 'value' => $params['room_id']] : null,
            ],
            'with' => ['propertyRoomRateMapping.propertyRoomRate', 'propertyRoomRateMapping.propertyRoomRateChannel'],
            "orderBy" => [
                ["field" => "id", "value" => "ASC"]
            ],
        ];

        $roomData = $this->propertyRoomRepository->findByCriteria($criteria, ['id', 'name', 'room_type_id', 'max_occupancy', 'max_adult', 'max_child', 'room_size', 'room_size_type', 'room_type_count', 'room_count', 'bathroom_count', 'toilet_count', 'lounge_count', 'max_child_number']);

        return $roomData ? $roomData : [];

    }

    public function inventoryRoomRateData($params = [])
    {

        $roomRatesCriteria = [
            'criteria' => [
                ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ['field' => 'date', 'condition' => '>=', 'value' => $params['start_date']],
                ['field' => 'date', 'condition' => '<=', 'value' => $params['end_date']],
                ['field' => 'channel_id', 'condition' => '=', 'value' => $params['channel_id']],
            ],
            'whereIn' => [
                ['field' => 'availability_type_id', 'value' => $params['availability_type_id']]
            ]
        ];

        $roomRatePrice = $this->propertyRoomRatePriceRepository->findbyCriteria($roomRatesCriteria, ['id', 'property_id', 'property_room_id', 'room_rate_mapping_id', 'availability_type_id', 'channel_id', 'min_stay', 'max_stay', 'stop_sell', 'booking_on_request', 'date', 'amount', 'currency']);
        $roomRatePrice = $roomRatePrice ? $roomRatePrice : [];
        $priceArray = [];
        foreach ($roomRatePrice as $price) {
            $priceArray[$price['property_room_id'] . '|' . $price['room_rate_mapping_id'] . '|' . $price['availability_type_id'] . '|' . $price['date']] = $price;
        }

        return $priceArray;

    }

    public function inventoryAvailabilityData($params = [])
    {

        $availabilityTypeIds = implode(",", $params['availability_type_id']);

        $roomAvailability = [];
        if(!is_null($params['start_date']) && !is_null($params['end_date'])) {
            $roomAvailabilityCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'date', 'condition' => '>=', 'value' => $params['start_date']],
                    ['field' => 'date', 'condition' => '<=', 'value' => $params['end_date']],
                ],
                'criteriaWhereRaw' =>
                    [
                        [
                            'query' => " ( `availability_type_id` = 3 OR ( `channel_id` = ? OR `channel_id` IS NULL ) AND `availability_type_id` IN ( " . $availabilityTypeIds . " ) )",
                            "binds" => [$params['channel_id']]
                        ]
                    ],

            ];

            $roomAvailability = $this->propertyRoomAvailabilityRepository->findbyCriteria($roomAvailabilityCriteria);
        }

        $availabilityArray = [];
        foreach ($roomAvailability as $availability) {

            $availabilityArrayKey = $availability['property_room_id'] . '|' . $availability['room_rate_mapping_id'] . '|' . $availability['availability_type_id'] . '|' . $availability['channel_id'] . '|' . $availability['date'];

            $availabilityArray[$availabilityArrayKey][] = [
                'id' => $availability['id'],
                'room_id' => $availability['property_room_id'],
                'room_rate_mapping_id' => $availability['room_rate_mapping_id'],
                'availability_type_id' => $availability['availability_type_id'],
                'channel_id' => $availability['channel_id'],
                'date' => $availability['date'],
                'availability' => $availability['availability'],
                'stop_sell' => $availability['stop_sell'],
            ];
        }

        //Sistemdeki benzer id listesi, mysql null unique index hatası için
        foreach ($availabilityArray as $availabilityKey => $availability) {

            if(count($availability) > 1) {

                $availabilityArray[$availabilityKey] = last($availability);
                $otherAvailabilityRowIds = collect($availability)->whereNotIn('id', [$availabilityArray[$availabilityKey]['id']])->pluck('id')->toArray();
                $availabilityArray[$availabilityKey] = last($availability);
                $availabilityArray[$availabilityKey]['otherIds'] = $otherAvailabilityRowIds;
            } else {
                $availabilityArray[$availabilityKey] = reset($availability);
            }

        }

        return $availabilityArray;

    }

    public function getInventory($params)
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {


            $startDate = fillOnUndefinedAndEmpty($params, 'start_date', date('Y-m-d'));
            $endDate = fillOnUndefinedAndEmpty($params, 'end_date', Carbon::parse($startDate)->addDay(15)->format('Y-m-d'));

            if ($endDate < $startDate) {
                throw new ApiErrorException('date error');
            }
            $diffInDays = Carbon::parse($startDate)->diffInDays($endDate);

            if ($diffInDays > 365) {
                throw new ApiErrorException('Up to 1 yearly price updates can be made.'); //TODO: param extend
            }

            $channelSetupTypes = $this->setChannelAvailabilityTypes(['property_id' => $params['property_id'], 'channel_id' => $params['channel_id']]);
            if ($channelSetupTypes['status'] != 'success') {
                throw new ApiErrorException($channelSetupTypes['message']);
            }
            $channelSetupTypes = $channelSetupTypes['data'];
            $forGeneralId = $channelSetupTypes['forGeneralId'];
            $forAvailabilityData = $channelSetupTypes['forAvailabilityData'];
            $forPriceData = $channelSetupTypes['forPriceData'];
            $getPriceDataIds = collect($forPriceData)->keyBy('id')->keys()->toArray();
            $getAvailabilityDataIds = collect($forAvailabilityData)->keyBy('id')->keys()->toArray();
            $getAvailabilityDataIds = array_unique(array_merge($forGeneralId, $getAvailabilityDataIds));

            $generalAvailabilityCheckId = $forGeneralId[0];


            $roomData = $this->inventoryRoomList($params);
            $priceRequest = [
                'property_id' => $params['property_id'],
                'start_date' => $startDate,
                'end_date' => $endDate,
                'channel_id' => $params['channel_id'],
                'availability_type_id' => $getPriceDataIds,
            ];
            $priceArray = $this->inventoryRoomRateData($priceRequest);

            $availabilityRequest = [
                'property_id' => $params['property_id'],
                'start_date' => $startDate,
                'end_date' => $endDate,
                'channel_id' => $params['channel_id'],
                'availability_type_id' => $getAvailabilityDataIds,
            ];

            $availabilityArray = $this->inventoryAvailabilityData($availabilityRequest);
            $quotaCollection = collect($availabilityArray)
                ->where('availability_type_id', '=', 3);


            $currencyCode = $params['channelData']['currency_code'];

            $return = [];
            $keysForDevelopment = [];

            // Fill Rooms
            foreach ($roomData as $room) {
                $item = $room;

                $roomGeneralAvailability = collect($availabilityArray)
                    ->where('room_id', '=', $room['id'])
                    ->where('availability_type_id', '=', 1)
                    ->where('room_rate_mapping_id', '=', null)
                    ->where('channel_id', '=', null)
                    ->toArray();

                // Fill General availability Keys
                $startDate = Carbon::parse($params['start_date']);
                $roomAvailability = [];
                $quotaAvailability = [];
                $roomStopSell = [];
                for ($i = 0; $i <= $diffInDays; $i++) {
                    $checkKey = $room['id'] . '||' . $generalAvailabilityCheckId . "||" . $startDate->format('Y-m-d');
                    $responseKey = 'AVA_' . $generalAvailabilityCheckId . '_' . $room['id'] . '_' . '0' . '_' . $startDate->format('Ymd');
                    $responseKeyStopSell = 'STS_' . $generalAvailabilityCheckId . '_' . $room['id'] . '_' . '0' . '_' . $startDate->format('Ymd');

                    $usedAvailability = $quotaCollection
                        ->where('date', '=', $startDate->format('Y-m-d'))
                        ->where('room_id', '=', $room['id'])
                        ->sum('availability');

                    $remainingAvailability = isset($roomGeneralAvailability[$checkKey]['availability']) ? ($roomGeneralAvailability[$checkKey]['availability'] - $usedAvailability) : 0;

                    if (isset($roomGeneralAvailability[$checkKey])) {
                        $roomAvailability[$startDate->format('Y-m-d')] = [
                            'key' => $responseKey,
                            'value' => $roomGeneralAvailability[$checkKey]['availability'],
                            'stop_sell' => $roomGeneralAvailability[$checkKey]['stop_sell']
                        ];

                        $roomStopSell[$startDate->format('Y-m-d')] = [
                            'key' => $responseKeyStopSell,
                            'value' => $roomGeneralAvailability[$checkKey]['stop_sell'],
                        ];

                        $keysForDevelopment[$responseKey] = $roomGeneralAvailability[$checkKey]['availability'];
                        $keysForDevelopment[$responseKeyStopSell] = $roomGeneralAvailability[$checkKey]['stop_sell'];
                    } else {
                        $roomAvailability[$startDate->format('Y-m-d')] = [
                            'key' => $responseKey,
                            'value' => null,
                            'stop_sell' => 0
                        ];

                        $roomStopSell[$startDate->format('Y-m-d')] = [
                            'key' => $responseKeyStopSell,
                            'value' => 0,
                        ];

                        $keysForDevelopment[$responseKey] = rand(1, 10);
                        $keysForDevelopment[$responseKeyStopSell] = 0;
                    }

                    $responseRMKey = 'RMA_' . $generalAvailabilityCheckId . '_' . $room['id'] . '_' . '0' . '_' . $startDate->format('Ymd');
                    $quotaAvailability[$startDate->format('Y-m-d')] = [
                        'key' => $responseRMKey,
                        'value' => $remainingAvailability,
                    ];


                    $startDate = $startDate->addDay();
                }
                $item['room_availability'] = $roomAvailability;
                $item['remaining_availability'] = $quotaAvailability;
                $item['room_stop_sell'] = $roomStopSell;

                // Fill Room Rate Array
                if (isset($room['property_room_rate_mapping'])) {
                    $roomRateMappings = $room['property_room_rate_mapping'];
                    if (isset($params['room_rate_mapping_id'])) {
                        $roomRateMappings = collect($roomRateMappings)
                            ->where('id', '=', $params['room_rate_mapping_id'])
                            ->toArray();
                    }
                    $mapping = [];
                    foreach ($roomRateMappings as $roomRateMapping) {

                        $checkMappingStatus = collect($roomRateMapping['property_room_rate_channel'])
                            ->where('channel_id', '=', $params['channel_id'])
                            ->where('status', '=', 1)
                            ->first();

                        if ($checkMappingStatus) {
                            $roomRateMapping['name'] = $roomRateMapping['property_room_rate']['name'];
                            $roomRateMapping['min_stay'] = $roomRateMapping['property_room_rate']['min_stay'];
                            $roomRateMapping['max_stay'] = $roomRateMapping['property_room_rate']['max_stay'];
                            $roomRateMapping['currency_code'] = $currencyCode;
                            unset($roomRateMapping['property_room_rate']);
                            foreach ($forPriceData as $roomRateAvailabilityCheckId) {
                                $startDate = Carbon::parse($params['start_date']);
                                $prices[$roomRateAvailabilityCheckId['id']]['name'] = $roomRateAvailabilityCheckId['name'];
                                $prices[$roomRateAvailabilityCheckId['id']]['language_key'] = $roomRateAvailabilityCheckId['language_key'];
                                for ($i = 0; $i <= $diffInDays; $i++) {
                                    $checkKey = $roomRateMapping['room_id'] . "|" . $roomRateMapping['id'] . "|" . $roomRateAvailabilityCheckId['id'] . "|" . $startDate->format('Y-m-d');
                                    $responsePRCKey = 'PRC_' . $roomRateAvailabilityCheckId['id'] . '_' . $roomRateMapping['room_id'] . '_' . $roomRateMapping['id'] . '_' . $startDate->format('Ymd');
                                    $responseSTSKey = 'STS_' . $roomRateAvailabilityCheckId['id'] . '_' . $roomRateMapping['room_id'] . '_' . $roomRateMapping['id'] . '_' . $startDate->format('Ymd');
                                    $responseMNSKey = 'MNS_' . $roomRateAvailabilityCheckId['id'] . '_' . $roomRateMapping['room_id'] . '_' . $roomRateMapping['id'] . '_' . $startDate->format('Ymd');

                                    // Fill Price Keys
                                    if (isset($priceArray[$checkKey])) {
                                        $prices[$roomRateAvailabilityCheckId['id']]['price'][$startDate->format('Y-m-d')] = [
                                            'key' => $responsePRCKey,
                                            'value' => $priceArray[$checkKey]['amount'],
                                            'stop_sell' => $priceArray[$checkKey]['stop_sell'],
                                        ];

                                        $prices[$roomRateAvailabilityCheckId['id']]['stop_sell'][$startDate->format('Y-m-d')] = [
                                            'key' => $responseSTSKey,
                                            'value' => $priceArray[$checkKey]['stop_sell'],
                                        ];

                                        $prices[$roomRateAvailabilityCheckId['id']]['min_stay'][$startDate->format('Y-m-d')] = [
                                            'key' => $responseMNSKey,
                                            'value' => $priceArray[$checkKey]['min_stay'],
                                        ];

                                        $keysForDevelopment[$responsePRCKey] = $priceArray[$checkKey]['amount'];
                                    } else {
                                        $prices[$roomRateAvailabilityCheckId['id']]['price'][$startDate->format('Y-m-d')] = [
                                            'key' => $responsePRCKey,
                                            'value' => null,
                                            'stop_sell' => 0
                                        ];

                                        $prices[$roomRateAvailabilityCheckId['id']]['stop_sell'][$startDate->format('Y-m-d')] = [
                                            'key' => $responseSTSKey,
                                            'value' => 0,
                                        ];

                                        $prices[$roomRateAvailabilityCheckId['id']]['min_stay'][$startDate->format('Y-m-d')] = [
                                            'key' => $responseMNSKey,
                                            'value' => 1,
                                        ];

                                        $keysForDevelopment[$responsePRCKey] = rand(1, 10);
                                    }

                                    $startDate = $startDate->addDay();
                                }
                            }
                            $roomRateMapping['prices'] = $prices;
                            $availabilities = [];
                            $prices = [];
                            foreach ($forAvailabilityData as $roomRateAvailabilityCheckId) {
                                $startDate = Carbon::parse($params['start_date']);
                                $availabilities[$roomRateAvailabilityCheckId['id']]['name'] = $roomRateAvailabilityCheckId['name'];
                                $availabilities[$roomRateAvailabilityCheckId['id']]['language_key'] = $roomRateAvailabilityCheckId['language_key'];
                                for ($i = 0; $i <= $diffInDays; $i++) {
                                    $checkKey = $roomRateMapping['room_id'] . "|" . $roomRateMapping['id'] . "|" . $roomRateAvailabilityCheckId['id'] . "|" . $params['channel_id'] . "|" . $startDate->format('Y-m-d');
                                    $responseAVAKey = 'AVA_' . $roomRateAvailabilityCheckId['id'] . '_' . $roomRateMapping['room_id'] . '_' . $roomRateMapping['id'] . '_' . $startDate->format('Ymd');

                                    // Fill Availability Keys
                                    if (isset($availabilityArray[$checkKey])) {
                                        $availabilities[$roomRateAvailabilityCheckId['id']]['availability'][$startDate->format('Y-m-d')] = [
                                            'key' => $responseAVAKey,
                                            'value' => $availabilityArray[$checkKey]['availability'],
                                        ];
                                        $keysForDevelopment[$responseAVAKey] = $availabilityArray[$checkKey]['availability'];
                                    } else {
                                        $availabilities[$roomRateAvailabilityCheckId['id']]['availability'][$startDate->format('Y-m-d')] = [
                                            'key' => $responseAVAKey,
                                            'value' => null,
                                        ];
                                        $keysForDevelopment[$responseAVAKey] = rand(1, 10);
                                    }
                                    $startDate = $startDate->addDay();
                                }
                            }
                            $roomRateMapping['availabilities'] = $availabilities;
                            $mapping[] = $roomRateMapping;
                        }


                    }
                    $item['property_room_rate_mapping'] = $mapping;
                    if ($mapping) {
                        $return[] = $item;
                    }
                }

            }
            //    log::debug(json_encode($keysForDevelopment));
            $response = [
                'status' => true,
                'data' => $return,
            ];

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

        return output($response);
    }

    public function setChannelAvailabilityTypes($params)
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            // Get Channel Setup
            $criteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($params, 'property_id')],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => fillOnUndefined($params, 'channel_id')],
                ],
                'firstRow' => 1
            ];

            $channelSetupData = $this->propertyChannelMappingRepository->findByCriteria($criteria);
            if (!$channelSetupData) {
                throw new ApiErrorException('Channel mapping not found');
            }

            $propertyChannelSetupTypeId = $channelSetupData['property_availability_type_id'];
            // Get All Availability types
            $criteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ]
            ];
            $allAvailabilityTypes = $this->propertyAvailabilityTypeRepository->findByCriteria($criteria);
            if (!$allAvailabilityTypes) {
                throw new ApiErrorException('Availability types not found');
            }

            switch ($propertyChannelSetupTypeId) {
                default :
                    $forGeneralId = [1];
                    $forAvailabilityId = [];
                    $forPriceId = [1];
                    break;
                case 2:
                    $forGeneralId = [1];
                    $forAvailabilityId = [2];
                    $forPriceId = [2];
                    break;
                case 3:
                    $forGeneralId = [1];
                    $forAvailabilityId = [3];
                    $forPriceId = [1, 3];
                    break;
            }

            $forGeneralData = $forGeneralId ? collect($allAvailabilityTypes)->whereIn('id', $forGeneralId)->toArray() : [];
            $forAvailabilityData = $forGeneralId ? collect($allAvailabilityTypes)->whereIn('id', $forAvailabilityId)->toArray() : [];
            $forPriceData = $forGeneralId ? collect($allAvailabilityTypes)->whereIn('id', $forPriceId)->toArray() : [];

            $returnData = [
                'forGeneralId' => $forGeneralId,
                'forGeneralData' => $forGeneralData,
                'forAvailabilityData' => $forAvailabilityData,
                'forPriceData' => $forPriceData,
                'channelAvailabilityWorkingType' => $propertyChannelSetupTypeId
            ];

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


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

        return output($response);


    }

    public function roomIncludeOccupancies($params = [])
    {
        $occupancies = [];
        for ($i = 1; $i <= $params['max_adult']; $i++) {
            for ($j = 0; $j <= $params['max_child']; $j++) {
                $paxTotal = $i + $j;
                if ($paxTotal > $params['max_occupancy']) {
                    continue;
                }
                $occupancy = str_repeat('A', $i) . str_repeat('C', $j);
                if (array_search($occupancy, $params['exclude_occupancy']) > -1) {
                    continue;
                }
                $occupancies[] = $occupancy;
            }
        }
        return $occupancies;
    }

    public function getGroupInventory($params)
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {


            $startDate = fillOnUndefinedAndEmpty($params, 'start_date', date('Y-m-d'));
            $endDate = fillOnUndefinedAndEmpty($params, 'end_date', Carbon::parse($startDate)->addDay(15)->format('Y-m-d'));

            if ($endDate < $startDate) {
                throw new ApiErrorException('date error');
            }
            $diffInDays = Carbon::parse($startDate)->diffInDays($endDate);
            if ($diffInDays > 15) {
                throw new ApiErrorException('date error');
            }


            $roomData = $this->inventoryRoomList($params);

            $priceRequest = [
                'property_id' => $params['property_id'],
                'start_date' => $startDate,
                'end_date' => $endDate,
                'channel_id' => $params['channel_id'],
                'availability_type_id' => 1,
            ];

            $availabilityRequest = [
                'property_id' => $params['property_id'],
                'start_date' => $startDate,
                'end_date' => $endDate,
                'channel_id' => $params['channel_id'],
                'availability_type_id' => 1,
            ];

            $availabilityArray = $this->inventoryAvailabilityData($availabilityRequest);
            $quotaCollection = collect($availabilityArray)
                ->where('availability_type_id', '=', 3);


            $currencyCode = $params['channelData']['currency_code'];

            $return = [];
            $keysForDevelopment = [];

            // Fill Rooms
            foreach ($roomData as $room) {
                $item = $room;

                $roomGeneralAvailability = collect($availabilityArray)
                    ->where('room_id', '=', $room['id'])
                    ->where('availability_type_id', '=', 1)
                    ->where('room_rate_mapping_id', '=', null)
                    ->where('channel_id', '=', null)
                    ->toArray();

                // Fill General availability Keys
                $startDate = Carbon::parse($params['start_date']);
                $roomAvailability = [];
                $quotaAvailability = [];
                $roomStopSell = [];
                for ($i = 0; $i <= $diffInDays; $i++) {
                    $checkKey = $room['id'] . '||' . $generalAvailabilityCheckId . "||" . $startDate->format('Y-m-d');
                    $responseKey = 'AVA_' . $generalAvailabilityCheckId . '_' . $room['id'] . '_' . '0' . '_' . $startDate->format('Ymd');
                    $responseKeyStopSell = 'STS_' . $generalAvailabilityCheckId . '_' . $room['id'] . '_' . '0' . '_' . $startDate->format('Ymd');

                    $usedAvailability = $quotaCollection
                        ->where('date', '=', $startDate->format('Y-m-d'))
                        ->where('room_id', '=', $room['id'])
                        ->sum('availability');

                    $remainingAvailability = isset($roomGeneralAvailability[$checkKey]['availability']) ? ($roomGeneralAvailability[$checkKey]['availability'] - $usedAvailability) : 0;

                    if (isset($roomGeneralAvailability[$checkKey])) {
                        $roomAvailability[$startDate->format('Y-m-d')] = [
                            'key' => $responseKey,
                            'value' => $roomGeneralAvailability[$checkKey]['availability'],
                            'stop_sell' => $roomGeneralAvailability[$checkKey]['stop_sell']
                        ];

                        $roomStopSell[$startDate->format('Y-m-d')] = [
                            'key' => $responseKeyStopSell,
                            'value' => $roomGeneralAvailability[$checkKey]['stop_sell'],
                        ];

                        $keysForDevelopment[$responseKey] = $roomGeneralAvailability[$checkKey]['availability'];
                        $keysForDevelopment[$responseKeyStopSell] = $roomGeneralAvailability[$checkKey]['stop_sell'];
                    } else {
                        $roomAvailability[$startDate->format('Y-m-d')] = [
                            'key' => $responseKey,
                            'value' => null,
                            'stop_sell' => 0
                        ];

                        $roomStopSell[$startDate->format('Y-m-d')] = [
                            'key' => $responseKeyStopSell,
                            'value' => 0,
                        ];

                        $keysForDevelopment[$responseKey] = rand(1, 10);
                        $keysForDevelopment[$responseKeyStopSell] = 0;
                    }

                    $responseRMKey = 'RMA_' . $generalAvailabilityCheckId . '_' . $room['id'] . '_' . '0' . '_' . $startDate->format('Ymd');
                    $quotaAvailability[$startDate->format('Y-m-d')] = [
                        'key' => $responseRMKey,
                        'value' => $remainingAvailability,
                    ];


                    $startDate = $startDate->addDay();
                }
                $item['room_availability'] = $roomAvailability;
                $item['remaining_availability'] = $quotaAvailability;
                $item['room_stop_sell'] = $roomStopSell;

                // Fill Room Rate Array
                if (isset($room['property_room_rate_mapping'])) {
                    $roomRateMappings = $room['property_room_rate_mapping'];
                    if (isset($params['room_rate_mapping_id'])) {
                        $roomRateMappings = collect($roomRateMappings)
                            ->where('id', '=', $params['room_rate_mapping_id'])
                            ->toArray();
                    }
                    $mapping = [];
                    foreach ($roomRateMappings as $roomRateMapping) {

                        $checkMappingStatus = collect($roomRateMapping['property_room_rate_channel'])
                            ->where('channel_id', '=', $params['channel_id'])
                            ->where('status', '=', 1)
                            ->first();

                        if ($checkMappingStatus) {
                            $roomRateMapping['name'] = $roomRateMapping['property_room_rate']['name'];
                            $roomRateMapping['min_stay'] = $roomRateMapping['property_room_rate']['min_stay'];
                            $roomRateMapping['max_stay'] = $roomRateMapping['property_room_rate']['max_stay'];
                            $roomRateMapping['currency_code'] = $currencyCode;
                            unset($roomRateMapping['property_room_rate']);
                            foreach ($forPriceData as $roomRateAvailabilityCheckId) {
                                $startDate = Carbon::parse($params['start_date']);
                                $prices[$roomRateAvailabilityCheckId['id']]['name'] = $roomRateAvailabilityCheckId['name'];
                                $prices[$roomRateAvailabilityCheckId['id']]['language_key'] = $roomRateAvailabilityCheckId['language_key'];
                                for ($i = 0; $i <= $diffInDays; $i++) {
                                    $checkKey = $roomRateMapping['room_id'] . "|" . $roomRateMapping['id'] . "|" . $roomRateAvailabilityCheckId['id'] . "|" . $startDate->format('Y-m-d');
                                    $responsePRCKey = 'PRC_' . $roomRateAvailabilityCheckId['id'] . '_' . $roomRateMapping['room_id'] . '_' . $roomRateMapping['id'] . '_' . $startDate->format('Ymd');
                                    $responseSTSKey = 'STS_' . $roomRateAvailabilityCheckId['id'] . '_' . $roomRateMapping['room_id'] . '_' . $roomRateMapping['id'] . '_' . $startDate->format('Ymd');
                                    $responseMNSKey = 'MNS_' . $roomRateAvailabilityCheckId['id'] . '_' . $roomRateMapping['room_id'] . '_' . $roomRateMapping['id'] . '_' . $startDate->format('Ymd');

                                    // Fill Price Keys
                                    if (isset($priceArray[$checkKey])) {
                                        $prices[$roomRateAvailabilityCheckId['id']]['price'][$startDate->format('Y-m-d')] = [
                                            'key' => $responsePRCKey,
                                            'value' => $priceArray[$checkKey]['amount'],
                                            'stop_sell' => $priceArray[$checkKey]['stop_sell'],
                                        ];

                                        $prices[$roomRateAvailabilityCheckId['id']]['stop_sell'][$startDate->format('Y-m-d')] = [
                                            'key' => $responseSTSKey,
                                            'value' => $priceArray[$checkKey]['stop_sell'],
                                        ];

                                        $prices[$roomRateAvailabilityCheckId['id']]['min_stay'][$startDate->format('Y-m-d')] = [
                                            'key' => $responseMNSKey,
                                            'value' => $priceArray[$checkKey]['min_stay'],
                                        ];

                                        $keysForDevelopment[$responsePRCKey] = $priceArray[$checkKey]['amount'];
                                    } else {
                                        $prices[$roomRateAvailabilityCheckId['id']]['price'][$startDate->format('Y-m-d')] = [
                                            'key' => $responsePRCKey,
                                            'value' => null,
                                            'stop_sell' => 0
                                        ];

                                        $prices[$roomRateAvailabilityCheckId['id']]['stop_sell'][$startDate->format('Y-m-d')] = [
                                            'key' => $responseSTSKey,
                                            'value' => 0,
                                        ];

                                        $prices[$roomRateAvailabilityCheckId['id']]['min_stay'][$startDate->format('Y-m-d')] = [
                                            'key' => $responseMNSKey,
                                            'value' => 1,
                                        ];

                                        $keysForDevelopment[$responsePRCKey] = rand(1, 10);
                                    }

                                    $startDate = $startDate->addDay();
                                }
                            }
                            $roomRateMapping['prices'] = $prices;
                            $availabilities = [];
                            $prices = [];
                            foreach ($forAvailabilityData as $roomRateAvailabilityCheckId) {
                                $startDate = Carbon::parse($params['start_date']);
                                $availabilities[$roomRateAvailabilityCheckId['id']]['name'] = $roomRateAvailabilityCheckId['name'];
                                $availabilities[$roomRateAvailabilityCheckId['id']]['language_key'] = $roomRateAvailabilityCheckId['language_key'];
                                for ($i = 0; $i <= $diffInDays; $i++) {
                                    $checkKey = $roomRateMapping['room_id'] . "|" . $roomRateMapping['id'] . "|" . $roomRateAvailabilityCheckId['id'] . "|" . $params['channel_id'] . "|" . $startDate->format('Y-m-d');
                                    $responseAVAKey = 'AVA_' . $roomRateAvailabilityCheckId['id'] . '_' . $roomRateMapping['room_id'] . '_' . $roomRateMapping['id'] . '_' . $startDate->format('Ymd');

                                    // Fill Availability Keys
                                    if (isset($availabilityArray[$checkKey])) {
                                        $availabilities[$roomRateAvailabilityCheckId['id']]['availability'][$startDate->format('Y-m-d')] = [
                                            'key' => $responseAVAKey,
                                            'value' => $availabilityArray[$checkKey]['availability'],
                                        ];
                                        $keysForDevelopment[$responseAVAKey] = $availabilityArray[$checkKey]['availability'];
                                    } else {
                                        $availabilities[$roomRateAvailabilityCheckId['id']]['availability'][$startDate->format('Y-m-d')] = [
                                            'key' => $responseAVAKey,
                                            'value' => null,
                                        ];
                                        $keysForDevelopment[$responseAVAKey] = rand(1, 10);
                                    }
                                    $startDate = $startDate->addDay();
                                }
                            }
                            $roomRateMapping['availabilities'] = $availabilities;
                            $mapping[] = $roomRateMapping;
                        }


                    }
                    $item['property_room_rate_mapping'] = $mapping;
                    if ($mapping) {
                        $return[] = $item;
                    }
                }

            }
            //    log::debug(json_encode($keysForDevelopment));
            $response = [
                'status' => true,
                'data' => $return,
            ];

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

        return output($response);
    }


    public function getParamsForPdfInvenyory($params = [])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {


            $criteria = [
                'criteria' => [
                    ['field' => 'token', 'condition' => '=', 'value' => $params['token']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'firstRow' => true
            ];

            $mapping = $this->propertyChannelMappingRepository->findbyCriteria($criteria);
            if (!isset($mapping)) {
                throw new ApiErrorException('Channel mapping not found');
            }


            $startDate = date('Y-m') . "-01";

            $return = [
                'property_id' => $mapping['property_id'],
                'channel_id' => $mapping['channel_id'],
                'start_date' => $startDate,
                'end_date' => Carbon::parse($startDate)->addMonth(6)->format('Y-m-d'),
            ];


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

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

        return output($response);

    }

    public function syncPropertyConnectedRoom($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {


            $deletePropertyRoomConnectedCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']]
                ]
            ];

            $deletePropertyRoomConnected = $this->propertyRoomConnectedRepository->delete($deletePropertyRoomConnectedCriteria);

            if (!empty($params['connected_rooms'])) {

                if (in_array($params['room_id'], $params['connected_rooms'])) {
                    throw new ApiErrorException('The room itself cannot be defined as a connected room.');
                }

                $criteria = [
                    'criteria' => [
                        ['field' => 'status', 'condition' => '=', 'value' => 1],
                        ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ],
                    'whereIn' => [
                        ['field' => 'id', 'value' => $params['connected_rooms']],
                    ]
                ];

                $rooms = $this->propertyRoomRepository->findByCriteria($criteria, ['id', 'name', 'room_type_id', 'max_occupancy', 'max_adult', 'max_child', 'room_size', 'room_size_type', 'room_type_count', 'room_count', 'bathroom_count', 'toilet_count', 'lounge_count', 'max_child_number', 'description']);

                if (count($rooms) != count($params['connected_rooms'])) {
                    throw new ApiErrorException('Connected rooms are not available for this property.');
                }

                foreach ($rooms as $connectedRoom) {

                    $connectedRoomCreateParam = [
                        'property_id' => $params['property_id'],
                        'room_id' => $params['room_id'],
                        'connected_room_id' => $connectedRoom['id'],
                        'created_by' => $params['user_id'],
                        'updated_by' => $params['user_id'],
                    ];

                    $connectedRoomCreate = $this->propertyRoomConnectedRepository->create($connectedRoomCreateParam);

                    if ($connectedRoomCreate['status'] != 'success') {
                        throw new Exception('Could not add connecting rooms.');
                    }

                }

            }

            $response = [
                'status' => true
            ];

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

        return output($response);
    }

}
