<?php


namespace App\Core\Service;

use App\Core\Repository\PropertyChannelMapping\PropertyChannelMappingRepository;
use App\Core\Repository\PropertyPricingPolicyAdult\PropertyPricingPolicyAdultRepository;
use App\Core\Repository\PropertyPricingPolicyChild\PropertyPricingPolicyChildRepository;
use App\Core\Repository\PropertyRoom\PropertyRoomRepository;
use App\Core\Repository\PropertyChannelRoomRatePricingPolicyAdultMapping\PropertyChannelRoomRatePricingPolicyAdultMappingRepository;
use App\Core\Repository\PropertyChannelRoomRatePricingPolicyChildMapping\PropertyChannelRoomRatePricingPolicyChildMappingRepository;
use App\Core\Validator\PropertyPersonPricingPolicy\UpdateRoomRateChannelPersonPricingAdultPolicyValidator;
use App\Core\Validator\PropertyPersonPricingPolicy\UpdateRoomRateChannelPersonPricingChildPolicyValidator;
use App\Core\Validator\PropertyPersonPricingPolicy\PropertyPricingPolicyAdultAddValidator;
use App\Core\Validator\PropertyPersonPricingPolicy\PropertyPricingPolicyAdultUpdateValidator;
use App\Core\Validator\PropertyPersonPricingPolicy\PropertyPricingPolicyChildAddValidator;
use App\Core\Validator\PropertyPersonPricingPolicy\PropertyPricingPolicyChildUpdateValidator;

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


class PropertyPersonPricingPolicyService
{
    private $propertyPricingPolicyAdultRepository;
    private $propertyPricingPolicyChildRepository;
    private $propertyChannelRoomRatePricingPolicyAdultMappingRepository;
    private $propertyChannelRoomRatePricingPolicyChildMappingRepository;
    private $updateRoomRateChannelPersonPricingAdultPolicyValidator;
    private $updateRoomRateChannelPersonPricingChildPolicyValidator;
    private $propertyRoomRepository;
    private $propertyPricingPolicyAdultAddValidator;
    private $propertyPricingPolicyAdultUpdateValidator;
    private $propertyPricingPolicyChildAddValidator;
    private $propertyPricingPolicyChildUpdateValidator;
    private $propertyChannelMappingRepository;


    public function __construct
    (
        PropertyPricingPolicyAdultRepository $propertyPricingPolicyAdultRepository,
        PropertyPricingPolicyChildRepository $propertyPricingPolicyChildRepository,
        PropertyChannelRoomRatePricingPolicyAdultMappingRepository $propertyChannelRoomRatePricingPolicyAdultMappingRepository,
        PropertyChannelRoomRatePricingPolicyChildMappingRepository $propertyChannelRoomRatePricingPolicyChildMappingRepository,
        UpdateRoomRateChannelPersonPricingAdultPolicyValidator $updateRoomRateChannelPersonPricingAdultPolicyValidator,
        UpdateRoomRateChannelPersonPricingChildPolicyValidator $updateRoomRateChannelPersonPricingChildPolicyValidator,
        PropertyRoomRepository $propertyRoomRepository,
        PropertyPricingPolicyAdultAddValidator $propertyPricingPolicyAdultAddValidator,
        PropertyPricingPolicyAdultUpdateValidator $propertyPricingPolicyUpdateValidator,
        PropertyPricingPolicyChildAddValidator $propertyPricingPolicyChildAddValidator,
        PropertyPricingPolicyChildUpdateValidator $propertyPricingPolicyChildUpdateValidator,
        PropertyChannelMappingRepository $propertyChannelMappingRepository

    )
    {
        $this->propertyPricingPolicyAdultRepository = $propertyPricingPolicyAdultRepository;
        $this->propertyPricingPolicyChildRepository = $propertyPricingPolicyChildRepository;
        $this->propertyChannelRoomRatePricingPolicyAdultMappingRepository = $propertyChannelRoomRatePricingPolicyAdultMappingRepository;
        $this->updateRoomRateChannelPersonPricingAdultPolicyValidator = $updateRoomRateChannelPersonPricingAdultPolicyValidator;
        $this->updateRoomRateChannelPersonPricingChildPolicyValidator = $updateRoomRateChannelPersonPricingChildPolicyValidator;
        $this->propertyChannelRoomRatePricingPolicyChildMappingRepository = $propertyChannelRoomRatePricingPolicyChildMappingRepository;
        $this->propertyRoomRepository = $propertyRoomRepository;
        $this->propertyPricingPolicyAdultAddValidator = $propertyPricingPolicyAdultAddValidator;
        $this->propertyPricingPolicyAdultUpdateValidator = $propertyPricingPolicyUpdateValidator;
        $this->propertyPricingPolicyChildAddValidator = $propertyPricingPolicyChildAddValidator;
        $this->propertyPricingPolicyChildUpdateValidator = $propertyPricingPolicyChildUpdateValidator;
        $this->propertyChannelMappingRepository = $propertyChannelMappingRepository;


    }


