<?php

namespace App\Http\Controllers\ChannelManager\Reseliva\v1;

use App\Core\Service\PropertyChannelService;
use App\Core\Service\PropertyChannelMappingService;
use App\Core\Service\PropertyRoomRateChannelMappingService;
use App\Core\Service\PropertyRoomRatePriceService;
use App\Core\Service\PropertyRoomAvailabilityService;
use App\Core\Service\PropertyRoomService;
use App\Core\Service\BookingService;
use App\Core\Service\ChannelManagerLogService;
use App\Core\Service\ChannelManagerPropertyMappingService;
use App\Http\Controllers\Controller;
use Carbon\Carbon;
use Illuminate\Http\Request;

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

class ReselivaController extends Controller
{


    private $username;
    private $password;

    private $request;
    private $propertyChannelService;
    private $propertyChannelMappingService;
    private $propertyRoomRatePriceService;
    private $serviceRequestName;
    private $param;
    private $channelId;
    private $channelManagerLogId;
    private $channelManagerRequestTime;


    public function __construct(
        Request $request,
        PropertyChannelService $propertyChannelService,
        PropertyChannelMappingService $propertyChannelMappingService,
        PropertyRoomRateChannelMappingService $propertyRoomRateChannelMappingService,
        PropertyRoomRatePriceService $propertyRoomRatePriceService,
        PropertyRoomAvailabilityService $propertyRoomAvailabilityService,
        PropertyRoomService $propertyRoomService,
        BookingService $bookingService,
        ChannelManagerPropertyMappingService $channelManagerPropertyMappingService,
        ChannelManagerLogService $channelManagerLogService
    )
    {

        //Note: channel_manager_property_mapping tablosunda channel_manager_property_id alanı NULL ise, bu ENW nin CHANNEL tarafından yönetiliyor olması demek.
        //Eğer channel_manager_property_id alanında bir otel id var ise, bu CHANNEL ın ENW tarafından güncelleniyor olması demek.

        $this->username = 'reseliva';
        $this->password = 'e3HYUTUSGcPwIRzV';

        $this->request = $request;
        $this->propertyChannelService = $propertyChannelService;
        $this->propertyChannelMappingService = $propertyChannelMappingService;
        $this->propertyRoomRateChannelMappingService = $propertyRoomRateChannelMappingService;
        $this->propertyRoomRatePriceService = $propertyRoomRatePriceService;
        $this->propertyRoomAvailabilityService = $propertyRoomAvailabilityService;
        $this->propertyRoomService = $propertyRoomService;
        $this->bookingService = $bookingService;
        $this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService;
        $this->channelManagerLogService = $channelManagerLogService;

        $payload = $this->request->getContent();
        $payloadXML = simplexml_load_string($payload);
        $payloadParam = json_decode(json_encode($payloadXML), 1);

        $serviceRequestName = str_replace('RQ', '', $payloadXML->getName());
        $this->serviceRequestName = $serviceRequestName;

        $this->param = $payloadParam;

        $this->channelId = 1;
        $this->channelManagerId = 1; //Reseliva, TODO: burada mapping yapılmış mı yapılmamış mı kontrol edilmeli, her şey verilmemeli


        //channelManagerLogService
        $this->channelManagerLogId = null;
        $this->channelManagerRequestTime = microtime(true);
        $insertDataLog = [
            'property_id' => $this->param['Hotel']['@attributes']['id'],
            'channel_manager_id' => $this->channelManagerId,
            'type' => 'C2E',
            'service' => $serviceRequestName,
            'request' => $payload,
            'response' => null,
            'ip_address' => $this->request->ip(),
            'status' => null
        ];

        $channelManagerLog = $this->channelManagerLogService->create($insertDataLog);
        if ($channelManagerLog['status'] == 'success') {
            $this->channelManagerLogId = $channelManagerLog['data']['id'];
        }
        //channelManagerLogService


        //Authentication
        $errors = [];
        if ($this->username != $payloadParam['Authentication']['@attributes']['username'] || $this->password != $payloadParam['Authentication']['@attributes']['password']) {
            $errors[] = [
                //'code' => 100,
                'message' => 'Your username or password is incorrect.'
            ];
        }

        if (!empty($errors)) {
            $this->responseError($errors);
        }


    }


