<?php

namespace App\Core\Service;

use App\Core\Repository\PropertyPromotion\PropertyPromotionRepository;
use App\Core\Repository\PromotionType\PromotionTypeRepository;
use App\Core\Repository\PropertyPromotionMapping\PropertyPromotionMappingRepository;
use App\Core\Repository\PropertyRoom\PropertyRoomRepository;
use App\Core\Validator\PropertyPromotion\PropertyPromotionAddValidator;
use App\Core\Validator\PropertyPromotion\PropertyPromotionUpdateValidator;
use App\Core\Validator\PropertyPromotion\UpdateRoomRateChannelPromotionValidator;


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

class PropertyPromotionService
{

    private $propertyPromotionRepository;
    private $promotionTypeRepository;
    private $propertyPromotionMappingRepository;
    private $propertyRoomRepository;
    private $propertyPromotionAddValidator;
    private $propertyPromotionUpdateValidator;
    private $updateRoomRateChannelPromotionValidator;


    public function __construct(
        PropertyPromotionRepository $propertyPromotionRepository,
        PromotionTypeRepository $promotionTypeRepository,
        PropertyPromotionMappingRepository $propertyPromotionMappingRepository,
        PropertyRoomRepository $propertyRoomRepository,
        PropertyPromotionUpdateValidator $propertyPromotionUpdateValidator,
        UpdateRoomRateChannelPromotionValidator $updateRoomRateChannelPromotionValidator,
        PropertyPromotionAddValidator $propertyPromotionAddValidator

    )
    {
        $this->promotionTypeRepository = $promotionTypeRepository;
        $this->propertyPromotionRepository = $propertyPromotionRepository;
        $this->propertyPromotionMappingRepository = $propertyPromotionMappingRepository;
        $this->propertyRoomRepository = $propertyRoomRepository;
        $this->propertyPromotionAddValidator = $propertyPromotionAddValidator;
        $this->propertyPromotionUpdateValidator = $propertyPromotionUpdateValidator;
        $this->updateRoomRateChannelPromotionValidator = $updateRoomRateChannelPromotionValidator;
    }

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

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

        try {

            $data = $this->propertyPromotionRepository->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 selectPropertyPromotionMapping($param = [], $column = ['*'])
    {

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

        try {

            $data = $this->propertyPromotionMappingRepository->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 getPromotionTypeList($params)
    {

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

            $promotionTypeRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'parent_id', 'condition' => '=', 'value' => fillOnUndefined($params, 'parent_id', null)],

                ],
            ];
            $promotionType = $this->promotionTypeRepository->findByCriteria($promotionTypeRequest, ['id', 'name', 'language_key', 'parent_id', 'type_code', 'order_number', 'status']);

            $promotionType = $promotionType ? $promotionType : [];

            array_multisort(
                array_column($promotionType, 'order_number'), SORT_ASC,
                array_column($promotionType, 'name'), SORT_ASC,
                $promotionType
            );

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

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

        return output($response);
    }

