<?php

namespace App\Http\Controllers\ChannelManager\ElektraWeb\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 ElektraWebController extends Controller
{


    private $username;
    private $password;

    private $request;
    private $propertyChannelService;
    private $propertyChannelMappingService;
    private $propertyRoomRatePriceService;
    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 = 'elektraweb';
        $this->password = 'XGgK2BSYCERDaVAx';

        $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();
        $payloadJson = json_decode($payload, 1);
        $this->param = $payloadJson;

        $this->channelId = 1;
        $this->channelManagerId = 4; //ElektraWeb

        $getRequestUri = $request->getRequestUri();
        $getRequestUriExplode = explode('/', $getRequestUri);
        $serviceRequestName = last($getRequestUriExplode);

        //channelManagerLogService
        $logArray = ['update-room-availability', 'update-room-rate'];
        $this->channelManagerLogId = null;
        $this->channelManagerRequestTime = microtime(true);
        if (in_array($serviceRequestName, $logArray)) {
            $insertDataLog = [
                'property_id' => $this->param['hotel_id'],
                'channel_manager_id' => $this->channelManagerId,
                'type' => 'C2E',
                'service' => $serviceRequestName,
                'request' => json_encode($payloadJson),
                'ip_address' => $this->request->ip(),
                'response' => null,
                'status' => null
            ];


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

    }

    public function checkAuthentication($username, $password)
    {

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

        if ($this->username != $username || $this->password != $password) {
            $response['message'] = 'Your username or password is incorrect.';
        } else {
            $response['status'] = true;
        }

        return $response;

    }


    public function responseError($errorMessage)
    {

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

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

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

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

        return response()->json($response);

    }

    public function responseSuccess($responseData = null)
    {

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

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

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

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

        return response()->json($response);

    }

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


            //TODO: burada otelinde kendisine bakmak lazım status


            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' => ''];

        //checkAuthentication
        $checkAuthentication = $this->checkAuthentication($this->param['username'], $this->param['password']);
        if (!$checkAuthentication['status']) {
            return $this->responseError($checkAuthentication['message']);
        }

        try {

            $propertyId = $this->param['hotel_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'];


            $response = [];

            $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',
                    'max_adult' => $roomRate['property_room_rate_mapping']['property_room']['max_adult'],
                    'max_child' => $roomRate['property_room_rate_mapping']['property_room']['max_child'],
                    'max_occupancy' => $roomRate['property_room_rate_mapping']['property_room']['max_occupancy'],
                ];

