<?php

namespace App\Core\Service;


use App\Core\Repository\PlaceCategoryField\PlaceCategoryFieldRepository;
use App\Core\Repository\PlaceCategoryFieldMapping\PlaceCategoryFieldMappingRepository;
use App\Core\Repository\PlaceCategoryFieldOption\PlaceCategoryFieldOptionRepository;
use App\Core\Repository\PlaceCategoryFieldOptionFieldMapping\PlaceCategoryFieldOptionFieldMappingRepository;
use App\Core\Repository\PropertyPlaceCategoryFieldValue\PropertyPlaceCategoryFieldValueRepository;
use App\Core\Repository\PropertyPlace\PropertyPlaceRepository;
use App\Core\Repository\PropertyPlaceCategory\PropertyPlaceCategoryRepository;
use App\Core\Repository\PropertyPlaceFactMapping\PropertyPlaceFactMappingRepository;
use App\Core\Repository\PropertyPlaceFactTitleFactMapping\PropertyPlaceFactTitleFactMappingRepository;
use App\Core\Repository\PropertyPlacePhotoMapping\PropertyPlacePhotoMappingRepository;
use App\Core\Repository\PropertyPlaceWorkingHour\PropertyPlaceWorkingHourRepository;
use App\Core\Repository\PropertyUnit\PropertyUnitRepository;
use App\Core\Validator\PropertyPlace\PropertyPlaceCreateValidator;
use App\Core\Validator\PropertyPlace\PropertyPlaceFactMappingUpdateValidator;
use App\Core\Validator\PropertyPlace\PropertyPlaceUpdateValidator;
use App\Core\Validator\PropertyPlace\PropertyPlacePhotoMappingAddValidator;
use Illuminate\Support\Facades\Log;
use Exception;
use App\Exceptions\ApiErrorException;
use Illuminate\Support\Facades\Config;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use function GuzzleHttp\Promise\all;


class PropertyPlaceService
{

    private $propertyPlaceRepository;
    private $propertyPlaceCategoryRepository;
    private $propertyPlaceWorkingHourRepository;
    private $propertyPlaceCreateValidator;
    private $propertyPlacePhotoMappingRepository;
    private $propertyPlacePhotoMappingAddValidator;
    private $propertyPlaceUpdateValidator;
    private $propertyPlaceFactTitleFactMappingRepository;
    private $propertyPlaceFactMappingRepository;
    private $propertyPlaceFactMappingUpdateValidator;
    private $placeCategoryFieldRepository;
    private $placeCategoryFieldOptionRepository;
    private $placeCategoryFieldOptionFieldMappingRepository;
    private $propertyPlaceCategoryFieldValueRepository;
    private $placeCategoryFieldMappingRepository;
    private $propertyUnitRepository;
    private $include;

    public function __construct(

        PropertyPlaceRepository $propertyPlaceRepository,
        PropertyPlaceCategoryRepository $propertyPlaceCategoryRepository,
        PropertyPlaceWorkingHourRepository $propertyPlaceWorkingHourRepository,
        PropertyPlaceCreateValidator $propertyPlaceCreateValidator,
        PropertyPlaceUpdateValidator $propertyPlaceUpdateValidator,
        PropertyPlacePhotoMappingAddValidator $propertyPlacePhotoMappingAddValidator,
        PropertyPlaceFactTitleFactMappingRepository $propertyPlaceFactTitleFactMappingRepository,
        PropertyPlaceFactMappingRepository $propertyPlaceFactMappingRepository,
        PropertyPlaceFactMappingUpdateValidator $propertyPlaceFactMappingUpdateValidator,
        PlaceCategoryFieldRepository $placeCategoryFieldRepository,
        PlaceCategoryFieldOptionRepository $placeCategoryFieldOptionRepository,
        PlaceCategoryFieldOptionFieldMappingRepository $placeCategoryFieldOptionFieldMappingRepository,
        PropertyPlaceCategoryFieldValueRepository $propertyPlaceCategoryFieldValueRepository,
        PlaceCategoryFieldMappingRepository $placeCategoryFieldMappingRepository,
        PropertyUnitRepository $propertyUnitRepository,
        PropertyPlacePhotoMappingRepository $propertyPlacePhotoMappingRepository,
        LanguageService $languageService

    )
    {

        $this->propertyPlaceRepository = $propertyPlaceRepository;
        $this->propertyPlaceCategoryRepository = $propertyPlaceCategoryRepository;
        $this->propertyPlaceWorkingHourRepository = $propertyPlaceWorkingHourRepository;
        $this->propertyPlaceCreateValidator = $propertyPlaceCreateValidator;
        $this->propertyPlacePhotoMappingRepository = $propertyPlacePhotoMappingRepository;
        $this->propertyPlacePhotoMappingAddValidator = $propertyPlacePhotoMappingAddValidator;
        $this->propertyPlaceUpdateValidator = $propertyPlaceUpdateValidator;
        $this->propertyPlaceFactTitleFactMappingRepository = $propertyPlaceFactTitleFactMappingRepository;
        $this->propertyPlaceFactMappingRepository = $propertyPlaceFactMappingRepository;
        $this->propertyPlaceFactMappingUpdateValidator = $propertyPlaceFactMappingUpdateValidator;
        $this->placeCategoryFieldRepository = $placeCategoryFieldRepository;
        $this->placeCategoryFieldOptionRepository = $placeCategoryFieldOptionRepository;
        $this->placeCategoryFieldOptionFieldMappingRepository = $placeCategoryFieldOptionFieldMappingRepository;
        $this->propertyPlaceCategoryFieldValueRepository = $propertyPlaceCategoryFieldValueRepository;
        $this->placeCategoryFieldMappingRepository = $placeCategoryFieldMappingRepository;
        $this->propertyUnitRepository = $propertyUnitRepository;
        $this->languageService = $languageService;

        $this->include = [
            [
                'id' => 1,
                'name' => 'Paid Services',
                'language_key' => 'input-option-paid_services',
            ],
            [
                'id' => 2,
                'name' => 'Free',
                'language_key' => 'input-option-free',
            ]
        ];

    }

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

            DB::beginTransaction();

            $validationResult = $this->propertyPlaceCreateValidator->validate($param);

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

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

            $languageName = [];
            foreach (fillOnUndefined($param, "language_name", []) as $value) {
                $languageName[$value['language_code']] = $value['name'];
            }


            $insertData = [
                "property_id" => fillOnUndefined($param, "property_id"),
                "name" => fillOnUndefined($param, "name"),
                "language_name" => !empty($languageName) ? json_encode($languageName) : null,
                "place_category_id" => fillOnUndefined($param, "place_category_id"),
                "place_working_hour_id" => fillOnUndefined($param, "place_working_hour_id"),
                "reservation_requirement" => fillOnUndefined($param, "reservation_requirement"),
                "include" => fillOnUndefined($param, "include"),
                "web" => fillOnUndefined($param, "web"),
                "menu" => fillOnUndefined($param, "menu"),
                "contact_form" => fillOnUndefined($param, "contact_form"),
                "description" => !empty($description) ? json_encode($description) : null,
                "status" => 1,
                "created_by" => fillOnUndefined($param, "user_id"),
                "updated_by" => fillOnUndefined($param, "user_id"),
                "created_at" => time(),
                "updated_at" => time(),
            ];