    public function getPropertyPromotionList($params)
    {

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

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

                ],
            ];
            $propertyPromotion = $this->propertyPromotionRepository->findByCriteria($propertyPromotionRequest,
                ['id', 'property_id','title', 'promotion_type_id', 'start_date', 'end_date', 'reservation_start_date', 'reservation_end_date',
                    'is_time', 'start_time', 'end_time', 'day_before', 'amount', 'min_stay', 'days', 'is_mobile', 'params', 'exclude_dates','detail', 'status']
            );

            $propertyPromotion = $propertyPromotion ? $propertyPromotion : [];

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

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

        return output($response);
    }

    public function createPropertyPromotion($params)
    {

        $response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];
        try {
            DB::beginTransaction();

            $promotionTypeRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => fillOnUndefined($params, 'promotion_type_id', null)],
                ],
                'firstRow' => 1
            ];
            $promotionType = $this->promotionTypeRepository->findByCriteria($promotionTypeRequest, ['id', 'name', 'language_key', 'parent_id', 'type_code', 'order_number', 'status']);


            if (!$promotionType) {
                throw new Exception('api-unknown_error');
            }


            $params['start_date'] = fillOnUndefined($params, 'start_date', null) != null ? Carbon::parse($params['start_date'])->format('Y-m-d') : null;
            $params['end_date'] = fillOnUndefined($params, 'start_date', null) != null ? Carbon::parse($params['end_date'])->format('Y-m-d') : null;
            $params['reservation_start_date'] = fillOnUndefined($params, 'start_date', null) != null ? Carbon::parse($params['reservation_start_date'])->format('Y-m-d') : null;
            $params['reservation_end_date'] = fillOnUndefined($params, 'start_date', null) != null ? Carbon::parse($params['reservation_end_date'])->format('Y-m-d') : null;
            $params['is_time'] = fillOnUndefined($params, 'is_time', null) != null ? 1 : null;
            $params['start_time'] = fillOnUndefined($params, 'start_time', null) != null ? Carbon::parse($params['start_time'])->format('H:i:s') : null;
            $params['end_time'] = fillOnUndefined($params, 'end_time', null) != null ? Carbon::parse($params['end_time'])->format('H:i:s') : null;
            $params['min_stay'] = fillOnUndefinedAndEmpty($params, 'min_stay');

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

            $createDays = fillOnUndefined($params, 'days', null) != null ? json_encode($params['days']) : null;
            $excludeDates = fillOnUndefined($params, 'exclude_dates', null) != null ? json_encode($params['exclude_dates']) : null;
            $createParams = fillOnUndefined($params, 'params', null) != null ? json_encode($params['params']) : null;
            $createDetail = fillOnUndefined($params, 'detail', null) != null ? json_encode($params['detail']) : null;


            $dayBefore = fillOnUndefined($params, 'day_before');
            if ($promotionType['type_code'] == 'LST') {
                $dayBefore = fillOnUndefined($params, 'last_minute');
            }

            $createData =
                [
                    'property_id' => fillOnUndefined($params, 'property_id'),
                    'promotion_type_id' => fillOnUndefined($params, 'promotion_type_id'),
                    'title' => fillOnUndefined($params, 'title'),
                    'start_date' => fillOnUndefined($params, 'start_date'),
                    'end_date' => fillOnUndefined($params, 'end_date'),
                    'reservation_start_date' => fillOnUndefined($params, 'reservation_start_date'),
                    'reservation_end_date' => fillOnUndefined($params, 'reservation_end_date'),
                    'is_time' => fillOnUndefined($params, 'is_time'),
                    'start_time' => fillOnUndefined($params, 'start_time'),
                    'end_time' => fillOnUndefined($params, 'end_time'),
                    'day_before' => $dayBefore,
                    'amount' => fillOnUndefined($params, 'amount'),
                    'min_stay' => fillOnUndefinedAndEmpty($params, 'min_stay'),
                    'days' => $createDays,
                    'exclude_dates' => $excludeDates,
                    'is_mobile' => fillOnUndefined($params, 'is_mobile'),
                    'params' => $createParams,
                    'detail' => $createDetail,
                    'status' => 1,
                    "created_by" => fillOnUndefined($params, "user_id"),
                    "updated_by" => fillOnUndefined($params, "user_id"),
                    "created_at" => time(),
                    "updated_at" => time(),
                ];


            $createResult = $this->propertyPromotionRepository->create($createData);

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

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

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

        return output($response);
    }

    public function getRoomRateChannelPromotion($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.propertyRoomRateChannelPromotion', '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']);

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

                ],
            ];
            $propertyPromotions = $this->propertyPromotionRepository->findByCriteria($propertyPromotionRequest, ['id', 'property_id', 'promotion_type_id', 'title', 'start_date', 'end_date', 'is_time', 'start_time', 'end_time', 'reservation_start_date', 'reservation_end_date', 'day_before', 'amount', 'min_stay', 'is_mobile', 'days', 'params','exclude_dates', 'detail', 'status']);


            $return = [];

            foreach ($roomData as $room) {

                if ($room['property_room_rate_mapping']) {
                    $item = $room;
                    $item['exclude_occupancy'] = json_decode($room['exclude_occupancy']);
                    $roomRateMappings = $room['property_room_rate_mapping'];
                    $mapping = [];
                    $addedMapping = 0;
                    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;
                        $propertyPromotionArray = [];
                        if ($propertyRoomRateChannel) {
                            if ($propertyRoomRateChannel['status'] == 1) {


                                $mappingStatus = true;
                                foreach ($propertyPromotions as $promotion) {
                                    $propertyRoomRateChannelPromotion = [];
                                    if (isset($propertyRoomRateChannel['property_room_rate_channel_promotion'])) {


                                        $propertyRoomRateChannelPromotion = collect($propertyRoomRateChannel['property_room_rate_channel_promotion'])
                                            ->where('property_promotion_id', '=', $promotion['id'])
                                            ->where('room_rate_channel_mapping_id', '=', $propertyRoomRateChannel['id'])
                                            ->where('status', '=', 1)
                                            ->values()->toArray();
                                    }

                                    $propertyPromotionArray[] = [
                                        'id' => $promotion['id'],
                                        'property_id' => $promotion['property_id'],
                                        'promotion_type_id' => $promotion['promotion_type_id'],
                                        'title' => $promotion['title'],
                                        'start_date' => $promotion['start_date'],
                                        'end_date' => $promotion['end_date'],
                                        'reservation_start_date' => $promotion['reservation_start_date'],
                                        'reservation_end_date' => $promotion['reservation_end_date'],
                                        'day_before' => $promotion['day_before'],
                                        'is_time' => $promotion['is_time'],
                                        'start_time' => $promotion['start_time'],
                                        'end_time' => $promotion['end_time'],
                                        'amount' => $promotion['amount'],
                                        'min_stay' => $promotion['min_stay'],
                                        'is_mobile' => $promotion['is_mobile'] ? true : false,
                                        'days' => $promotion['days'],
                                        'params' => $promotion['params'],
                                        'excludeDatesArray' => $promotion['excludeDatesArray'],
                                        'detail' => $promotion['detail'],
                                        'promotion_status' => $promotion['status'],
                                        'is_selected' => $propertyRoomRateChannelPromotion ? true : false,
                                    ];
                                }
                            }
                        }
                        $roomRateMapping['name'] = $roomRateMapping['property_room_rate']['name'];
                        $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'];
                        $roomRateMapping['room_rate_channel_mapping_id'] = $propertyRoomRateChannel['id'];
                        $roomRateMapping['room_rate_channel_promotion'] = $propertyPromotionArray;

                        unset($roomRateMapping['property_room_rate']);
                        unset($roomRateMapping['property_room_rate_channel']);
                        if ($mappingStatus) {
                            $addedMapping++;
                            $mapping[] = $roomRateMapping;
                        }
                    }
                    $item['property_room_rate_mapping'] = $mapping;
                    if ($addedMapping > 0) {
                        $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 updatePropertyPromotion($params)
    {

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


            $propertyPromotionRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => $params['promotion_id']],

                ],
                'firstRow' => 1,
            ];
            $propertyPromotion = $this->propertyPromotionRepository->findByCriteria($propertyPromotionRequest, ['id', 'property_id', 'promotion_type_id', 'title','start_date', 'end_date', 'reservation_start_date', 'reservation_end_date', 'day_before', 'amount', 'min_stay', 'days', 'params', 'detail', 'status']);

            if (!$propertyPromotion) {
                throw new Exception('api-unknown_error');
            }

            $params['promotion_type_id'] = $propertyPromotion['promotion_type_id'];
            $params['end_date'] = fillOnUndefined($params, 'start_date', null) != null ? Carbon::parse($params['end_date'])->format('Y-m-d') : null;
            $params['reservation_start_date'] = fillOnUndefined($params, 'start_date', null) != null ? Carbon::parse($params['reservation_start_date'])->format('Y-m-d') : null;
            $params['reservation_end_date'] = fillOnUndefined($params, 'start_date', null) != null ? Carbon::parse($params['reservation_end_date'])->format('Y-m-d') : null;
            $params['is_time'] = fillOnUndefined($params, 'is_time', null) != null ? 1 : null;
            $params['start_time'] = fillOnUndefined($params, 'start_time', null) != null ? Carbon::parse($params['start_time'])->format('H:i:s') : null;
            $params['end_time'] = fillOnUndefined($params, 'end_time', null) != null ? Carbon::parse($params['end_time'])->format('H:i:s') : null;
            $params['min_stay'] = fillOnUndefinedAndEmpty($params, 'min_stay');

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

            $createDays = fillOnUndefined($params, 'days', null) != null ? json_encode($params['days']) : null;
            $excludeDates = fillOnUndefined($params, 'exclude_dates', null) != null ? json_encode($params['exclude_dates']) : null;
            $createParams = fillOnUndefined($params, 'params', null) != null ? json_encode($params['params']) : null;
            $createDetail = fillOnUndefined($params, 'detail', null) != null ? json_encode($params['detail']) : null;

            $dayBefore = fillOnUndefined($params, 'day_before');
            if ($propertyPromotion['promotion_type_id'] == 4) {
                $dayBefore = fillOnUndefined($params, 'last_minute');
            }

            $promotionUpdateData =
                [
                    'title' => fillOnUndefined($params, 'title'),
                    'start_date' => fillOnUndefined($params, 'start_date'),
                    'end_date' => fillOnUndefined($params, 'end_date'),
                    'reservation_start_date' => fillOnUndefined($params, 'reservation_start_date'),
                    'reservation_end_date' => fillOnUndefined($params, 'reservation_end_date'),
                    'is_time' => fillOnUndefined($params, 'is_time'),
                    'start_time' => fillOnUndefined($params, 'start_time'),
                    'end_time' => fillOnUndefined($params, 'end_time'),
                    'day_before' => $dayBefore,
                    'amount' => fillOnUndefined($params, 'amount'),
                    'min_stay' => fillOnUndefinedAndEmpty($params, 'min_stay'),
                    'days' => $createDays,
                    'exclude_dates' => $excludeDates,
                    'is_mobile' => fillOnUndefined($params, 'is_mobile'),
                    'params' => $createParams,
                    'detail' => $createDetail,
                    'updated_by' => fillOnUndefined($params, 'user_id'),
                    'updated_at' => time()
                ];

            $promotionId = fillOnUndefined($params, 'promotion_id');

            $promotionResult = $this->propertyPromotionRepository->update($promotionId, $promotionUpdateData);

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

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

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

        return output($response);

    }

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

            DB::beginTransaction();

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


            $criteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['propertyPromotion.promotionType.parentPromotionType']
            ];

            $propertyChannelRoomRatePromotionMapping = $this->propertyPromotionMappingRepository->findByCriteria($criteria);
            $oldMappingData = collect($propertyChannelRoomRatePromotionMapping);

            $criteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'id', 'condition' => '=', 'value' => $params['property_promotion_id']],
                ],
                'with' => ['promotionType.parentPromotionType'],
                'firstRow' => 1
            ];

            $mappedPromotion = $this->propertyPromotionRepository->findByCriteria($criteria);
            if (!$mappedPromotion) {
                throw new Exception('api-unknown-error');
            }

            $addThisPromotion = [
                "id" => $mappedPromotion['id'],
                "property_id" => $mappedPromotion['property_id'],
                "promotion_type_id" => $mappedPromotion['promotion_type_id'],
                "start_date" => $mappedPromotion['start_date'],
                "end_date" => $mappedPromotion['end_date'],
                "reservation_start_date" => $mappedPromotion['reservation_start_date'],
                "reservation_end_date" => $mappedPromotion['reservation_end_date'],
                'is_time' => $mappedPromotion['is_time'],
                'start_time' => $mappedPromotion['start_time'],
                'end_time' => $mappedPromotion['end_time'],
                'is_mobile' => $mappedPromotion['is_mobile'],
                "day_before" => $mappedPromotion['day_before'],
                "amount" => $mappedPromotion['amount'],
                "min_stay" => $mappedPromotion['min_stay'],
                "days" => $mappedPromotion['days'],
                "params" => $mappedPromotion['params'],
                "detail" => $mappedPromotion['detail'],
                "status" => $mappedPromotion['status'],
                'promotion_type_name' => $mappedPromotion['promotion_type']['name'],
                'promotion_type_language_key' => $mappedPromotion['promotion_type']['language_key'],
                'promotion_type_code' => $mappedPromotion['promotion_type']['type_code'],
                'parent_promotion_type_name' => $mappedPromotion['promotion_type']['parent_promotion_type']['name'],
                'parent_promotion_type_language_key' => $mappedPromotion['promotion_type']['parent_promotion_type']['language_key'],
                'parent_promotion_type_code' => $mappedPromotion['promotion_type']['parent_promotion_type']['type_code'],
            ];

            $oldDataMappingCollect = collect($oldMappingData)->map(function ($value) {
                return [
                    'id' => $value['id'],
                    'property_id' => $value['property_id'],
                    'property_promotion_id' => $value['property_promotion_id'],
                    'room_rate_channel_mapping_id' => $value['room_rate_channel_mapping_id'],
                    'promotion_type_id' => $value['property_promotion']['promotion_type_id'],
                    'start_date' => $value['property_promotion']['start_date'],
                    'end_date' => $value['property_promotion']['end_date'],
                    'is_time' => $value['property_promotion']['is_time'],
                    'start_time' => $value['property_promotion']['start_time'],
                    'end_time' => $value['property_promotion']['start_time'],
                    'is_mobile' => $value['property_promotion']['is_mobile'],
                    'reservation_start_date' => $value['property_promotion']['reservation_start_date'],
                    'reservation_end_date' => $value['property_promotion']['reservation_end_date'],
                    'day_before' => $value['property_promotion']['day_before'],
                    'amount' => $value['property_promotion']['amount'],
                    'min_stay' => $value['property_promotion']['min_stay'],
                    'days' => $value['property_promotion']['days'],
                    'promotion_type_name' => $value['property_promotion']['promotion_type']['name'],
                    'promotion_type_language_key' => $value['property_promotion']['promotion_type']['language_key'],
                    'promotion_type_code' => $value['property_promotion']['promotion_type']['type_code'],
                    'parent_promotion_type_name' => $value['property_promotion']['promotion_type']['parent_promotion_type']['name'],
                    'parent_promotion_type_language_key' => $value['property_promotion']['promotion_type']['parent_promotion_type']['language_key'],
                    'parent_promotion_type_code' => $value['property_promotion']['promotion_type']['parent_promotion_type']['type_code'],
                    'mapping_status' => $value['status']
                ];
            });


            $haveThisMapping = $oldDataMappingCollect
                ->where('property_promotion_id', '=', $params['property_promotion_id'])
                ->where('room_rate_channel_mapping_id', '=', $params['room_rate_channel_mapping_id'])
                ->where('property_id', '=', $params['property_id']);


            if ($params['is_selected'] == true) {

                // control adding roles ;


                /*$checkRole = $oldDataMappingCollect
                    ->where('room_rate_channel_mapping_id', '=', $params['room_rate_channel_mapping_id'])
                    ->where('property_promotion_id', '=', $params['property_promotion_id'])
                    ->where('property_id', '=', $params['property_id'])
                    ->where('mapping_status', '=', 1)
                    ->first();

                dd($checkRole,$params, $oldDataMappingCollect);
                if ($checkRole) {
                    throw new Exception('enw-booking_engine_promotion-overlapping_error');
                }*/

                if ($addThisPromotion['parent_promotion_type_code'] == 'ERB' && $addThisPromotion['promotion_type_code'] == 'PRD') {
                    $checkRoles = $oldDataMappingCollect
                        ->where('room_rate_channel_mapping_id', '=', $params['room_rate_channel_mapping_id'])
                        ->where('promotion_type_code', '=', $addThisPromotion['promotion_type_code'])
                        ->where('mapping_status', '=', 1);


                    $overLappingError = null;
                    foreach ($checkRoles as $checkRole) {



                        if ($checkRole && ($checkRole['min_stay'] == $addThisPromotion['min_stay'])) {
                            if ($checkRole['start_date'] <= $addThisPromotion['start_date']) {
                                if ($checkRole['reservation_start_date'] <= $addThisPromotion['reservation_start_date']) {
                                    //$overLappingError = true;
                                } elseif ($checkRole['reservation_start_date'] >= $addThisPromotion['reservation_start_date']
                                    && $addThisPromotion['reservation_end_date'] >= $checkRole['reservation_start_date']) {
                                    $overLappingError = true;

                                }


                            } /*elseif ($checkRole['start_date'] >= $addThisPromotion['start_date'] && $addThisPromotion['end_date'] >= $checkRole['start_date']) {


                                if ($checkRole['reservation_start_date'] <= $addThisPromotion['reservation_start_date']) {
                                    $overLappingError = true;
                                    dd($checkRole);
                                } elseif ($checkRole['reservation_start_date'] >= $addThisPromotion['reservation_start_date']
                                    && $addThisPromotion['reservation_end_date'] >= $checkRole['reservation_start_date']) {
                                    $overLappingError = true;
                                }
                            }*/
                        }
                    }

                    if ($overLappingError) {
                        throw new Exception('enw-booking_engine_promotion-overlapping_error');
                    }
                }

                if ($addThisPromotion['parent_promotion_type_code'] == 'ERB' && $addThisPromotion['promotion_type_code'] == 'BFD') {

                    $checkRole = $oldDataMappingCollect
                        ->where('room_rate_channel_mapping_id', '=', $params['room_rate_channel_mapping_id'])
                        ->where('promotion_type_code', '=', $addThisPromotion['promotion_type_code'])
                        ->where('day_before', '=', $addThisPromotion['day_before'])
                        ->where('min_stay', '=', $addThisPromotion['min_stay'])
                        ->where('is_mobile', '=', $addThisPromotion['is_mobile'])
                        ->where('mapping_status', '=', 1)
                        ->first();
                    if ($checkRole) {
                        throw new Exception('enw-booking_engine_promotion-overlapping_error');
                    }
                }

                if ($addThisPromotion['promotion_type_code'] == 'LST') {

                    $checkRole = $oldDataMappingCollect
                        ->where('room_rate_channel_mapping_id', '=', $params['room_rate_channel_mapping_id'])
                        ->where('promotion_type_code', '=', $addThisPromotion['promotion_type_code'])
                        ->where('min_stay', '=', $addThisPromotion['min_stay'])
                        ->where('is_time', '=', $addThisPromotion['is_time'])
                        ->where('is_mobile', '=', $addThisPromotion['is_mobile'])
                        ->where('amount', '=', $addThisPromotion['amount'])
                        ->where('mapping_status', '=', 1)
                        ->first();
                    if ($checkRole) {
                        throw new Exception('enw-booking_engine_promotion-overlapping_error');
                    }
                }


                if ($addThisPromotion['promotion_type_code'] == 'DSC') {

                    $checkRole = $oldDataMappingCollect
                        ->where('room_rate_channel_mapping_id', '=', $params['room_rate_channel_mapping_id'])
                        ->where('promotion_type_code', '=', $addThisPromotion['promotion_type_code'])
                        ->where('min_stay', '=', $addThisPromotion['min_stay'])
                        ->where('is_time', '=', $addThisPromotion['is_time'])
                        ->where('is_mobile', '=', $addThisPromotion['is_mobile'])
                        ->where('amount', '=', $addThisPromotion['amount'])
                        ->where('mapping_status', '=', 1)
                        ->first();

                    //dd($addThisPromotion,$checkRole, $params['room_rate_channel_mapping_id'],$oldDataMappingCollect);
                    if ($checkRole) {
                        throw new Exception('enw-booking_engine_promotion-overlapping_error');
                    }

                }


                if ($haveThisMapping->first()) {
                    $thisMapping = $haveThisMapping->first();
                    $updateData = [
                        'status' => 1,
                        'updated_by' => fillOnUndefined($params, 'user_id'),
                        'updated_at' => Carbon::now()->timestamp,
                    ];
                    $updateThis = $this->propertyPromotionMappingRepository->update($thisMapping['id'], $updateData);
                    if ($updateThis['status'] != 'success') {
                        throw new Exception('api-unknown_error');
                    }
                } else {

                    $insertData = [];
                    $insertData[] = [
                        'property_id' => $params['property_id'],
                        'room_rate_channel_mapping_id' => $params['room_rate_channel_mapping_id'],
                        'property_promotion_id' => $params['property_promotion_id'],
                        'status' => 1,
                        'created_by' => fillOnUndefined($params, 'user_id'),
                        'updated_by' => fillOnUndefined($params, 'user_id'),
                        'created_at' => Carbon::now()->timestamp,
                        'updated_at' => Carbon::now()->timestamp,
                    ];

                    if ($insertData) {
                        $createResult = $this->propertyPromotionMappingRepository->insert($insertData);
                        if ($createResult['status'] != 'success') {
                            throw new Exception('api-unknown_error');
                        }
                    }
                }
            }


            // Pasife alma işlemi
            if ($params['is_selected'] == false) {
                $deleteThis = collect($propertyChannelRoomRatePromotionMapping)
                    ->where('property_promotion_id', '=', $params['property_promotion_id'])
                    ->where('room_rate_channel_mapping_id', '=', $params['room_rate_channel_mapping_id'])
                    ->where('property_id', '=', $params['property_id'])
                    ->keyBy('id')->keys()->toArray();


                if ($deleteThis) {
                    $updateData = [
                        'status' => 0,
                        'updated_by' => fillOnUndefined($params, 'user_id'),
                        'updated_at' => Carbon::now()->timestamp,
                    ];
                    $deleteThisArray = $this->propertyPromotionMappingRepository->update($deleteThis, $updateData);
                    if ($deleteThisArray['status'] != 'success') {
                        throw new Exception('api-unknown_error');
                    }
                }

            }


            $response = [
                'status' => true,
                'data' => null,
            ];
            DB::commit();

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

        return output($response);
    }

    public function deletePropertyPromotion($params)
    {

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

        DB::beginTransaction();

        try {

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

                ]
            ];
            $propertyPromotion = $this->propertyPromotionRepository->findByCriteria($propertyPromotionRequest);
            if (!$propertyPromotion) {
                throw new Exception('No promotion found.');
            }

            $propertyPromotionDeleteIds = $propertyPromotion ? collect($propertyPromotion)->pluck('id')->toArray() : null;


            $propertyPromotionMappingRequest = [
                'criteria' => [
                    ['field' => 'property_promotion_id', 'condition' => '=', 'value' => $params['promotion_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],

                ]
            ];
            $propertyPromotionMapping = $this->propertyPromotionMappingRepository->findByCriteria($propertyPromotionMappingRequest, ['id']);
            $propertyPromotionMappingDeleteIds = $propertyPromotionMapping ? collect($propertyPromotionMapping)->pluck('id')->toArray() : null;

            if(!empty($propertyPromotionMappingDeleteIds)) {
                $propertyPromotionMappingDelete = $this->propertyPromotionMappingRepository->destroy($propertyPromotionMappingDeleteIds);
                if ($propertyPromotionMappingDelete['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

            }

            $propertyPromotionDelete = $this->propertyPromotionRepository->destroy($propertyPromotionDeleteIds);

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

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

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


        if($response['status']) {
            DB::commit();
        } else {
            DB::rollBack();
        }

        return output($response);

    }

}