    public function getPropertyPersonPricingPolicyList($params)
    {

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

            $propertyId = fillOnUndefined($params, 'property_id');
            $propertyPersonPricingPolicyRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                ]
            ];
            $propertyPersonPricingAdultPolicy = $this->propertyPricingPolicyAdultRepository->findByCriteria($propertyPersonPricingPolicyRequest, ['id', 'property_id', 'name', 'adult_action_type', 'adult', "action_type", "type", "value", "status"]);
            $propertyPersonPricingAdultPolicy = $propertyPersonPricingAdultPolicy ? $propertyPersonPricingAdultPolicy : [];


            $propertyPersonPricingChildPolicy = $this->propertyPricingPolicyChildRepository->findByCriteria($propertyPersonPricingPolicyRequest, ['id', 'property_id', 'name', "adult", "child_order", "child_age_start", "child_age_end", "type", "value", "status"]);
            $propertyPersonPricingChildPolicy = $propertyPersonPricingChildPolicy ? $propertyPersonPricingChildPolicy : [];

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => ["person_pricing_adult_policy" => $propertyPersonPricingAdultPolicy, "person_pricing_child_policy" => $propertyPersonPricingChildPolicy]];

        } 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 createPropertyPersonPricingAdultPolicy($params)
    {

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

            $validate = [
                'name' => fillOnUndefinedAndEmpty($params, 'name', null),
                'adult_action_type' => fillOnUndefined($params, 'adult_action_type'),
                'adult' => fillOnUndefined($params, 'adult'),
                'action_type' => fillOnUndefinedAndEmpty($params, 'action_type', null),
                'type' => fillOnUndefinedAndEmpty($params, 'type', null),
                'value' => fillOnUndefinedAndEmpty($params, 'value', null),
                'property_id' => fillOnUndefinedAndEmpty($params, 'property_id', null),
                'reservation_start_date' => fillOnUndefinedAndEmpty($params, 'reservation_start_date', null),
                'reservation_end_date' => fillOnUndefinedAndEmpty($params, 'reservation_end_date', null),
            ];

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


            $createData =
                [
                    'property_id' => fillOnUndefined($params, 'property_id'),
                    'name' => $validate['name'],
                    'adult_action_type' => $validate['adult_action_type'],
                    'adult' => $validate['adult'],
                    'action_type' => $validate['action_type'],
                    'type' => $validate['type'],
                    'value' => $validate['value'],
                    'reservation_start_date' => $validate['reservation_start_date'],
                    'reservation_end_date' => $validate['reservation_end_date'],
                    "status" => fillOnUndefined($params, "status", 1),
                    "created_by" => fillOnUndefined($params, "user_id"),
                    "updated_by" => fillOnUndefined($params, "user_id"),
                    "created_at" => time(),
                    "updated_at" => time(),
                ];

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

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

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $createResult['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 updatePropertyPersonPricingAdultPolicy($params)
    {

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

            $validate = [
                'name' => fillOnUndefinedAndEmpty($params, 'name', null),
                'adult_action_type' => fillOnUndefined($params, 'adult_action_type'),
                'adult' => fillOnUndefined($params, 'adult'),
                'pricing_policy_id' => fillOnUndefinedAndEmpty($params, 'pricing_policy_id', null),
                'property_id' => fillOnUndefinedAndEmpty($params, 'property_id', null),
                'action_type' => fillOnUndefinedAndEmpty($params, 'action_type', null),
                'type' => fillOnUndefinedAndEmpty($params, 'type', null),
                'value' => fillOnUndefinedAndEmpty($params, 'value', null),
                'reservation_start_date' => fillOnUndefinedAndEmpty($params, 'reservation_start_date', null),
                'reservation_end_date' => fillOnUndefinedAndEmpty($params, 'reservation_end_date', null),
            ];

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

            $updateData =
                [
                    'name' => $validate['name'],
                    'adult_action_type' => $validate['adult_action_type'],
                    'adult' => $validate['adult'],
                    'action_type' => $validate['action_type'],
                    'type' => $validate['type'],
                    'value' => $validate['value'],
                    'reservation_start_date' => $validate['reservation_start_date'],
                    'reservation_end_date' => $validate['reservation_end_date'],
                    "status" => fillOnUndefined($params, "status", 1),
                    "updated_by" => fillOnUndefined($params, "user_id"),
                    "updated_at" => time(),
                ];

            $updateResult = $this->propertyPricingPolicyAdultRepository->update($validate['pricing_policy_id'], $updateData);

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

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $updateResult['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 deletePropertyPersonPricingAdultPolicy($params)
    {

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

            $adultCriteria = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['pricing_policy_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['channelRoomRatePricingPolicyAdultMapping'],
                'firstRow' => true
            ];

            $propertyPersonPricingAdultPolicy = $this->propertyPricingPolicyAdultRepository->findByCriteria($adultCriteria);

            if (empty($propertyPersonPricingAdultPolicy)) {
                throw new ApiErrorException('Adult policy data not found');
            }

            DB::beginTransaction();

            $channelRoomRatePricingPolicyAdultMappingIds = collect($propertyPersonPricingAdultPolicy['channel_room_rate_pricing_policy_adult_mapping'])->pluck('id')->toArray();
            if ($channelRoomRatePricingPolicyAdultMappingIds) {
                $deleteChannelRoomRatePricingPolicyAdultMapping = $this->propertyChannelRoomRatePricingPolicyAdultMappingRepository->destroy($channelRoomRatePricingPolicyAdultMappingIds);
            }

            $deletePropertyPricingPolicyAdult = $this->propertyPricingPolicyAdultRepository->destroy([$propertyPersonPricingAdultPolicy['id']]);

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

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $deletePropertyPricingPolicyAdult['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 createPropertyPersonPricingChildPolicy($params)
    {

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


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

            $createData =
                [
                    'property_id' => fillOnUndefined($params, 'property_id'),
                    'name' => fillOnUndefined($params, 'name'),
                    'adult' => fillOnUndefined($params, 'adult'),
                    'child_order' => fillOnUndefined($params, 'child_order'),
                    'child_age_start' => fillOnUndefined($params, 'child_age_start'),
                    'child_age_end' => fillOnUndefined($params, 'child_age_end'),
                    'type' => fillOnUndefined($params, 'type'),
                    'value' => fillOnUndefined($params, 'value'),
                    'reservation_start_date' => fillOnUndefined($params, 'reservation_start_date'),
                    'reservation_end_date' => fillOnUndefined($params, 'reservation_end_date'),
                    "status" => fillOnUndefined($params, "status", 1),
                    "created_by" => fillOnUndefined($params, "user_id"),
                    "updated_by" => fillOnUndefined($params, "user_id"),
                    "created_at" => time(),
                    "updated_at" => time(),
                ];

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

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

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $createResult['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 updatePropertyPersonPricingChildPolicy($params)
    {

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

            $validationResult = $this->propertyPricingPolicyChildUpdateValidator->validate($params);
            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }
            $criteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'room_rate_channel_mapping_id', 'condition' => '=', 'value' => $params['room_rate_channel_mapping_id']],
                ],
                'with' => ['propertyPricingPolicyChild']
            ];

            $propertyChannelRoomRatePersonPricingPolicyMapping = $this->propertyChannelRoomRatePricingPolicyChildMappingRepository->findByCriteria($criteria);
            $propertyChannelRoomRatePersonPricingPolicyMapping = $propertyChannelRoomRatePersonPricingPolicyMapping ? $propertyChannelRoomRatePersonPricingPolicyMapping : [];

            if (!empty($propertyChannelRoomRatePersonPricingPolicyMapping)) {

                $oldDataMappingCollect = collect($propertyChannelRoomRatePersonPricingPolicyMapping)->map(function ($value) {
                    return [
                        'id' => $value['property_pricing_policy_child']['id'],
                        'name' => $value['property_pricing_policy_child']['name'],
                        'adult' => $value['property_pricing_policy_child']['adult'],
                        'child_order' => $value['property_pricing_policy_child']['child_order'],
                        'child_age_start' => $value['property_pricing_policy_child']['child_age_start'],
                        'child_age_end' => $value['property_pricing_policy_child']['child_age_end'],
                        'type' => $value['property_pricing_policy_child']['type'],
                        'value' => $value['property_pricing_policy_child']['value'],
                        'reservation_start_date' => $value['property_pricing_policy_child']['reservation_start_date'],
                        'reservation_end_date' => $value['property_pricing_policy_child']['reservation_end_date'],
                    ];
                });

                for ($age = $params['child_age_start']; $age <= $params['child_age_end']; $age++) {
                    $checkOldData = $oldDataMappingCollect->where('adult', '=', $params['adult'])
                        ->where('child_age_start', '<=', $age)
                        ->where('child_age_end', '>', $age)
                        ->where('child_order', '=', $params['child_order'])
                        ->where('reservation_start_date', $params['reservation_start_date'])
                        ->where('reservation_end_date',  $params['reservation_end_date'])
                        ->where('id', '!=', $params['pricing_policy_id'])
                        ->first();
                    if ($checkOldData) {
                        throw new ApiErrorException('This mapping added before');
                    }
                }

            }
            $updateData =
                [
                    'property_id' => fillOnUndefined($params, 'property_id'),
                    'name' => fillOnUndefined($params, 'name'),
                    'adult' => fillOnUndefined($params, 'adult'),
                    'child_order' => fillOnUndefined($params, 'child_order'),
                    'child_age_start' => fillOnUndefined($params, 'child_age_start'),
                    'child_age_end' => fillOnUndefined($params, 'child_age_end'),
                    'type' => fillOnUndefined($params, 'type'),
                    'value' => fillOnUndefined($params, 'value'),
                    'reservation_start_date' => fillOnUndefined($params, 'reservation_start_date'),
                    'reservation_end_date' => fillOnUndefined($params, 'reservation_end_date'),
                    "status" => fillOnUndefined($params, "status", 1),
                    "updated_by" => fillOnUndefined($params, "user_id"),
                    "updated_at" => time(),
                ];

            $updateResult = $this->propertyPricingPolicyChildRepository->update($params['pricing_policy_id'], $updateData);

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

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $updateResult['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 deletePropertyPersonPricingChildPolicy($params)
    {

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

            $adultCriteria = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['pricing_policy_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['channelRoomRatePricingPolicyChildMapping'],
                'firstRow' => true
            ];

            $propertyPersonPricingChildPolicy = $this->propertyPricingPolicyChildRepository->findByCriteria($adultCriteria);

            if (empty($propertyPersonPricingChildPolicy)) {
                throw new ApiErrorException('Child policy data not found');
            }

            DB::beginTransaction();

            $channelRoomRatePricingPolicyChildMappingIds = collect($propertyPersonPricingChildPolicy['channel_room_rate_pricing_policy_child_mapping'])->pluck('id')->toArray();
            if ($channelRoomRatePricingPolicyChildMappingIds) {
                $deleteChannelRoomRatePricingPolicyAdultMapping = $this->propertyChannelRoomRatePricingPolicyChildMappingRepository->destroy($channelRoomRatePricingPolicyChildMappingIds);
            }

            $deletePropertyPricingPolicyChild = $this->propertyPricingPolicyChildRepository->destroy([$propertyPersonPricingChildPolicy['id']]);

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

            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $deletePropertyPricingPolicyChild['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 updateRoomRatePricingAdultPolicy($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            DB::beginTransaction();

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

            $criteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'room_rate_channel_mapping_id', 'condition' => '=', 'value' => $params['room_rate_channel_mapping_id']],
                ],
                'with' => ['propertyPricingPolicyAdult']
            ];

            $propertyChannelRoomRatePersonPricingPolicyMapping = $this->propertyChannelRoomRatePricingPolicyAdultMappingRepository->findByCriteria($criteria);
            $propertyChannelRoomRatePersonPricingPolicyMapping = $propertyChannelRoomRatePersonPricingPolicyMapping ? $propertyChannelRoomRatePersonPricingPolicyMapping : [];
            // $deleteThis = collect($propertyChannelRoomRatePersonPricingPolicyMapping)->keyBy('id')->keys()->toArray();
            $insertData = [];
            if ($params['is_selected'] == true) {

                /*foreach ($propertyChannelRoomRatePersonPricingPolicyMapping as $adultMapping) {
                    $property_pricing_policy_adult = fillOnUndefined($adultMapping, 'property_pricing_policy_adult');
                    $adultCriteria = [
                        'criteria' => [
                            ['field' => 'id', 'condition' => '=', 'value' => $params['pricing_policy_adult_id']],
                        ]
                    ];

                    $propertyPersonPricingAdultPolicy = $this->propertyPricingPolicyAdultRepository->findByCriteria($adultCriteria, ['id', 'property_id', 'name', 'adult_action_type', 'adult', "action_type", "type", "value", 'reservation_start_date', 'reservation_end_date', "status"]);
                    if (
                        $property_pricing_policy_adult['adult_action_type'] == $propertyPersonPricingAdultPolicy['adult_action_type'] &&
                        $property_pricing_policy_adult['adult'] == $propertyPersonPricingAdultPolicy['adult']
                    ) {

                        throw new ApiErrorException('enw-person_pricing_one_selected_error');
                    }
                }*/

                $insertData[] = [
                    'property_id' => $params['property_id'],
                    'pricing_policy_adult_id' => $params['pricing_policy_adult_id'],
                    'room_rate_channel_mapping_id' => $params['room_rate_channel_mapping_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->propertyChannelRoomRatePricingPolicyAdultMappingRepository->insert($insertData);
                    if ($createResult['status'] != 'success') {
                        throw new Exception('api-unknown_error');
                    }
                }
            } else {

                $criteria = [
                    'criteria' => [
                        ['field' => 'pricing_policy_adult_id', 'condition' => '=', 'value' => $params['pricing_policy_adult_id']],
                        ['field' => 'room_rate_channel_mapping_id', 'condition' => '=', 'value' => $params['room_rate_channel_mapping_id']],
                    ],
                    'firstRow' => true
                ];

                $propertyChannelRoomRatePersonPricingPolicyMapping = $this->propertyChannelRoomRatePricingPolicyAdultMappingRepository->findByCriteria($criteria);

                if ($propertyChannelRoomRatePersonPricingPolicyMapping['id']) {
                    $deleteThisArray = $this->propertyChannelRoomRatePricingPolicyAdultMappingRepository->destroy([$propertyChannelRoomRatePersonPricingPolicyMapping['id']]);
                    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 updateRoomRatePricingChildPolicy($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            DB::beginTransaction();

            $validationResult = $this->updateRoomRateChannelPersonPricingChildPolicyValidator->validate($params);
            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }
            $criteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'room_rate_channel_mapping_id', 'condition' => '=', 'value' => $params['room_rate_channel_mapping_id']],
                ],
                'with' => ['propertyPricingPolicyChild']
            ];

            $propertyChannelRoomRatePersonPricingPolicyMapping = $this->propertyChannelRoomRatePricingPolicyChildMappingRepository->findByCriteria($criteria);
            $propertyChannelRoomRatePersonPricingPolicyMapping = $propertyChannelRoomRatePersonPricingPolicyMapping ? $propertyChannelRoomRatePersonPricingPolicyMapping : [];

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

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

                $addPricingPolicy = $this->propertyPricingPolicyChildRepository->findByCriteria($criteria);
                if (!$addPricingPolicy) {
                    throw new ApiErrorException('Child data not found');
                }

                $oldDataMappingCollect = collect($propertyChannelRoomRatePersonPricingPolicyMapping)->map(function ($value) {
                    return [
                        'id' => $value['property_pricing_policy_child']['id'],
                        'name' => $value['property_pricing_policy_child']['name'],
                        'adult' => $value['property_pricing_policy_child']['adult'],
                        'child_order' => $value['property_pricing_policy_child']['child_order'],
                        'child_age_start' => $value['property_pricing_policy_child']['child_age_start'],
                        'child_age_end' => $value['property_pricing_policy_child']['child_age_end'],
                        'type' => $value['property_pricing_policy_child']['type'],
                        'value' => $value['property_pricing_policy_child']['value'],
                    ];
                });

                for ($age = $addPricingPolicy['child_age_start']; $age <= $addPricingPolicy['child_age_end']; $age++) {
                    /*$checkOldData = $oldDataMappingCollect->where('adult', '=', $addPricingPolicy['adult'])
                        ->where('child_age_start', '<=', $age)
                        ->where('child_age_end', '>', $age)
                        ->where('child_order', '=', $addPricingPolicy['child_order'])
                        ->first();
                    if ($checkOldData) {
                        throw new ApiErrorException('This mapping added before');
                    }*/
                }

                $insertData[] = [
                    'property_id' => $params['property_id'],
                    'pricing_policy_child_id' => $params['pricing_policy_child_id'],
                    'room_rate_channel_mapping_id' => $params['room_rate_channel_mapping_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->propertyChannelRoomRatePricingPolicyChildMappingRepository->insert($insertData);
                    if ($createResult['status'] != 'success') {
                        throw new Exception('api-unknown_error');
                    }
                }
            }

            if ($params['is_selected'] == false) {
                $deleteThis = collect($propertyChannelRoomRatePersonPricingPolicyMapping)
                    ->where('pricing_policy_child_id', '=', $params['pricing_policy_child_id'])
                    ->keyBy('id')->keys()->toArray();
                if ($deleteThis) {
                    $deleteThisArray = $this->propertyChannelRoomRatePricingPolicyChildMappingRepository->destroy($deleteThis);
                    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 getRoomRateChannelPersonPricingPolicy($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.propertyRoomRateChannelPricingAdultPolicy', 'propertyRoomRateMapping.propertyRoomRateChannel.propertyRoomRateChannelPricingChildPolicy', 'propertyRoomRateMapping.propertyRoomRate']
            ];

            $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']);


            $propertyPricingAdultPolicyRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ]
            ];
            $propertyPricingAdultPolicy = $this->propertyPricingPolicyAdultRepository->findByCriteria($propertyPricingAdultPolicyRequest, ['id', 'property_id', 'name', 'adult_action_type', 'adult', "action_type", "type", 'reservation_start_date', 'reservation_end_date', "value"]);
            $propertyPricingAdultPolicy = $propertyPricingAdultPolicy ? $propertyPricingAdultPolicy : [];

            array_multisort(
                array_column($propertyPricingAdultPolicy, 'adult'), SORT_ASC,
                array_column($propertyPricingAdultPolicy, 'adult_action_type'), SORT_ASC,
                $propertyPricingAdultPolicy
            );

            $propertyPricingChildPolicyRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ]
            ];
            $propertyPricingChildPolicy = $this->propertyPricingPolicyChildRepository->findByCriteria($propertyPricingChildPolicyRequest, ['id', 'property_id', 'name', 'adult', 'child_order', 'child_age_start', 'child_age_end', 'reservation_start_date', 'reservation_end_date', 'type', 'value']);
            $propertyPricingChildPolicy = $propertyPricingChildPolicy ? $propertyPricingChildPolicy : [];


            $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;
                        $propertyPersonPricingAdultPolicyArray = [];
                        $propertyPersonPricingChildPolicyArray = [];

                        if ($propertyRoomRateChannel) {
                            if ($propertyRoomRateChannel['status'] == 1) {
                                $mappingStatus = true;

                                foreach ($propertyPricingAdultPolicy as $adultPolicy) {
                                    $propertyRoomRateChannelAdultPricingPolicy = [];
                                    if (isset($propertyRoomRateChannel['property_room_rate_channel_pricing_adult_policy'])) {

                                        $propertyRoomRateChannelAdultPricingPolicy = collect($propertyRoomRateChannel['property_room_rate_channel_pricing_adult_policy'])
                                            ->where('pricing_policy_adult_id', '=', $adultPolicy['id'])
                                            ->where('room_rate_channel_mapping_id', '=', $propertyRoomRateChannel['id'])
                                            ->values()->toArray();
                                    }

                                    $propertyPersonPricingAdultPolicyArray[] = [
                                        'id' => $adultPolicy['id'],
                                        'property_id' => $adultPolicy['property_id'],
                                        'name' => $adultPolicy['name'],
                                        'adult_action_type' => $adultPolicy['adult_action_type'],
                                        'adult' => $adultPolicy['adult'],
                                        'action_type' => $adultPolicy['action_type'],
                                        'type' => $adultPolicy['type'],
                                        'value' => $adultPolicy['value'],
                                        'reservation_start_date' => $adultPolicy['reservation_start_date'],
                                        'reservation_end_date' => $adultPolicy['reservation_end_date'],
                                        'pricing_adult_policy_is_selected' => $propertyRoomRateChannelAdultPricingPolicy ? true : false,
                                    ];

                                }


                                foreach ($propertyPricingChildPolicy as $childPolicy) {
                                    $propertyRoomRateChannelChildPricingPolicy = [];
                                    if (isset($propertyRoomRateChannel['property_room_rate_channel_pricing_child_policy'])) {
                                        $propertyRoomRateChannelChildPricingPolicy = collect($propertyRoomRateChannel['property_room_rate_channel_pricing_child_policy'])
                                            ->where('pricing_policy_child_id', '=', $childPolicy['id'])
                                            ->where('room_rate_channel_mapping_id', '=', $propertyRoomRateChannel['id'])
                                            ->values()->toArray();
                                    }

                                    $propertyPersonPricingChildPolicyArray[] = [
                                        'id' => $childPolicy['id'],
                                        'property_id' => $childPolicy['property_id'],
                                        'name' => $childPolicy['name'],
                                        'adult' => $childPolicy['adult'],
                                        'child_order' => $childPolicy['child_order'],
                                        'child_age_start' => $childPolicy['child_age_start'],
                                        'child_age_end' => $childPolicy['child_age_end'],
                                        'reservation_start_date' => $childPolicy['reservation_start_date'],
                                        'reservation_end_date' => $childPolicy['reservation_end_date'],
                                        'type' => $childPolicy['type'],
                                        'value' => $childPolicy['value'],
                                        'pricing_child_policy_is_selected' => $propertyRoomRateChannelChildPricingPolicy ? true : false,
                                    ];
                                }

                                array_multisort(array_column($propertyPersonPricingChildPolicyArray, 'adult'), SORT_ASC,
                                    array_column($propertyPersonPricingChildPolicyArray, 'child_order'), SORT_ASC,
                                    $propertyPersonPricingChildPolicyArray);
                            }
                        }


                        $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_adult_pricing_policy'] = $propertyPersonPricingAdultPolicyArray;
                        $roomRateMapping['room_rate_channel_child_pricing_policy'] = $propertyPersonPricingChildPolicyArray;


                        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 checkChannelRoomPricingType($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {

            $criteria =
                [
                    "criteria" =>
                        [
                            ["field" => "property_id", "condition" => "=", "value" => $params['property_id']],
                            ["field" => "channel_id", "condition" => "=", "value" => $params['channel_id']],
                        ],
                    'with' => ['channelRoomPricingType'],
                    'firstRow' => true
                ];
            $mapping = $this->propertyChannelMappingRepository->findByCriteria($criteria);
            if (!$mapping) {
                throw new ApiErrorException('Property Channel Setup not found ');
            }

            if ($mapping['channel_room_pricing_type']['code'] != 'PRS') {
                throw new ApiErrorException('Property Channel Room Pricing Type is not Per Pricing');
            }


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

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

}