            $userCreateResult = $this->propertyPlaceRepository->create($insertData);
            if ($userCreateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }

            $placeData = $userCreateResult['data'];

            $placeCategoryRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_place_category_id', 'condition' => '=', 'value' => $placeData['place_category_id']],
                ],
                'with' => ['placeCategoryField'],
                'orderBy' => [["field" => "order_number", "value" => "ASC"]],
            ];
            $placeCategoryMappingData = $this->placeCategoryFieldMappingRepository->findByCriteria($placeCategoryRequest);
            $placeCategoryMappingData = $placeCategoryMappingData ? $placeCategoryMappingData : [];
            $placeCategories = collect($placeCategoryMappingData)->map(function ($value) {
                return $value['place_category_field'];
            });

            $fieldValues = fillOnUndefined($param, 'field_values', []);
            $insertFieldValue = [];

            foreach ($fieldValues as $fieldKey => $fieldValue) {

                if (strpos($fieldKey, '_unit') > -1) {
                    continue;
                }

                if (strpos($fieldKey, '_max') > -1) {
                    continue;
                }

                $fieldInfo = $placeCategories->where('id', '=', $fieldValue['field_id'])->where('name', '=', $fieldValue['field_name'])->first();
                if (!$fieldInfo) {
                    throw new Exception('api-unknown_error');
                }

                $fieldStatics = [
                    'property_id' => $param['property_id'],
                    'place_id' => $placeData['id'],
                    'property_place_category_id' => $placeData['place_category_id'],
                    'place_category_field_id' => $fieldValue['field_id'],
                    'status' => 1,
                    'created_by' => fillOnUndefined($param, 'user_id'),
                    'updated_by' => fillOnUndefined($param, 'user_id'),
                    'created_at' => Carbon::now()->timestamp,
                    'updated_at' => Carbon::now()->timestamp,
                ];

                if ($fieldInfo['element'] == 'multiselect') {
                    foreach ($fieldValue['field_value'] as $item) {
                        $value = [
                            'input_value' => null,
                            'option_value' => $item,
                            'unit_value' => null,
                        ];
                        $insertFieldValue[] = array_merge($fieldStatics, $value);
                    }
                } elseif ($fieldInfo['element'] == 'inputunit') {
                    $searchKey = $fieldValue['field_id'] . '_unit';
                    if (!isset($fieldValues[$searchKey]['field_unit_value'])) {
                        throw new Exception('api-unknown_error');
                    }
                    $value = [
                        'input_value' => $fieldValue['field_value'],
                        'option_value' => null,
                        'unit_value' => $fieldValues[$searchKey]['field_unit_value'],
                    ];

                    $insertFieldValue[] = array_merge($fieldStatics, $value);

                } elseif ($fieldInfo['element'] == 'slider') {

                    $maxData = null;
                    if (isset($fieldValues['3_max']) && isset($fieldValues['3_max']['field_max_value']) && $fieldValues['3_max']['field_max_value']) {
                        $maxData = $fieldValues['3_max']['field_max_value'];
                    }


                    if (($fieldValue['field_value'] && $maxData === NULL) || $maxData && !$fieldValue['field_value']) {
                        throw new Exception('Min Age and Max Age is required');
                    }

                    $inputValue = $fieldValue['field_value'] && $maxData ? $fieldValue['field_value'] . '-' . $maxData : null;
                    $value = [
                        'input_value' => $inputValue,
                        'option_value' => null,
                        'unit_value' => null,
                    ];

                    $insertFieldValue[] = array_merge($fieldStatics, $value);

                } else {
                    $value = [
                        'input_value' => $fieldInfo['element'] != 'select' ? $fieldValue['field_value'] : null,
                        'option_value' => $fieldInfo['element'] == 'select' ? $fieldValue['field_value'] : null,
                        'unit_value' => null,
                    ];
                    $insertFieldValue[] = array_merge($fieldStatics, $value);

                }
            }

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

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

        return output($response);
    }

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

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

        try {

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

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

        try {

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

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

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

        return output($response);
    }

    public function update($param = [])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            DB::beginTransaction();
            $placeId = fillOnUndefined($param, "property_place_id");
            $placeRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($param, 'property_id')],
                    ['field' => 'id', 'condition' => '=', 'value' => $placeId],
                ],
                'firstRow' => true
            ];
            $propertyWebData = $this->propertyPlaceRepository->findByCriteria($placeRequest, ['id', 'name', 'place_category_id']);

            if (!$propertyWebData) {
                throw new ApiErrorException(lang('Property - Place mapping not found.'));
            }


            $paramPlaceCategoryId = fillOnUndefined($param, 'place_category_id');

            if ($paramPlaceCategoryId && ($propertyWebData['place_category_id'] != $paramPlaceCategoryId)) {

                $propertyPlaceFactMappingRequest = [
                    'criteria' => [
                        ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($param, 'property_id')],
                        ['field' => 'property_place_id', 'condition' => '=', 'value' => $placeId]
                    ]

                ];
                $propertyPlaceFactMappingData = $this->propertyPlaceFactMappingRepository->findByCriteria($propertyPlaceFactMappingRequest);

                $propertyPlaceFactMappingData = $propertyPlaceFactMappingData ? $propertyPlaceFactMappingData : [];

                $propertyPlaceFactMappingIds = collect($propertyPlaceFactMappingData)->keyBy('id')->keys()->all();

                if ($propertyPlaceFactMappingIds) {

                    $propertyPlaceFactMappingDelete = $this->propertyPlaceFactMappingRepository->destroy($propertyPlaceFactMappingIds);

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


                $propertyPlacePhotoMappingRequest = [
                    'criteria' => [
                        ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($param, 'property_id')],
                        ['field' => 'place_id', 'condition' => '=', 'value' => $placeId]
                    ]

                ];

                $propertyPlacePhotoMapping = $this->propertyPlacePhotoMappingRepository->findByCriteria($propertyPlacePhotoMappingRequest);
                $propertyPlacePhotoMapping = $propertyPlacePhotoMapping ? $propertyPlacePhotoMapping : [];

                $propertyPlacePhotoMappingIds = collect($propertyPlacePhotoMapping)->keyBy('id')->keys()->all();
                if ($propertyPlacePhotoMappingIds) {

                    $propertyPlacePhotoMappingDelete = $this->propertyPlacePhotoMappingRepository->destroy($propertyPlacePhotoMappingIds);

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

            }

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

            $languageName = [];
            foreach (fillOnUndefined($param, "language_name", []) as $value) {
                $languageName[$value['language_code']] = $value['name'];
            }

            $updateData = [
                "name" => fillOnUndefined($param, "name"),
                "language_name" => !empty($languageName) ? json_encode($languageName) : null,
                "place_category_id" => fillOnUndefined($param, "place_category_id"),
                "place_working_hour_id" => fillOnUndefined($param, "place_working_hour_id"),
                "reservation_requirement" => fillOnUndefined($param, "reservation_requirement"),
                "include" => fillOnUndefined($param, "include"),
                "description" => !empty($description) ? json_encode($description) : null,
                "web" => fillOnUndefined($param, "web"),
                "menu" => fillOnUndefined($param, "menu"),
                "contact_form" => fillOnUndefined($param, "contact_form"),
                "status" => fillOnUndefined($param, "status", 1),
                "updated_by" => fillOnUndefined($param, "user_id"),
                "updated_at" => time(),
            ];

            $validationResult = $this->propertyPlaceUpdateValidator->validate($param);

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

            $updateResult = $this->propertyPlaceRepository->update($placeId, $updateData);


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

            $fieldValuesRequest = [
                'criteria' => [
                    ['field' => 'place_id', 'condition' => '=', 'value' => $placeId],
                ],

            ];
            $oldValuesData = $this->propertyPlaceCategoryFieldValueRepository->findByCriteria($fieldValuesRequest);
            $oldValuesData = $oldValuesData ? $oldValuesData : [];

            $deleteThisIds = collect($oldValuesData)->keyBy('id')->keys()->all();

            if ($deleteThisIds) {
                $deleteThisArray = $this->propertyPlaceCategoryFieldValueRepository->destroy($deleteThisIds);
                if ($deleteThisArray['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }
            }
            $placeCategoryRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_place_category_id', 'condition' => '=', 'value' => $updateData['place_category_id']],
                ],
                'with' => ['placeCategoryField'],
                'orderBy' => [["field" => "order_number", "value" => "ASC"]],
            ];
            $placeCategoryMappingData = $this->placeCategoryFieldMappingRepository->findByCriteria($placeCategoryRequest);
            $placeCategoryMappingData = $placeCategoryMappingData ? $placeCategoryMappingData : [];
            $placeCategories = collect($placeCategoryMappingData)->map(function ($value) {
                return $value['place_category_field'];
            });

            $fieldValues = fillOnUndefined($param, 'field_values', []);
            $insertFieldValue = [];
            foreach ($fieldValues as $fieldKey => $fieldValue) {

                if (strpos($fieldKey, '_unit') > -1) {
                    continue;
                }

                $fieldInfo = $placeCategories->where('id', '=', $fieldValue['field_id'])->where('name', '=', $fieldValue['field_name'])->first();
                if (!$fieldInfo) {
                    throw new Exception('api-unknown_error');
                }

                $fieldStatics = [
                    'property_id' => $updateData['property_id'],
                    'place_id' => $placeId,
                    'property_place_category_id' => $updateData['place_category_id'],
                    'place_category_field_id' => $fieldValue['field_id'],
                    'status' => 1,
                    'created_by' => fillOnUndefined($param, 'user_id'),
                    'updated_by' => fillOnUndefined($param, 'user_id'),
                    'created_at' => Carbon::now()->timestamp,
                    'updated_at' => Carbon::now()->timestamp,
                ];

                if ($fieldInfo['element'] == 'multiselect') {
                    foreach ($fieldValue['field_value'] as $item) {
                        $value = [
                            'input_value' => null,
                            'option_value' => $item,
                            'unit_value' => null,
                        ];
                        $insertFieldValue[] = array_merge($fieldStatics, $value);
                    }
                } elseif ($fieldInfo['element'] == 'inputunit') {
                    $searchKey = $fieldValue['field_id'] . '_unit';
                    $fieldUnitValue = null;
                    if (isset($fieldValues[$searchKey]['field_unit_value'])) {
                        $fieldUnitValue = $fieldValues[$searchKey]['field_unit_value'];
                    }
                    $value = [
                        'input_value' => $fieldValue['field_value'],
                        'option_value' => null,
                        'unit_value' => $fieldUnitValue == "" ? null : $fieldUnitValue,
                    ];

                    $insertFieldValue[] = array_merge($fieldStatics, $value);

                } elseif ($fieldInfo['element'] == 'slider') {

                    if (isset($fieldValue['field_value']) && !empty($fieldValue['field_value'])) {

                        $count = collect($fieldValue['field_value'])->count();
                        if ($count == 1) {
                            throw new Exception('Min Age and Max Age is required');
                        }

                        if (($fieldValue['field_value'][0] && $fieldValue['field_value'][1] === NULL) || ($fieldValue['field_value'][0] === NULL && $fieldValue['field_value'][1])) {
                            throw new Exception('Min Age and Max Age is required');
                        }

                    }
                    $saveValue = null;
                    if (!in_array("", $fieldValue['field_value'])) {
                        $saveValue = implode('-', $fieldValue['field_value']);
                    }


                    $value = [
                        'input_value' => $saveValue,
                        'option_value' => null,
                        'unit_value' => null,
                    ];

                    $insertFieldValue[] = array_merge($fieldStatics, $value);

                } else {
                    $value = [
                        'input_value' => $fieldInfo['element'] != 'select' ? $fieldValue['field_value'] : null,
                        'option_value' => $fieldInfo['element'] == 'select' && !empty($fieldValue['field_value']) ? $fieldValue['field_value'] : null,
                        'unit_value' => null,

                    ];
                    $insertFieldValue[] = array_merge($fieldStatics, $value);

                }
            }

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

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

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

        return output($response);
    }

    public function getPropertyPlaceCategories($params = [])
    {

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

        try {

            $placeCategoryRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ]
            ];

            $placeCategoryData = $this->propertyPlaceCategoryRepository->findByCriteria($placeCategoryRequest);
            $placeCategories = collect($placeCategoryData);

            $categoryTriesRequest = [
                'parent_id' => null,
                'placeCategories' => $placeCategories
            ];


            $categoryTries = $this->categoryTries($categoryTriesRequest);


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

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

    private function categoryTries($params)
    {

        $placeCategories = $params['placeCategories'];
        $parentId = $params['parent_id'];
        $placeCategoryList = $placeCategories->where('parent_id', '=', $parentId)->all();
        $responseData = [];
        foreach ($placeCategoryList as $placeCategory) {

            $responseItem = [
                "id" => $placeCategory['id'],
                "name" => $placeCategory['name'],
                "language_key" => $placeCategory['language_key'],
                "parent_id" => $placeCategory['parent_id'],
                "level" => $placeCategory['level'],
                "order_number" => $placeCategory['order_number'],
                "icon" => $placeCategory['icon'],
                "child" => null
            ];

            $checkChild = $placeCategories->where('parent_id', '=', $placeCategory['id'])->count();

            if ($checkChild > 0) {
                $categoryTriesRequest = [
                    'parent_id' => $placeCategory['id'],
                    'placeCategories' => $placeCategories
                ];
                $categoryTries = $this->categoryTries($categoryTriesRequest);
                $responseItem['child'] = $categoryTries;
            }

            $responseData[$placeCategory['id']] = $responseItem;

        }


        return $responseData;

    }

    private function categoryTriesSingleArray($params)
    {

        $placeCategories = $params['placeCategories'];
        $parentId = $params['parent_id'];
        $placeCategoryList = $placeCategories->where('parent_id', '=', $parentId)->all();
        $responseData = [];
        foreach ($placeCategoryList as $placeCategory) {

            $responseItem = [
                "id" => $placeCategory['id'],
                "name" => $placeCategory['name'],
                "language_key" => $placeCategory['language_key'],
                "parent_id" => $placeCategory['parent_id'],
                "level" => $placeCategory['level'],
                "order_number" => $placeCategory['order_number'],
                "icon" => $placeCategory['icon'],

            ];

            $checkChild = $placeCategories->where('parent_id', '=', $placeCategory['id'])->count();
            $categoryTries = [];
            if ($checkChild > 0) {
                $categoryTriesRequest = [
                    'parent_id' => $placeCategory['id'],
                    'placeCategories' => $placeCategories
                ];
                $categoryTries = $this->categoryTriesSingleArray($categoryTriesRequest);
            }
            $responseData[] = $responseItem;
            $responseData = array_merge($responseData, $categoryTries);
        }

        return $responseData;

    }

    public function getPropertyWorkingHours($params = [])
    {

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

        try {

            $placeCategoryRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ]
            ];

            $placeWorkingHourData = $this->propertyPlaceWorkingHourRepository->findByCriteria($placeCategoryRequest);
            $placeWorkingHours = collect($placeWorkingHourData)->map(function ($value) {

                return [
                    "id" => $value['id'],
                    "name" => $value['name'],
                    "language_key" => $value['language_key'],
                    "status" => $value['status'],
                ];

            });

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

        } 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 listPlaces($params = [])
    {

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

        try {

            $placeRequest = [
                'criteria' => [
                    //['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['propertyPlaceCategory', 'propertyPlaceWorkingHour']
            ];
            $placeData = $this->propertyPlaceRepository->findByCriteria($placeRequest);
            $placeData = $placeData ? $placeData : [];


            $placeCategoryRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ]
            ];

            $placeCategoryData = $this->propertyPlaceCategoryRepository->findByCriteria($placeCategoryRequest);
            $placeCategories = collect($placeCategoryData);


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

            $places = [];

            foreach ($placeData as $place) {
                $include = collect($this->include)->where('id', '=', $place['include'])->first();

                $descriptionLangContents = json_decode($place['description'], 1);
                $responseLangDescription = [];
                foreach ($applicationLanguages as $applicationLanguage) {
                    $langKey = $applicationLanguage['code'];
                    $responseLangDescription[] = [
                        'language_code' => $langKey,
                        'description' => isset($descriptionLangContents[$langKey]) ? $descriptionLangContents[$langKey] : null
                    ];
                }

                $languageNameContents = json_decode($place['language_name'], 1);
                $responseLanguageName = [];
                foreach ($applicationLanguages as $applicationLanguage) {
                    $langKey = $applicationLanguage['code'];
                    $responseLanguageName[] = [
                        'language_code' => $langKey,
                        'name' => isset($languageNameContents[$langKey]) ? $languageNameContents[$langKey] : null
                    ];
                }

                $exportPlace = [
                    "id" => $place['id'],
                    "property_id" => $place['property_id'],
                    "name" => $place['name'],
                    "place_category_id" => $place['place_category_id'],
                    "place_working_hour_id" => $place['place_working_hour_id'],
                    "place_working_hour_name" => $place['property_place_working_hour']['name'],
                    "place_working_hour_language_key" => $place['property_place_working_hour']['language_key'],
                    "reservation_requirement" => $place['reservation_requirement'],
                    "contact_form" => $place['contact_form'],
                    "include_name" => isset($include) ? $include['name'] : null,
                    "include_language_key" => isset($include) ? $include['language_key'] : null,
                    "order_number" => $place['order_number'],
                    "description" => $responseLangDescription,
                    "language_name" => $responseLanguageName,
                    "web" => $place['web'],
                    "menu" => $place['menu'],
                    "include" => $place['include'],
                    "status" => $place['status'],
                ];

                $categoryParentRequest = [
                    'parent_id' => isset($place['property_place_category']) ? $place['property_place_category']['parent_id'] : null,
                    'placeCategories' => $placeCategories
                ];

                $placeCategoryArray = [];

                $placeCategoryArray[] = $place['property_place_category'];
                if ($place['property_place_category']['parent_id'] != null) {
                    $parentCategory = $this->categoryParents($categoryParentRequest);
                    $placeCategoryArray = array_merge($placeCategoryArray, $parentCategory);
                }
                $categories = collect($placeCategoryArray)->sortBy('level')->all();

                $level = 1;
                $categoryFilter = [];
                foreach ($categories as $category) {
                    $exportPlace['category_tree'][$level] = [
                        "id" => $category['id'],
                        "name" => $category['name'],
                        "language_key" => $category['language_key'],
                        "parent_id" => $category['parent_id'],
                        "level" => $category['level'],
                        "order_number" => $category['order_number'],
                        "icon" => $category['icon'],
                        "status" => $category['status'],
                    ];
                    $level++;
                    $categoryFilter[] = $category['id'];
                }
                $exportPlace['category_filters'] = $categoryFilter;

                $places[] = $exportPlace;
            }


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

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

    private function categoryParents($params)
    {
        $placeCategories = $params['placeCategories'];
        $parentId = $params['parent_id'];
        $placeCategory = $placeCategories->where('id', '=', $parentId)->first();
        $responseData[] = $placeCategory;

        if (isset($placeCategory) && $placeCategory['parent_id'] != null) {
            $categoryParentRequest = [
                'parent_id' => $placeCategory['parent_id'],
                'placeCategories' => $placeCategories
            ];
            $parentCategory = $this->categoryParents($categoryParentRequest);
            $responseData = array_merge($responseData, $parentCategory);
        }
        return $responseData;
    }

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

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

            $addPropertyPlacePhotoMapping = [];
            $addPhotoList = collect($params['property_place_photo'])
                ->where('is_selected', '=', true);
            $addPhotoIds = $addPhotoList->keyBy("id")->keys()->toArray();

            $removePhotoList = collect($params['property_place_photo'])
                ->where('is_selected', '=', false);

            $removePhotoIds = $removePhotoList->keyBy("id")->keys()->toArray();

            $checkPropertyMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'place_id', 'condition' => '=', 'value' => $params['place_id']],
                ],
                "whereIn" => [
                    ["field" => "photo_id", "value" => $addPhotoIds]
                ]
            ];
            $checkPropertyMappingResponse = $this->select($checkPropertyMappingRequest, ['id', 'property_id', 'photo_id']);

            if ($checkPropertyMappingResponse['status'] != 'success') {
                throw new ApiErrorException(lang('Mapping data not loaded'));
            }
            $checkPropertyMappingCollect = collect($checkPropertyMappingResponse['data']);

            foreach ($addPhotoList->toArray() as $key => $param) {

                if (
                !$checkPropertyMappingCollect->where('property_id', '=', $params['property_id'])
                    ->where('photo_id', '=', $param['id'])
                    ->first()
                ) {

                    $addPropertyPlacePhotoMapping[] =
                        [
                            'property_id' => $params['property_id'],
                            'place_id' => $params['place_id'],
                            'photo_id' => fillOnUndefined($param, 'id'),
                            'created_by' => $params['user_id'],
                            'updated_by' => $params['user_id'],
                        ];
                }
            }

            $response = $this->propertyPlacePhotoMappingRepository->createAll($addPropertyPlacePhotoMapping);

            if ($removePhotoIds) {

                $findCriteria = [
                    'criteria' => [
                        ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                        ['field' => 'place_id', 'condition' => '=', 'value' => $params['place_id']],
                    ],
                    "whereIn" =>
                        [
                            ["field" => "photo_id", "value" => $removePhotoIds]
                        ]
                ];

                $deletePropertyPlacePhotoMapping = $this->propertyPlacePhotoMappingRepository->findByCriteria($findCriteria);

                $deleteThisIds = [];
                foreach ($deletePropertyPlacePhotoMapping as $deleteThisItem) {
                    $deleteThisIds[] = $deleteThisItem['id'];
                }

                if ($deleteThisIds) {
                    $this->propertyPlacePhotoMappingRepository->deleteById($deleteThisIds);
                }
            }

            if ($response['status'] != 'success') {
                throw new ApiErrorException(lang('Data is not added'));
            }

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

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

        return output($response);
    }

    public function updateStatus($param = [])
    {

        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $placeId = fillOnUndefined($param, "property_place_id");
            $placeRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($param, 'property_id')],
                    ['field' => 'id', 'condition' => '=', 'value' => $placeId],
                ]
            ];
            $propertyWebData = $this->propertyPlaceRepository->findByCriteria($placeRequest, ['id', 'name']);

            if (!$propertyWebData) {
                throw new ApiErrorException(lang('Property - Place mapping not found.'));
            }

            $updateData =
                [
                    "status" => fillOnUndefined($param, "set_status", 0),
                    "updated_by" => fillOnUndefined($param, "user_id"),
                    "updated_at" => time(),
                ];

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

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

        return output($response);
    }

    public function deletePlace($params = [])
    {

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

        try {

            DB::beginTransaction();

            $placeRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($params, 'property_id')],
                    ['field' => 'id', 'condition' => '=', 'value' => fillOnUndefined($params, 'property_place_id')],
                ],
                'with' => ['propertyPlaceCategory', 'propertyPlaceWorkingHour', 'propertyPlacePhotoMapping'],
                "firstRow" => 1
            ];
            $placeData = $this->propertyPlaceRepository->findByCriteria($placeRequest);
            if (!$placeData) {
                throw new ApiErrorException(lang('Property - Place not found.'));
            }
            $deleteIds = collect($placeData['property_place_photo_mapping'])->keyBy('id')->keys()->all();
            if ($deleteIds) {
                $deletePhotoMapping = $this->propertyPlacePhotoMappingRepository->destroy($deleteIds);
                if ($deletePhotoMapping['status'] != "success") {
                    throw new Exception('api-unknown_error');
                }
            }

            $deletePlaceCriteria = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['property_place_id']]
                ]
            ];
            $this->propertyPlaceRepository->delete($deletePlaceCriteria);


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

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

        return output($response);
    }

    public function getPropertyPlaceCategoriesSingle($params = [])
    {

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

        try {

            $placeCategoryRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
            ];

            $placeCategoryData = $this->propertyPlaceCategoryRepository->findByCriteria($placeCategoryRequest);
            $placeCategories = collect($placeCategoryData);

            $categoryTries = $placeCategories->map(function ($value) {

                return [
                    "id" => $value['id'],
                    "name" => $value['name'],
                    "language_key" => $value['language_key'],
                    "parent_id" => $value['parent_id'],
                    "level" => $value['level'],
                    "order_number" => $value['order_number'],
                    "icon" => $value['icon'],
                ];
            })->values()->all();

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

        } 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 editPlaces($params = [])
    {

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

        try {

            $placeRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => $params['property_place_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['propertyPlaceCategory', 'propertyPlaceWorkingHour'],
                'firstRow' => 1
            ];
            $placeData = $this->propertyPlaceRepository->findByCriteria($placeRequest);
            if (!$placeData) {
                throw new ApiErrorException(lang('Property - Place not found.'));
            }
            $placeCategoryRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ]
            ];

            $placeCategoryData = $this->propertyPlaceCategoryRepository->findByCriteria($placeCategoryRequest);
            $placeCategories = collect($placeCategoryData);

            $place = $placeData;
            $include = collect($this->include)->where('id', '=', $place['include'])->first();


            $exportPlace = [
                "id" => $place['id'],
                "property_id" => $place['property_id'],
                "name" => $place['name'],
                "place_category_id" => $place['place_category_id'],
                "place_working_hour_id" => $place['place_working_hour_id'],
                "place_working_hour_name" => $place['property_place_working_hour']['name'],
                "place_working_hour_language_key" => $place['property_place_working_hour']['language_key'],
                "reservation_requirement" => $place['reservation_requirement'],
                "include" => $place['include'],
                "include_name" => isset($include) ? $include['name'] : null,
                "include_language_key" => isset($include) ? $include['language_key'] : null,
                "web" => $place['web'],
                "status" => $place['status'],
            ];

            $categoryParentRequest = [
                'parent_id' => isset($place['property_place_category']) ? $place['property_place_category']['parent_id'] : null,
                'placeCategories' => $placeCategories
            ];

            $placeCategoryArray = [];

            $placeCategoryArray[] = $place['property_place_category'];
            if ($place['property_place_category']['parent_id'] != null) {
                $parentCategory = $this->categoryParents($categoryParentRequest);
                $placeCategoryArray = array_merge($placeCategoryArray, $parentCategory);
            }
            $categories = collect($placeCategoryArray)->sortBy('level')->all();

            $level = 1;
            $categoryFilter = [];
            foreach ($categories as $category) {
                $exportPlace['category_tree'][$level] = [
                    "id" => $category['id'],
                    "name" => $category['name'],
                    "language_key" => $category['language_key'],
                    "parent_id" => $category['parent_id'],
                    "level" => $category['level'],
                    "order_number" => $category['order_number'],
                    "icon" => $category['order_number'],
                    "status" => $category['status'],
                ];
                $level++;
                $categoryFilter[] = $category['id'];
            }
            $exportPlace['category_filters'] = json_encode($categoryFilter);

            $categoryTries = $placeCategories->map(function ($value) {

                return [
                    "id" => $value['id'],
                    "name" => $value['name'],
                    "language_key" => $value['language_key'],
                    "parent_id" => $value['parent_id'],
                    "level" => $value['level'],
                    "order_number" => $value['order_number'],
                    "icon" => $value['icon'],
                ];
            })->values()->all();


            $responseData = [
                'place' => $exportPlace,
                'place_categories' => $categoryTries,
                'place_includes' => $this->include,

            ];


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

        } 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 listPlaceFacilities($params = [])
    {

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

        try {

            $placeRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'id', 'condition' => '=', 'value' => $params['place_id']],
                ],
                'firstRow' => true,
            ];
            $placeData = $this->propertyPlaceRepository->findByCriteria($placeRequest);
            if (!$placeData) {
                throw new ApiErrorException(lang('Property - Place not found.'));
            }

            $placeFactTitleFactMappingRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'place_category_id', 'condition' => '=', 'value' => $placeData['place_category_id']],
                ],
                'with' => ['placeCategory', 'placeFactTitle', 'placeFact']
            ];

            $placeFactTitleFactMappingData = $this->propertyPlaceFactTitleFactMappingRepository->findByCriteria($placeFactTitleFactMappingRequest);
            $placeFactTitleFactMapping = collect($placeFactTitleFactMappingData);

            $placeFactTitleFactMappingRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'property_place_id', 'condition' => '=', 'value' => $params['place_id']],
                ],
            ];

            $placeFactMappingData = $this->propertyPlaceFactMappingRepository->findByCriteria($placeFactTitleFactMappingRequest);
            $placeFactMapping = collect($placeFactMappingData);

            $titleGroups = $placeFactTitleFactMapping->groupBy('place_fact_title_id')->toArray();
            $exportTitles = [];

            foreach ($titleGroups as $titleGroupList) {
                if (!$titleGroupList) {
                    continue;
                }
                $exportTitleGroup = $titleGroupList[0]['place_fact_title'];
                $facts = [];
                foreach ($titleGroupList as $title) {
                    $checkSelected = $placeFactMapping
                        ->where('place_fact_title_fact_mapping_id', '=', $title['id'])
                        ->where('property_place_id', '=', $params['place_id'])
                        ->first();
                    $exportItem = $title['place_fact'];
                    $exportItem['place_fact_title_fact_mapping_id'] = $title['id'];
                    $exportItem['is_selected'] = isset($checkSelected);
                    $facts[] = $exportItem;
                }
                $exportTitleGroup['facts'] = $facts;
                $exportTitles[] = $exportTitleGroup;
            }

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

        } 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 updatePlaceFacilities($params = [])
    {

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

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

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


            $placeRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ]
            ];
            $propertyPlaceData = $this->propertyPlaceRepository->findByCriteria($placeRequest, ['id', 'name']);

            if (!$propertyPlaceData) {
                throw new ApiErrorException(lang('Property - Place mapping not found.'));
            }

            $propertyPlaceFactMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($params, 'property_id')],
                    ['field' => 'property_place_id', 'condition' => '=', 'value' => fillOnUndefined($params, 'place_id')],
                    ['field' => 'place_fact_title_fact_mapping_id', 'condition' => '=', 'value' => $params['place_fact_title_fact_mapping_id']],
                ],
                'firstRow' => true
            ];
            $propertyPlaceFactMappingData = $this->propertyPlaceFactMappingRepository->findByCriteria($propertyPlaceFactMappingRequest);


            if ($params['is_selected']) {

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

                $insertData =
                    [
                        "property_id" => fillOnUndefined($params, "property_id"),
                        "property_place_id" => fillOnUndefined($params, "place_id"),
                        "place_fact_title_fact_mapping_id" => fillOnUndefined($params, "place_fact_title_fact_mapping_id"),
                        "status" => 1,
                        "created_by" => fillOnUndefined($params, "user_id"),
                        "updated_by" => fillOnUndefined($params, "user_id"),
                        "created_at" => time(),
                        "updated_at" => time(),
                    ];

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

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

                $deleteThis[] = $propertyPlaceFactMappingData['id'];
                $this->propertyPlaceFactMappingRepository->deleteById($deleteThis);
            }

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

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

        return output($response);
    }

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

            $placeCategoryRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_place_category_id', 'condition' => '=', 'value' => $params['place_category_id']],
                ],
                'with' => ['placeCategoryField.placeFieldOptionMapping.placeCategoryFieldOption'],
                'orderBy' => [["field" => "order_number", "value" => "ASC"]],

            ];
            $placeCategoryMappingData = $this->placeCategoryFieldMappingRepository->findByCriteria($placeCategoryRequest);
            $placeCategoryMappingData = $placeCategoryMappingData ? $placeCategoryMappingData : [];

            $oldValuesData = [];
            if ($params['place_id']) {
                $fieldValuesRequest = [
                    'criteria' => [
                        ['field' => 'status', 'condition' => '=', 'value' => 1],
                        ['field' => 'property_place_category_id', 'condition' => '=', 'value' => $params['place_category_id']],
                        ['field' => 'place_id', 'condition' => '=', 'value' => $params['place_id']],
                    ],

                ];
                $oldValuesData = $this->propertyPlaceCategoryFieldValueRepository->findByCriteria($fieldValuesRequest);
                $oldValuesData = $oldValuesData ? $oldValuesData : [];
            }
            $oldValues = collect($oldValuesData);
            $responseFields = [];


            $fieldUnitsRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],

            ];
            $fieldUnitData = $this->propertyUnitRepository->findByCriteria($fieldUnitsRequest);
            $fieldUnitData = collect($fieldUnitData);

            foreach ($placeCategoryMappingData as $mapping) {
                if (!$mapping['place_category_field']) {
                    continue;
                }

                $field = $mapping['place_category_field'];
                $fieldUnitShortName = null;
                $oldFieldValues = $oldValues
                    ->where('property_place_category_id', '=', $params['place_category_id'])
                    ->where('place_category_field_id', '=', $field['id']);

                if ($field['element'] == 'multiselect') {
                    $oldValue = $oldFieldValues->keyBy('option_value')->keys()->all();
                } elseif ($field['element'] == 'select') {
                    $oldValue = $oldFieldValues->keyBy('option_value')->keys()->first();
                } elseif ($field['element'] == 'slider') {
                    $getOldValue = $oldFieldValues->keyBy('input_value')->keys()->first();
                    $oldValue = $getOldValue ? explode('-', $getOldValue) : [];
                } else {
                    $oldValue = $oldFieldValues->first();
                    $oldValue = $oldValue['input_value'];
                }

                $fieldUnits = null;
                $oldUnitValue = null;
                $unitShortName = null;
                if ($field['element'] == 'inputunit') {
                    $fieldAttribute = json_decode($field['field_attribute'], 1);
                    if (!isset($fieldAttribute['units'])) {
                        throw new Exception('api-unknown_error');
                    }

                    $oldUnit = $oldFieldValues->first();
                    $oldUnitValue = $oldUnit['unit_value'];
                    $oldUnitData = $fieldUnitData->where('id', '=', $oldUnit['unit_value'])->first();
                    $unitShortName = $oldUnitData['short_name'];

                    $fieldUnits = $fieldUnitData->whereIn('id', $fieldAttribute['units'])->map(function ($unit) use ($oldUnitValue) {
                        return [
                            "id" => $unit['id'],
                            "name" => $unit['name'],
                            "language_key" => $unit['language_key'],
                            "short_name" => $unit['short_name'],
                            "is_selected" => $oldUnitValue == $unit['id'],
                        ];
                    })->values()->all();
                }

                $responseField = [
                    'field_id' => $field['id'],
                    'field_name' => $field['name'],
                    'field_value' => $oldValue,
                    'field_unit_value' => $oldUnitValue,
                    'field_unit_short_name' => $unitShortName,
                    'field_place_category_id' => $field['id'],
                    'field_label' => $field['label'],
                    'field_language_key' => $field['language_key'],
                    'field_element' => $field['element'],
                    'field_type' => $field['type'],
                    'field_attribute' => json_decode($field['field_attribute'], 1),
                    'field_order_number' => $mapping['order_number'],
                    'field_status' => $field['status'],
                    'field_units' => $fieldUnits,

                ];
                if ($field['place_field_option_mapping']) {
                    $searchArray = $field['element'] != 'multiselect' ? [$oldValue] : $oldValue;
                    $options = collect($field['place_field_option_mapping'])->mapWithKeys(function ($value) use ($searchArray) {

                        $optionIsSelected = array_search($value['place_category_field_option']['id'], $searchArray) > -1 ? true : false;
                        return [
                            $value['place_category_field_option']['id'] =>
                                [
                                    'option_id' => $value['place_category_field_option']['id'],
                                    'option_name' => $value['place_category_field_option']['name'],
                                    'option_language_key' => $value['place_category_field_option']['language_key'],
                                    'option_status' => $value['place_category_field_option']['status'],
                                    'option_is_selected' => $optionIsSelected,
                                ]
                        ];

                    })->toArray();
                    $responseField['options'] = $options;
                }
                $responseFields[$field['id']] = $responseField;
                if ($field['element'] == 'inputunit') {
                    $responseField['field_id'] = $field['id'] . '_unit';
                    unset($responseField['field_element']);
                    $responseFields[$field['id'] . '_unit'] = $responseField;
                }
            }
            $response = [
                'status' => true,
                'data' => $responseFields,
            ];

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

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

        try {
            $deleteCriteria = [
                'criteria' => [
                    ['field' => 'photo_id', 'condition' => '=', 'value' => $params['photo_id']],
                ]
            ];
            $deleteData = $this->propertyPlacePhotoMappingRepository->findByCriteria($deleteCriteria, ['id']);
            $deleteData = $deleteData ? $deleteData : [];
            if ($deleteData) {
                $deleteIds = array_column($deleteData, 'id');
                $destroyResult = $this->propertyPlacePhotoMappingRepository->destroy($deleteIds);
                if ($destroyResult['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }
            }

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


    }

    public function insertNewFieldMapping($params)
    {

        // bu fonksiyon yeni bir field eklendiğinde mapping eklenebilmesi için konmuştur.

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

        try {


            die();
            $mappingData = $this->placeCategoryFieldMappingRepository->findByCriteria();
            $mapping = collect($mappingData);
            $categoryList = $mapping->where('property_place_category_field_id', '=', $params['before_field'])->all();
            $withoutList = $mapping
                ->where('property_place_category_field_id', '!=', $params['before_field'])
                ->where('property_place_category_field_id', '!=', $params['add_field_id'])
                ->all();


            $orderList = [];
            foreach ($withoutList as $item) {
                if ($item['order_number'] > 1) {
                    $update = [
                        'order_number' => $item['order_number'] + 1,
                    ];
                    $orderList[$item['id']] = [
                        'order_number' => $item['order_number'] + 1,
                    ];

                    // $this->placeCategoryFieldMappingRepository->update($item['id'], $update) ;
                }
            }

            $insertThis = [];
            foreach ($categoryList as $data) {
                $insertData =
                    [
                        "property_place_category_id" => $data['property_place_category_id'],
                        "property_place_category_field_id" => $params['add_field_id'],
                        "order_number" => $data['order_number'] + 1,
                        "status" => 1,
                        "created_by" => fillOnUndefined($params, "user_id"),
                        "updated_by" => fillOnUndefined($params, "user_id"),
                        "created_at" => time(),
                        "updated_at" => time(),
                    ];
                $insertThis[] = $insertData;
            }

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


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


    }

    public function webMenuPlaceCategoriesAndPlaces($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $placeData = $this->listPlaces($params);
            if ($placeData['status'] != 'success') {
                throw new ApiErrorException($placeData['message']);
            }
            $places = $placeData['data'] ? $placeData['data'] : [];
            $responsePlaces = [];
            $responsePlaceCategories = [];
            foreach ($places as $place) {
                $responsePlaces[] = [
                    "id" => $place['id'],
                    "name" => $place['name'],
                    "language_key" => $place['name'],
                    "route" => 'place/' . $place['id'],
                    "menu_type" => "PLC",
                    "menu_code" => "TOP",
                    "order_number" => $place['order_number'],
                    "icon" => "fas fa-check",
                    "alias" => "place-" . $place['id'],
                    "is_selected" => false,
                    "order_number_mapping" => null,
                    "status" => $place['status'],
                ];

                $placeCategory = $place['category_tree'][1];
                $responsePlaceCategories[$placeCategory['id']] = [
                    "id" => $placeCategory['id'],
                    "name" => $placeCategory['name'],
                    "language_key" => $placeCategory['language_key'],
                    "route" => 'place-category/' . $placeCategory['id'],
                    "menu_type" => "PLCCAT",
                    "menu_code" => "TOP",
                    "order_number" => $placeCategory['order_number'],
                    "icon" => $placeCategory["icon"] ? $placeCategory["icon"] : "fas fa-check",
                    "alias" => "place-category-" . $placeCategory['id'],
                    "is_selected" => false,
                    "order_number_mapping" => null
                ];
            }

            $response = array_merge($responsePlaceCategories, $responsePlaces);
            $response = [
                'status' => true,
                'data' => $response,
            ];

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

            $placeCategoryRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ]
            ];

            $placeCategoryData = $this->propertyPlaceCategoryRepository->findByCriteria($placeCategoryRequest);
            $placeCategories = collect($placeCategoryData);

            $categoryTriesRequest = [
                'parent_id' => $params['place_category_id'],
                'placeCategories' => $placeCategories
            ];
            $categoryArray = $this->categoryTriesSingleArray($categoryTriesRequest);
            $categoryIds = collect($categoryArray)->keyBy('id')->keys()->all();

            $parentCategory = $placeCategories->where('id', $params['place_category_id'])->first();
            $responseData['category'] = [
                'id' => $parentCategory['id'],
                'name' => $parentCategory['name'],
                'language_key' => $parentCategory['language_key'],
            ];

            $placeRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'whereIn' => [
                    ['field' => 'place_category_id', 'value' => $categoryIds]
                ],
                'with' => [
                    'propertyPlaceCategory', 'propertyPlaceWorkingHour',
                    'propertyPlacePhotoMapping.propertyPlacePhoto',
                    'propertyPlaceFactMapping.propertyPlaceFactTitleFactMapping.placeFact',
                    'propertyPlaceFactMapping.propertyPlaceFactTitleFactMapping.placeFactTitle'
                ]
            ];
            $placeData = $this->propertyPlaceRepository->findByCriteria($placeRequest);
            $placeData = $placeData ? $placeData : [];


            $responseData['places'] = collect($placeData)->map(function ($value) {
                $return = $value;

                $return['photos'] = collect($value['property_place_photo_mapping'])->map(function ($photoMap) {
                    return isset($photoMap['property_place_photo']) ? $photoMap['property_place_photo']['photoUrl'] : null;
                })->values()->all();

                $return['default_photo'] = collect($value['property_place_photo_mapping'])->map(function ($photoMap) {
                    return isset($photoMap['property_place_photo']) ? $photoMap['property_place_photo']['photoUrl'] : null;
                })->values()->first();

                unset($return['property_place_photo_mapping']);
                $return['slug'] = Str::slug($return['name'], $separator = '-', $language = 'en');

                $factMappingArray = [];
                foreach ($return['property_place_fact_mapping'] as $factMapping) {

                    $factMappingArray[$factMapping['property_place_fact_title_fact_mapping']['place_fact_title_id']]['category'] = [
                        'id' => $factMapping['property_place_fact_title_fact_mapping']['place_fact_title']['id'],
                        'name' => $factMapping['property_place_fact_title_fact_mapping']['place_fact_title']['name'],
                        'language_key' => $factMapping['property_place_fact_title_fact_mapping']['place_fact_title']['language_key'],
                    ];

                    $factMappingArray[$factMapping['property_place_fact_title_fact_mapping']['place_fact_title_id']]['fact'][$factMapping['property_place_fact_title_fact_mapping']['place_fact_id']] = $factMapping['property_place_fact_title_fact_mapping']['place_fact'];
                }

                unset($return['property_place_fact_mapping']);
                $return['fact_mapping'] = $factMappingArray;

                return $return;
            })->values()->all();

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

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

            $placeRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'id', 'condition' => '=', 'value' => $params['place_id']],
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ],
                'with' => ['propertyPlaceCategory', 'propertyPlaceWorkingHour', 'propertyPlacePhotoMapping.propertyPlacePhoto', 'propertyPlaceFactMapping.propertyPlaceFactTitleFactMapping.placeFact', 'propertyPlaceFactMapping.propertyPlaceFactTitleFactMapping.placeFactTitle'],
                'firstRow' => true
            ];
            $placeData = $this->propertyPlaceRepository->findByCriteria($placeRequest);

            if (!$placeData) {
                throw new Exception('api-unknown_error');
            }
            $return = $placeData;

            $return['facts'] = collect($placeData['property_place_fact_mapping'])->map(function ($factMap) {

                return [

                    'id' => $factMap['id'],
                    'property_place_fact_title_fact_mapping_id' => $factMap['property_place_fact_title_fact_mapping']['id'],
                    'place_fact_id' => $factMap['property_place_fact_title_fact_mapping']['place_fact']['id'],
                    'place_fact_name' => $factMap['property_place_fact_title_fact_mapping']['place_fact']['name'],
                    'place_fact_language_key' => $factMap['property_place_fact_title_fact_mapping']['place_fact']['language_key'],
                    'place_fact_icon' => $factMap['property_place_fact_title_fact_mapping']['place_fact']['icon'],
                    'place_fact_title_id' => $factMap['property_place_fact_title_fact_mapping']['place_fact_title']['id'],
                    'place_fact_title_name' => $factMap['property_place_fact_title_fact_mapping']['place_fact_title']['name'],
                    'place_fact_title_language_key' => $factMap['property_place_fact_title_fact_mapping']['place_fact_title']['language_key'],
                    'place_fact_title_language_icon' => $factMap['property_place_fact_title_fact_mapping']['place_fact_title']['icon'],
                ];
            })->values()->all();


            $return['photos'] = collect($placeData['property_place_photo_mapping'])->map(function ($photoMap) {
                return isset($photoMap['property_place_photo']) ? $photoMap['property_place_photo']['photoUrl'] : null;
            })->values()->all();
            $return['default_photo'] = collect($placeData['property_place_photo_mapping'])->map(function ($photoMap) {
                return isset($photoMap['property_place_photo']) ? $photoMap['property_place_photo']['photoUrl'] : null;
            })->values()->first();
            unset($return['property_place_photo_mapping']);
            unset($return['property_place_fact_mapping']);
            $return['slug'] = Str::slug($return['name'], $separator = '-', $language = 'en');

            $getPlaceCategoryFieldsRequest = [
                'place_category_id' => $return['place_category_id'],
                'place_id' => $return['id'],

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

            $placeFields = collect($getPlaceCategoryFields['data'])->filter(function ($value, $key) {
                if (strpos($key, '_unit') === false) {
                    return $value;
                }
            })->map(function ($value) {
                $return = $value;
                if ($value['field_element'] == 'multiselect') {
                    $options = collect($value['options'])->where('option_is_selected', '=', true);
                    $return['options'] = $options->values()->all();
                    $return['field_value'] = $options->map(function ($opt) {
                        return $opt['option_language_key'];
                    })->values()->all();

                } elseif ($value['field_element'] == 'select') {
                    $options = collect($value['options'])->where('option_is_selected', '', true);
                    $return['options'] = $options->values()->first();
                    $return['field_value'] = $return['options'] ? $return['options']['option_language_key'] : null;

                } elseif ($value['field_element'] == 'slider') {
                    $return['field_value'] = implode('-', $return['field_value']);
                }

                unset($return['options']);

                return $return;
            })->values()->all();

            $return['place_fields'] = $placeFields;


            $placeCategoryRequest['criteria'] = [['field' => 'status', 'condition' => '=', 'value' => 1]];
            $placeCategoryData = $this->propertyPlaceCategoryRepository->findByCriteria($placeCategoryRequest);
            $placeCategories = collect($placeCategoryData);

            $parentCategory = null;
            $currentCategoryId = $placeData['place_category_id'];
            while (is_null($parentCategory)) {
                $currentCategory = $placeCategories->where('id', $currentCategoryId)->first();
                if (is_null($currentCategory['parent_id'])) {
                    $parentCategory = $currentCategory;
                } else {
                    $currentCategoryId = $currentCategory['parent_id'];
                }
            }

            $return['category'] = [
                'id' => $parentCategory['id'],
                'name' => $parentCategory['name'],
                'language_key' => $parentCategory['language_key'],
            ];

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

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

        return output($response);
    }

    public function propertyPlaceCategories($params, $select = ['*'])
    {

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

        try {

            $placeCategoryData = $this->propertyPlaceCategoryRepository->findByCriteria($params, $select);

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

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

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

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


}