                $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'],
                    'accommodationId' => $roomRate['property_room_rate_mapping']['property_room_rate']['property_room_rate_accommodation']['id'],
                    'included_occupancy' => $roomRate['property_room_rate_mapping']['included_occupancy'],
                ];

            }

            $roomKey = 0;
            $response['rooms'] = [];
            foreach ($roomRates as $roomId => $roomRate) {

                $response['rooms'][$roomKey] = [
                    'id' => $roomId,
                    'room_name' => $roomRate['room']['name'],
                    'max_adult' => $roomRate['room']['max_adult'],
                    'max_child' => $roomRate['room']['max_child'],
                    'max_occupancy' => $roomRate['room']['max_occupancy'],
                ];

                $roomRateKey = 0;
                $response['rooms'][$roomKey]['rates'] = [];
                foreach ($roomRate['rate'] as $roomRateMappingId => $rateData) {

                    $response['rooms'][$roomKey]['rates'][$roomRateKey] = [
                        'id' => $roomRateMappingId,
                        'rate_name' => $rateData['name'] . ' - ' . $rateData['rate'],
                        'board_id' => $rateData['accommodationId'],
                        'board_name' => $rateData['name'],
                        'included_occupancy' => floor($rateData['included_occupancy']),
                    ];

                    $roomRateKey++;

                }

                $roomKey++;
            }

            return $this->responseSuccess($response);


        } 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']) {
            return $this->responseError($response['message']);
        }

    }

    public function updateRoomAvailability(Request $request)
    {

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

        try {

            //checkAuthentication
            $checkAuthentication = $this->checkAuthentication($this->param['username'], $this->param['password']);
            if (!$checkAuthentication['status']) {
                return $this->responseError($checkAuthentication['message']);
            }

            $propertyId = $this->param['hotel_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'];

            $roomAvailabilities = $this->param['rooms'];

            // Merge consecutive dates with same availability and stop_sell
            usort($roomAvailabilities, function ($a, $b) {
                if ($a['room_id'] === $b['room_id']) {
                    return strcmp($a['start_date'], $b['start_date']);
                }
                return $a['room_id'] <=> $b['room_id'];
            });

            $mergedAvailabilities = [];
            $currentAvailability = null;

            foreach ($roomAvailabilities as $availability) {
                if ($currentAvailability === null) {
                    $currentAvailability = $availability;
                    continue;
                }

                $currentEnd = Carbon::parse($currentAvailability['end_date']);
                $nextStart = Carbon::parse($availability['start_date']);

                $isConsecutive = $currentEnd->addDay()->toDateString() === $nextStart->toDateString();

                $sameRoomId = ($currentAvailability['room_id'] === $availability['room_id']);
                $sameAvailability = (isset($currentAvailability['availability']) && isset($availability['availability']) && $currentAvailability['availability'] === $availability['availability']) || (!isset($currentAvailability['availability']) && !isset($availability['availability']));
                $sameStopSell = (isset($currentAvailability['stop_sell']) && isset($availability['stop_sell']) && $currentAvailability['stop_sell'] === $availability['stop_sell']) || (!isset($currentAvailability['stop_sell']) && !isset($availability['stop_sell']));

                if ($isConsecutive && $sameRoomId && $sameAvailability && $sameStopSell) {
                    $currentAvailability['end_date'] = $availability['end_date'];
                } else {
                    $mergedAvailabilities[] = $currentAvailability;
                    $currentAvailability = $availability;
                }
            }

            if ($currentAvailability !== null) {
                $mergedAvailabilities[] = $currentAvailability;
            }

            $roomAvailabilities = $mergedAvailabilities;
            $roomAvailabilitiesCollect = collect($roomAvailabilities);

            DB::beginTransaction();

            $startDate = $roomAvailabilitiesCollect->sortBy('start_date')->first();
            $startDate = $startDate['start_date'];

            $endDate = $roomAvailabilitiesCollect->sortByDesc('end_date')->first();
            $endDate = $endDate['end_date'];

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

            foreach ($roomAvailabilities as $availability) {

                $roomId = $availability['room_id'];

                $roomCheck = $channelPropertyRoomRateCollect->where('property_room_rate_mapping.room_id', $roomId)->isEmpty();
                if ($roomCheck) {
                    throw new ApiErrorException('Undefined or inactive room accommodation');
                }

                $totalInventoryAvailable = null;
                if (isset($availability['availability'])) {
                    $totalInventoryAvailable = $availability['availability'];
                }

                $startDate = Carbon::parse($availability['start_date'])->toDateString();
                $endDate = Carbon::parse($availability['end_date'])->toDateString();

                $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' => $startDate,
                    'end_date' => $endDate,
                    '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($availability['stop_sell']) && !is_null($availability['stop_sell'])) {

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

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

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

                }

            }

            DB::commit();

            return $this->responseSuccess(['confirmCode' => $this->channelManagerLogId]);

        } 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']) {
            return $this->responseError($response['message']);
        }

    }

    public function updateRoomRate(Request $request)
    {

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

        try {

            //checkAuthentication
            $checkAuthentication = $this->checkAuthentication($this->param['username'], $this->param['password']);
            if (!$checkAuthentication['status']) {
                return $this->responseError($checkAuthentication['message']);
            }

            $propertyId = $this->param['hotel_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'];

            $roomRates = $this->param['rooms'];
            $roomRatesCollect = collect($roomRates);

            $paramsListChannel = [];
            $paramsListChannel[] = $this->channelId;

            //CONNECTED CHANNEL RATE UPDATE
            /*$propertyChannelMappingConnectedCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                    ['field' => 'connected_channel_id', 'condition' => '=', 'value' => $this->channelId],
                    ['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


            DB::beginTransaction();

            foreach ($roomRates as $roomRate) {

                $roomId = $roomRate['room_id'];

                $roomCheck = $channelPropertyRoomRateCollect->where('property_room_rate_mapping.room_id', $roomId)->isEmpty();
                if ($roomCheck) {
                    //throw new ApiErrorException('Undefined or inactive room accommodation');
                    continue;
                }

                $rates = $roomRate['rates'];
                if (empty($rates)) {
                    continue;
                }

                // Sort by rate_id and then start_date to ensure we process them in order for each rate_id
                usort($rates, function ($a, $b) {
                    if ($a['rate_id'] === $b['rate_id']) {
                        return strcmp($a['start_date'], $b['start_date']);
                    }
                    return strcmp($a['rate_id'], $b['rate_id']);
                });

                $mergedRates = [];
                $currentRate = null;

                foreach ($rates as $rate) {
                    if ($currentRate === null) {
                        $currentRate = $rate;
                        continue;
                    }

                    $currentEnd = Carbon::parse($currentRate['end_date']);
                    $nextStart = Carbon::parse($rate['start_date']);

                    $isConsecutive = $currentEnd->addDay()->toDateString() === $nextStart->toDateString();

                    $sameRateId = ($currentRate['rate_id'] === $rate['rate_id']);
                    $sameAmount = (isset($currentRate['amount']) && isset($rate['amount']) && (float)$currentRate['amount'] === (float)$rate['amount']) || (!isset($currentRate['amount']) && !isset($rate['amount']));
                    $sameStopSell = (isset($currentRate['stop_sell']) && isset($rate['stop_sell']) && $currentRate['stop_sell'] === $rate['stop_sell']) || (!isset($currentRate['stop_sell']) && !isset($rate['stop_sell']));
                    $sameMinStay = (isset($currentRate['min_stay']) && isset($rate['min_stay']) && $currentRate['min_stay'] === $rate['min_stay']) || (!isset($currentRate['min_stay']) && !isset($rate['min_stay']));

                    if ($isConsecutive && $sameRateId && $sameAmount && $sameStopSell && $sameMinStay) {
                        $currentRate['end_date'] = $rate['end_date'];
                    } else {
                        $mergedRates[] = $currentRate;
                        $currentRate = $rate;
                    }
                }

                if ($currentRate !== null) {
                    $mergedRates[] = $currentRate;
                }


                $roomRatesCollect = collect($mergedRates);

                $startDate = $roomRatesCollect->sortBy('start_date')->first();
                $startDate = $startDate['start_date'];

                $endDate = $roomRatesCollect->sortByDesc('end_date')->first();
                $endDate = $endDate['end_date'];

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

                foreach ($mergedRates as $rate) {

                    $startDate = Carbon::parse($rate['start_date'])->toDateString();
                    $endDate = Carbon::parse($rate['end_date'])->toDateString();

                    $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' => $startDate,
                        'end_date' => $endDate,
                        'include_days' => ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
                    ];


                    $roomRateMappingId = $rate['rate_id'];

                    $isCloseRoomRateMappingSale = null;
                    if (isset($rate['stop_sell'])) {
                        $isCloseRoomRateMappingSale = $rate['stop_sell'] == 1 ? true : false;
                    }


                    $channelRoomRateMappingCheck = $channelPropertyRoomRateCollect->where('room_rate_mapping_id', $roomRateMappingId)->isEmpty();
                    if ($channelRoomRateMappingCheck) {
                        //throw new ApiErrorException('Undefined or inactive room accommodation');
                        continue;
                    }

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

                    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($rate['amount'])) {

                            $currency = $this->param['currency'];

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

                            if (!$currencyCheck) {
                                throw new ApiErrorException('Exchange rate that does not match the channel exchange rate, channel exchange rate: ' . $propertyChannelMapping['currency_code']);
                            }

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

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

                            $requestParams['channel_id'] = $paramChannelId;
                            $requestParams['ip_address'] = $this->request->ip();

                            $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;
                            $requestParams['ip_address'] = $this->request->ip();

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

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


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

                            //Minimum Konaklama Gün Sayısı
                            if (isset($rate['min_stay'])) {

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

                                $requestParams['channel_id'] = $paramChannelId;
                                $requestParams['ip_address'] = $this->request->ip();

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

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


                            }

                        }

                    }


                }
            }

            DB::commit();


            return $this->responseSuccess(['confirmCode' => $this->channelManagerLogId]);

        } 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']) {
            return $this->responseError($response['message']);
        }

    }


}