    public function responseError($errors)
    {

        $serviceRequestName = $this->serviceRequestName;
        $xmlResponse = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><' . $serviceRequestName . 'RS></' . $serviceRequestName . 'RS>');

        foreach ($errors as $error) {
            $xmlResponseError = $xmlResponse->addChild('Error', $error['message']);
            if (isset($error['code'])) {
                $xmlResponseError->addAttribute('code', $error['code']);
            }
        }

        //channelManagerLogService
        if (!is_null($this->channelManagerLogId)) {
            $updateDataLog = [
                'response' => $xmlResponse->asXML(),
                'status' => 0
            ];

            if (!is_null($this->channelManagerRequestTime)) {
                $updateDataLog['response_time'] = microtime(true) - $this->channelManagerRequestTime;
            }

            $channelManagerLog = $this->channelManagerLogService->update($this->channelManagerLogId, $updateDataLog);
        }
        //channelManagerLogService


        echo $xmlResponse->asXML();

        die();
    }

    public function responseSuccess($xmlPayload)
    {

        //channelManagerLogService
        if (!is_null($this->channelManagerLogId)) {
            $updateDataLog = [
                'response' => $xmlPayload->asXML(),
                'status' => 1
            ];

            if (!is_null($this->channelManagerRequestTime)) {
                $updateDataLog['response_time'] = microtime(true) - $this->channelManagerRequestTime;
            }

            $channelManagerLog = $this->channelManagerLogService->update($this->channelManagerLogId, $updateDataLog);
        }
        //channelManagerLogService

        echo $xmlPayload->asXML();

        die();
    }

    public function propertyChannelMapping($propertyId)
    {

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

        try {

            $propertyChannelMappingCriteria = [
                'criteria' => [
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $this->channelId],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'firstRow' => true
            ];


            $propertyChannelMapping = $this->propertyChannelMappingService->select($propertyChannelMappingCriteria);

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

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


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

        return $response;

    }

    public function channelPropertyRoomRate($propertyId)
    {

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

        try {

            $requestParam = [
                'criteria' => [
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $this->channelId],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'with' => [
                    'propertyRoomRateMapping.propertyRoomRate.propertyRoomRateAccommodation',
                    'propertyRoomRateMapping.propertyRoom.propertyRoomType',
                ]
            ];

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

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

            $getChannelPropertyRoomRate['data'] = collect($getChannelPropertyRoomRate['data'])->where('property_room_rate_mapping.property_room.status',1)->toArray();

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


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

        return $response;

    }

    public function channelManagerPropertyCheck($propertyId)
    {

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

        try {

            $requestParam =
                [
                    'criteria' =>
                        [
                            ['field' => 'status', 'condition' => '=', 'value' => 1],
                            ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                            ['field' => 'channel_manager_id', 'condition' => '=', 'value' => $this->channelManagerId],
                        ],
                    'firstRow' => true
                ];

            $channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($requestParam);


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

            $channelManagerPropertyMapping = $channelManagerPropertyMapping['data'];

            if (!is_null($channelManagerPropertyMapping['channel_manager_property_id'])) {
                throw new ApiErrorException('This hotel can only be updated by ENW');
            }

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


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

        return $response;

    }


    public function roomRate(Request $request)
    {

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

        try {

            $propertyId = $this->param['Hotel']['@attributes']['id'];

            $channelManagerPropertyCheck = $this->channelManagerPropertyCheck($propertyId);
            if (!$channelManagerPropertyCheck['status']) {
                throw new ApiErrorException($channelManagerPropertyCheck['message']);
            }


            $channelPropertyRoomRate = $this->channelPropertyRoomRate($propertyId);
            if (!$channelPropertyRoomRate['status']) {
                throw new ApiErrorException($channelPropertyRoomRate['message']);
            }

            $channelPropertyRoomRate = $channelPropertyRoomRate['data'];


            $propertyChannelMapping = $this->propertyChannelMapping($propertyId);
            if (!$propertyChannelMapping['status']) {
                throw new ApiErrorException($propertyChannelMapping['message']);
            }

            $propertyChannelMapping = $propertyChannelMapping['data'];


            $serviceRequestName = $this->serviceRequestName;
            $xmlResponse = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><' . $serviceRequestName . 'RS></' . $serviceRequestName . 'RS>');

            $ProductList = $xmlResponse->addChild('ProductList');

            $ProductListHotel = $ProductList->addChild('Hotel');
            $ProductListHotel->addAttribute('id', $propertyId);
            $ProductListHotel->addAttribute('currency', $propertyChannelMapping['currency_code']);
            $ProductListHotel->addAttribute('child_age_group_number', 1); //TODO:


            $roomRates = [];
            foreach ($channelPropertyRoomRate as $roomRate) {

                if ($roomRate['property_room_rate_mapping']['property_room_rate']['name'] == 'Best Available Rate') {
                    continue;
                }

                $roomRates[$roomRate['property_room_rate_mapping']['room_id']]['room'] = [
                    'id' => $roomRate['property_room_rate_mapping']['property_room']['id'],
                    'name' => $roomRate['property_room_rate_mapping']['property_room']['name'],
                    'status' => 'Active',
                    'capacity' => $roomRate['property_room_rate_mapping']['property_room']['max_adult'],
                    'capacity_child' => $roomRate['property_room_rate_mapping']['property_room']['max_child'],
                ];

                $roomRates[$roomRate['property_room_rate_mapping']['room_id']]
                ['rate'][$roomRate['property_room_rate_mapping']['id']] = [
                    'id' => $roomRate['property_room_rate_mapping']['id'],
                    'name' => $roomRate['property_room_rate_mapping']['property_room_rate']['property_room_rate_accommodation']['name'],
                    'rate' => $roomRate['property_room_rate_mapping']['property_room_rate']['name']
                ];

            }

            foreach ($roomRates as $roomId => $roomRate) {

                $RoomType = $ProductList->addChild('RoomType');
                $RoomType->addAttribute('id', $roomId);
                $RoomType->addAttribute('name', $roomRate['room']['name']);
                $RoomType->addAttribute('status', $roomRate['room']['status']);
                $RoomType->addAttribute('capacity', $roomRate['room']['capacity']);
                $RoomType->addAttribute('capacity_child', $roomRate['room']['capacity_child']);

                foreach ($roomRate['rate'] as $roomRateMappingId => $rate) {
                    $RatePlan = $RoomType->addChild('RatePlan');
                    $RatePlan->addAttribute('id', $roomRateMappingId);
                    $RatePlan->addAttribute('name', $rate['name'] . ' - ' . $rate['rate']);
                }

            }

            $this->responseSuccess($xmlResponse);


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

        if (!$response['status']) {
            $errors[] = [
                'message' => $response['message']
            ];

            $this->responseError($errors);

        }

    }

    public function availabilityRateUpdate(Request $request)
    {

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

        try {

            $propertyId = $this->param['Hotel']['@attributes']['id'];

            $channelManagerPropertyCheck = $this->channelManagerPropertyCheck($propertyId);
            if (!$channelManagerPropertyCheck['status']) {
                throw new ApiErrorException($channelManagerPropertyCheck['message']);
            }

            $channelPropertyRoomRate = $this->channelPropertyRoomRate($propertyId);
            if (!$channelPropertyRoomRate['status']) {
                throw new ApiErrorException($channelPropertyRoomRate['message']);
            }

            $channelPropertyRoomRate = $channelPropertyRoomRate['data'];
            $channelPropertyRoomRateCollect = collect($channelPropertyRoomRate);


            $propertyChannelMapping = $this->propertyChannelMapping($propertyId);
            if (!$propertyChannelMapping['status']) {
                throw new ApiErrorException($propertyChannelMapping['message']);
            }

            $propertyChannelMapping = $propertyChannelMapping['data'];

            $availRateUpdates = singleElementXMLArray($this->param['AvailRateUpdate']);


            DB::beginTransaction();


            foreach ($availRateUpdates as $availRateUpdate) {

                $dateRange = [];
                $dateRange['startDate'] = $availRateUpdate['DateRange']['@attributes']['from'];
                $dateRange['finishDate'] = $availRateUpdate['DateRange']['@attributes']['to'];

                if (Carbon::parse($dateRange['startDate'])->isBefore(Carbon::now()->toDateString()) || Carbon::parse($dateRange['finishDate'])->isBefore(Carbon::now()->toDateString())) {
                    throw new ApiErrorException('Dates to be updated cannot be earlier than today');
                }

                $roomTypes = singleElementXMLArray($availRateUpdate['RoomType']);

                foreach ($roomTypes as $roomType) {

                    $roomId = $roomType['@attributes']['id'];

                    $roomCheck = $channelPropertyRoomRateCollect->where('property_room_rate_mapping.room_id', $roomId)->isEmpty();
                    if ($roomCheck) {
                        throw new ApiErrorException('Tanımlı ya da aktif olmayan oda');
                    }


                    $totalInventoryAvailable = null;
                    if (isset($roomType['Inventory']['@attributes']['totalInventoryAvailable'])) {
                        $totalInventoryAvailable = $roomType['Inventory']['@attributes']['totalInventoryAvailable'];
                    }


                    $requestParamBase = [
                        'property_id' => fillOnUndefined($propertyChannelMapping, 'property_id'),
                        'channel_id' => fillOnUndefined($propertyChannelMapping, 'channel_id'),
                        'availability_type_id' => fillOnUndefined($propertyChannelMapping, 'property_availability_type_id', 1),
                        'start_date' => $dateRange['startDate'],
                        'end_date' => $dateRange['finishDate'],
                        'include_days' => ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
                    ];


                    if (!is_null($totalInventoryAvailable)) {

                        $requestParams = [];
                        $requestParams = $requestParamBase;
                        $requestParams['update_type'] = 'availability';
                        $requestParams['value'] = $totalInventoryAvailable;
                        $requestParams['room_rates'] = [
                            ['room_id' => $roomId]
                        ];

                        $propertyRoomRateMapping = $this->propertyRoomAvailabilityService->bulkUpdate($requestParams);

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

                    }


                    if (isset($roomType['RatePlan'])) {

                        $ratePlans = singleElementXMLArray($roomType['RatePlan']);

                        foreach ($ratePlans as $ratePlan) {

                            $roomRateMappingId = $ratePlan['@attributes']['id'];

                            $isCloseRoomRateMappingSale = null;
                            if (isset($ratePlan['@attributes']['closed'])) {
                                $isCloseRoomRateMappingSale = $ratePlan['@attributes']['closed'] == 'true' ? true : false;
                            }

                            $channelRoomRateMappingCheck = $channelPropertyRoomRateCollect->where('room_rate_mapping_id', $roomRateMappingId)->isEmpty();
                            if ($channelRoomRateMappingCheck) {
                                throw new ApiErrorException('Tanımlı ya da aktif olmayan oda konaklama');
                            }


                            $roomRates = [];
                            $roomRates[] = [
                                'room_id' => $roomId,
                                'room_rate_mapping_id' => [
                                    $roomRateMappingId
                                ]
                            ];


                            $paramsListChannel = [];
                            $paramsListChannel[] = 1;
                            //CONNECTED CHANNEL RATE UPDATE
                            $propertyChannelMappingConnectedCriteria = [
                                'criteria' => [
                                    ['field' => 'property_id', 'condition' => '=', 'value' => $requestParamBase['property_id']],
                                    ['field' => 'connected_channel_id', 'condition' => '=', 'value' => $requestParamBase['channel_id']],
                                    ['field' => 'channel_id', 'condition' => '=', 'value' => 5],//JUST CM
                                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                                ],
                                'with' => ['channel']
                            ];

                            $propertyChannelMappingConnected = $this->propertyChannelMappingService->select($propertyChannelMappingConnectedCriteria);
                            if ($propertyChannelMappingConnected['status'] == 'success') {

                                foreach ($propertyChannelMappingConnected['data'] as $channel) {

                                    if (!is_null($channel['channel']['parent_id'])) {
                                        continue;
                                    }

                                    $paramsListChannel[] = $channel['channel_id'];

                                }

                            }
                            //CONNECTED CHANNEL RATE UPDATE


                            foreach ($paramsListChannel as $paramChannelId) {


                                //Eğer Rate var ise currency check yapılmalı ve PerDay var mı check edilmeli, burada sonra günceleme yaptırılabilri
                                if (isset($ratePlan['Rate'])) {

                                    $currency = $ratePlan['Rate']['@attributes']['currency'];

                                    $currencyCheck = ($currency == $propertyChannelMapping['currency_code']) ? true : false;

                                    if (!$currencyCheck) {
                                        throw new ApiErrorException('Kanal döviz kuru ile eşleşmeyen döviz kuru, kanal döviz kuru: ' . $propertyChannelMapping['currency_code']);
                                    }

                                    $channelRoomRateMapping = $channelPropertyRoomRateCollect->where('room_rate_mapping_id', $roomRateMappingId)->first();


                                    $amountPerDay = $ratePlan['Rate']['PerDay']['@attributes']['rate'];

                                    $requestParams = [];
                                    $requestParams = $requestParamBase;
                                    $requestParams['update_type'] = 'rate';
                                    $requestParams['value'] = $amountPerDay;
                                    $requestParams['room_rates'] = $roomRates;

                                    $requestParams['channel_id'] = $paramChannelId;

                                    $propertyRoomRateMapping = $this->propertyRoomRatePriceService->bulkUpdate($requestParams);

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

                                }


                                //Room Rate Stop Sale
                                if (!is_null($isCloseRoomRateMappingSale)) {
                                    $requestParams = [];
                                    $requestParams = $requestParamBase;
                                    $requestParams['update_type'] = 'rate_stop_sell';
                                    $requestParams['value'] = $isCloseRoomRateMappingSale ? 1 : 0;
                                    $requestParams['room_rates'] = $roomRates;

                                    $requestParams['channel_id'] = $paramChannelId;

                                    $propertyRoomRateMapping = $this->propertyRoomRatePriceService->bulkUpdate($requestParams);

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


                                //Kısıtlamalar var ise min los
                                if (isset($ratePlan['Restrictions'])) {

                                    //Minimum Konaklama Gün Sayısı
                                    if (isset($ratePlan['Restrictions']['@attributes']['minLOS'])) {

                                        $minStay = $ratePlan['Restrictions']['@attributes']['minLOS'];

                                        $requestParams = [];
                                        $requestParams = $requestParamBase;
                                        $requestParams['update_type'] = 'min_stay';
                                        $requestParams['value'] = $minStay;
                                        $requestParams['room_rates'] = $roomRates;

                                        $requestParams['channel_id'] = $paramChannelId;

                                        $propertyRoomRateMapping = $this->propertyRoomRatePriceService->bulkUpdate($requestParams);

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


                                    }

                                }

                            }


                        }

                    }


                }

            }

            DB::commit();

            $serviceRequestName = $this->serviceRequestName;
            $xmlResponse = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><' . $serviceRequestName . 'RS></' . $serviceRequestName . 'RS>');

            $xmlResponse->addChild('Success');
            $xmlResponse->addChild('ConfirmCode', $this->channelManagerLogId);

            $this->responseSuccess($xmlResponse);

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

        DB::rollBack();

        if (!$response['status']) {
            $errors[] = [
                'message' => $response['message']
            ];

            $this->responseError($errors);

        }

    }

    public function availabilityRate(Request $request)
    {

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

        try {

            $propertyId = $this->param['Hotel']['@attributes']['id'];

            $channelManagerPropertyCheck = $this->channelManagerPropertyCheck($propertyId);
            if (!$channelManagerPropertyCheck['status']) {
                throw new ApiErrorException($channelManagerPropertyCheck['message']);
            }

            $startDate = $this->param['ParamSet']['AvailRateRetrieval']['@attributes']['from'];
            $finishDate = $this->param['ParamSet']['AvailRateRetrieval']['@attributes']['to'];


            $channelPropertyRoomRate = $this->channelPropertyRoomRate($propertyId);
            if (!$channelPropertyRoomRate['status']) {
                throw new ApiErrorException($channelPropertyRoomRate['message']);
            }

            $channelPropertyRoomRate = $channelPropertyRoomRate['data'];


            $propertyChannelMapping = $this->propertyChannelMapping($propertyId);
            if (!$propertyChannelMapping['status']) {
                throw new ApiErrorException($propertyChannelMapping['message']);
            }

            $propertyChannelMapping = $propertyChannelMapping['data'];


            $requestParams = [
                'property_id' => $propertyId,
                'room_id' => null,
                'room_rate_mapping_id' => null,
                'channel_id' => $this->channelId,
                'start_date' => $startDate,
                'end_date' => $finishDate,

            ];

            $propertyRoomType = $this->propertyRoomService->getPropertyRoomInventory($requestParams);
            if ($propertyRoomType['status'] != 'success') {
                throw new ApiErrorException($propertyRoomType['message']);
            }

            $propertyRoomType = $propertyRoomType['data'];
            $propertyRoomRateAvailability = collect($propertyRoomType);


            $roomRates = [];
            foreach ($propertyRoomRateAvailability as $room) {

                foreach ($room['property_room_rate_mapping'] as $roomRateMapping) {


                    foreach ($room['room_availability'] as $date => $roomAvailability) {
                        $roomRates[$room['id']]['availability'][$date] = $roomAvailability['value'];
                    }

                    $roomRates[$room['id']]['rate'][$roomRateMapping['id']] = [
                        'roomName' => $room['name'],
                        'roomRateName' => $roomRateMapping['name'],
                        //'minStay' =>  $roomRateMapping['min_stay'],
                        //'maxStay' =>  $roomRateMapping['max_stay'],
                        'currencyCode' => $roomRateMapping['currency_code'],
                    ];


                    $roomRatePrices = reset($roomRateMapping['prices']);
                    foreach ($roomRatePrices['price'] as $date => $roomRatePrice) {
                        $roomRates[$room['id']]['rate'][$roomRateMapping['id']]['price'][$date] = $roomRatePrice['value'];
                        $roomRates[$room['id']]['rate'][$roomRateMapping['id']]['stopSell'][$date] = $roomRatePrice['stop_sell'];
                    }

                    foreach ($roomRatePrices['stop_sell'] as $date => $stopSell) {
                        $roomRates[$room['id']]['rate'][$roomRateMapping['id']]['stopSell'][$date] = $stopSell['value'];
                    }

                    foreach ($roomRatePrices['min_stay'] as $date => $minStay) {
                        $roomRates[$room['id']]['rate'][$roomRateMapping['id']]['minstay'][$date] = $minStay['value'];
                    }

                }
            }

            $serviceRequestName = $this->serviceRequestName;
            $xmlResponse = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><' . $serviceRequestName . 'RS></' . $serviceRequestName . 'RS>');

            $AvailRateList = $xmlResponse->addChild('AvailRateList');

            $AvailRateListHotel = $AvailRateList->addChild('Hotel');
            $AvailRateListHotel->addAttribute('id', $propertyId);


            $diffInDays = Carbon::parse($startDate)->diffInDays(Carbon::parse($finishDate));

            if ($diffInDays > 180) {
                throw new ApiErrorException('A maximum of 180 days of data can be retrieved.');
            }

            $currentDate = $startDate;
            for ($i = 0; $i <= $diffInDays; $i++) {

                //Burada her roomid, roomratemappingid, availability, stopsell, kur, fiyat hepsi var ise kayda girece

                $AvailRate = $AvailRateList->addChild('AvailRate');
                $AvailRate->addAttribute('date', $currentDate);


                foreach ($roomRates as $roomId => $roomRateMapping) {

                    $RoomType = $AvailRate->addChild('RoomType');
                    $RoomType->addAttribute('id', $roomId);

                    $Inventory = $RoomType->addChild('Inventory');
                    $Inventory->addAttribute('totalInventoryAvailable', $roomRateMapping['availability'][$currentDate]);

                    foreach ($roomRateMapping['rate'] as $roomRateMappingId => $roomRate) {


                        $RatePlan = $RoomType->addChild('RatePlan');
                        $RatePlan->addAttribute('id', $roomRateMappingId);
                        $RatePlan->addAttribute('closed', $roomRate['stopSell'][$currentDate] == 1 ? 'true' : 'false');


                        $Rate = $RatePlan->addChild('Rate');
                        $Rate->addAttribute('currency', $roomRate['currencyCode']);

                        $PerDay = $Rate->addChild('PerDay');
                        $PerDay->addAttribute('rate', $roomRate['price'][$currentDate]);

                        $Restrictions = $RatePlan->addChild('Restrictions');
                        $Restrictions->addAttribute('minLOS', $roomRate['minstay'][$currentDate]);


                    }


                }


                $currentDate = Carbon::parse($currentDate)->addDay()->toDateString();


            }


            $this->responseSuccess($xmlResponse);


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

        if (!$response['status']) {
            $errors[] = [
                'message' => $response['message']
            ];

            $this->responseError($errors);

        }

    }


    public function booking(Request $request, $param = [])
    {

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

        try {

            $propertyId = $this->param['Hotel']['@attributes']['id'];
            $bookingId = $this->param['Booking']['@attributes']['id'];
            $type = $this->param['Booking']['@attributes']['type'];

            if (!in_array($type, ['Book', 'Modify', 'Cancel'])) {
                throw new ApiErrorException('Unknown process type:' . $type);
            }


            $this->serviceRequestName = 'BookingRetrieval';

            $channelPropertyRoomRate = $this->channelPropertyRoomRate($propertyId);
            if (!$channelPropertyRoomRate['status']) {
                throw new ApiErrorException($channelPropertyRoomRate['message']);
            }

            $channelPropertyRoomRate = $channelPropertyRoomRate['data'];


            $propertyChannelMapping = $this->propertyChannelMapping($propertyId);
            if (!$propertyChannelMapping['status']) {
                throw new ApiErrorException($propertyChannelMapping['message']);
            }

            $propertyChannelMapping = $propertyChannelMapping['data'];


            $requestData = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $bookingId],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                ],
                'with' => ['bookingContact', 'bookingChannel', 'bookingPayment', 'bookingPaymentType', 'bookingStatus', 'bookingRoom.roomPax.paxCountry'],
                'firstRow' => true
            ];

            $bookingDetail = $this->bookingService->select($requestData);

            if ($bookingDetail['status'] != 'success') {
                throw new ApiErrorException('Property Booking Data not found');
            }

            $bookingDetail = $bookingDetail['data'];

            $serviceRequestName = 'BookingRetrieval';
            $xmlResponse = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><' . $serviceRequestName . 'RS></' . $serviceRequestName . 'RS>');


            if (in_array($bookingDetail['status'], [0, 3])) {

                $Bookings = $xmlResponse->addChild('Bookings');
                $Booking = $Bookings->addChild('Booking');

                $Booking->addAttribute('id', $bookingDetail['id']);
                $Booking->addAttribute('type', 'Cancel');
                $Booking->addAttribute('cancelDateTime', Carbon::createFromTimestamp($bookingDetail['updated_at'])->toISOString());

                $Hotel = $Booking->addChild('Hotel');
                $Hotel->addAttribute('id', $bookingDetail['property_id']);

                foreach ($bookingDetail['booking_room'] as $room) {

                    $RoomStay = $Booking->addChild('RoomStay');
                    $RoomStay->addAttribute('roomTypeID', $room['room_id']);
                    $RoomStay->addAttribute('ratePlanID', $room['room_rate_mapping_id']);

                    $StayDate = $RoomStay->addChild('StayDate');
                    $StayDate->addAttribute('arrival', $room['checkin_date']);
                    $StayDate->addAttribute('departure', $room['checkout_date']);

                }

            } else {


                $Bookings = $xmlResponse->addChild('Bookings');
                $Booking = $Bookings->addChild('Booking');

                $Booking->addAttribute('id', $bookingDetail['id']);

                //Book ve Modify Aynı olacak, Cancel
                if ($type == 'Book') {
                    $Booking->addAttribute('type', 'Book');
                    $Booking->addAttribute('createDateTime', Carbon::createFromTimestamp($bookingDetail['created_at'])->toISOString());
                }

                if ($type == 'Modify') {
                    $Booking->addAttribute('type', 'Modify');
                    $Booking->addAttribute('modifyDateTime', Carbon::createFromTimestamp($bookingDetail['updated_at'])->toISOString());
                }

                $Hotel = $Booking->addChild('Hotel');
                $Hotel->addAttribute('id', $bookingDetail['property_id']);


                foreach ($bookingDetail['booking_room'] as $room) {

                    $RoomStay = $Booking->addChild('RoomStay');
                    $RoomStay->addAttribute('roomTypeID', $room['room_id']);
                    $RoomStay->addAttribute('ratePlanID', $room['room_rate_mapping_id']);

                    $StayDate = $RoomStay->addChild('StayDate');
                    $StayDate->addAttribute('arrival', $room['checkin_date']);
                    $StayDate->addAttribute('departure', $room['checkout_date']);


                    $roomPaxCollect = collect($room['room_pax']);

                    $GuestCount = $RoomStay->addChild('GuestCount');
                    $GuestCount->addAttribute('adult', $roomPaxCollect->where('type', 'ADT')->count());

                    $diffInDays = Carbon::parse($room['checkin_date'])->diffInDays(Carbon::parse($room['checkout_date']));

                    //dd($room['total'], $diffInDays, $room);

                    $PerDayRates = $RoomStay->addChild('PerDayRates');
                    $PerDayRates->addAttribute('currency', $room['currency_code']);

                    $baseRateDaily = moneyDoubleFormatDecimal($room['total'] / $diffInDays);

                    $currentDate = $room['checkin_date'];
                    for ($i = 0; $i < $diffInDays; $i++) {
                        $PerDayRate = $PerDayRates->addChild('PerDayRate');
                        $PerDayRate->addAttribute('stayDate', $currentDate);
                        $PerDayRate->addAttribute('baseRate', $baseRateDaily);
                        $PerDayRate->addAttribute('hotelServiceFees', 0);

                        $currentDate = Carbon::parse($currentDate)->addDay()->toDateString();
                    }

                    $Total = $RoomStay->addChild('Total');
                    $Total->addAttribute('amountAfterTaxes', $room['total']);
                    $Total->addAttribute('amountOfTaxes', 0);
                    $Total->addAttribute('currency', $room['currency_code']);

                    $RoomStay->addChild('RoomNotes', $bookingDetail['booking_contact']['note']);

                }


                $PrimaryGuest = $Booking->addChild('PrimaryGuest');

                $Name = $PrimaryGuest->addChild('Name');
                $Name->addAttribute('givenName', $bookingDetail['booking_contact']['name']);
                $Name->addAttribute('surname', $bookingDetail['booking_contact']['surname']);

                $Phone = $PrimaryGuest->addChild('Phone');
                $Phone->addAttribute('countryCode', $bookingDetail['booking_contact']['phone_code']);
                //$Phone->addAttribute('cityAreaCode');
                $Phone->addAttribute('number', $bookingDetail['booking_contact']['phone_number']);

                $PrimaryGuest->addChild('Email', $bookingDetail['booking_contact']['email']);


                $Total = $Booking->addChild('Total');
                $Total->addAttribute('amountAfterTaxes', $bookingDetail['total']);
                $Total->addAttribute('amountOfTaxes', 0);
                $Total->addAttribute('currency', $bookingDetail['currency_code']);


                $Booking->addChild('SpecialRequest');
                $Booking->addChild('BookingNotes', $bookingDetail['booking_contact']['note']);


            }


            $this->responseSuccess($xmlResponse);


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

        if (!$response['status']) {
            $errors[] = [
                'message' => $response['message']
            ];

            $this->responseError($errors);

        }

    }


}
