<?php

namespace App\Core\Service;

use App\Core\Service\LanguageService;
use App\Core\Repository\PropertyFact\PropertyFactRepository;
use App\Core\Repository\PropertyFactMapping\PropertyFactMappingRepository;
use App\Core\Validator\PropertyFact\PropertyFactSearchValidator;
use App\Core\Service\PropertyRoomFactMappingService;
use App\Core\Service\PropertyFactMappingService;
use App\Core\Service\ApplicationCacheService;


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

class PropertyFactService
{

    private $languageService;
    private $propertyFactRepository;
    private $propertyFactMappingService;
    private $applicationCacheService;
    private $propertyFactMappingRepository;
    private $propertyFactSearchValidator;
    private $propertyRoomFactMappingService;


    public function __construct(
        ApplicationCacheService $applicationCacheService,
        PropertyFactMappingService $propertyFactMappingService,
        PropertyFactRepository $propertyFactRepository,
        PropertyFactMappingRepository $propertyFactMappingRepository,
        PropertyFactSearchValidator $propertyFactSearchValidator,
        PropertyRoomFactMappingService $propertyRoomFactMappingService,
        LanguageService $languageService
    )
    {
        $this->applicationCacheService = $applicationCacheService;
        $this->propertyFactMappingService = $propertyFactMappingService;
        $this->languageService = $languageService;
        $this->propertyFactRepository = $propertyFactRepository;
        $this->propertyFactMappingRepository = $propertyFactMappingRepository;
        $this->propertyFactSearchValidator = $propertyFactSearchValidator;
        $this->propertyRoomFactMappingService = $propertyRoomFactMappingService;
    }

    public function create($param = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $insertData =
                [
                    "property_id" => fillOnUndefined($param, "property_id"),
                    "Fact_category_id" => fillOnUndefined($param, "Fact_category_id"),
                    "Fact" => fillOnUndefined($param, "Fact"),
                    "locale" => fillOnUndefined($param, "locale"),
                    "status" => fillOnUndefined($param, "status", 0),
                    "created_by" => fillOnUndefined($param, "created_by"),
                    "updated_by" => fillOnUndefined($param, "updated_by"),
                    "created_at" => time(),
                    "updated_at" => time(),
                ];


            $userCreateResult = $this->propertyFactRepository->create($insertData);
            if ($userCreateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $userData = $userCreateResult["data"]->toArray();
            $response = [
                'status' => true,
                'data' => $userData,
            ];

        } 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 select($param = [], $column = ['*'])
    {

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

        try {

            $data = $this->propertyFactRepository->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 getPropertyFact($params = [])
    {

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

        try {
            $requestData = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'with' => []
            ];
            $fectData = $this->select($requestData);


            if ($fectData['status'] != 'success') {
                throw new ApiErrorException(lang('Fact data not loaded'));
            }

            $factCollection = collect($fectData['data']);

            $propertyFactMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ]
            ];

            $propertyFactMappingData = $this->propertyFactMappingService->select($propertyFactMappingRequest);
            if ($propertyFactMappingData['status'] != 'success') {
                throw new ApiErrorException(lang('Fact data not loaded'));
            }

            $propertyFactMappingData = $propertyFactMappingData['data'] ? $propertyFactMappingData['data'] : [];
            $propertyFactMapping = [];
            foreach ($propertyFactMappingData as $propertyFactItem) {
                $propertyFactMapping[$propertyFactItem['fact_id']] = $propertyFactItem;
            }

            $return = [];

            $mainFacts = $factCollection->where('parent_id', '=', null)
                ->toArray();
            $responseFacts = [];

            foreach ($mainFacts as $fact) {


                $mainFactItem['id'] = $fact['id'];
                $mainFactItem['name'] = $fact['name'];
                $mainFactItem['language_key'] = $fact['language_key'];
                $mainFactItem['title_language_key'] = $fact['title_language_key'];
                $mainFactItem['icon'] = $fact['icon'];
                if ($fact['type'] == 1) {
                    $mainFactItem['icon'] = 'far fa-tv-retro';
                }
                $subCats = $factCollection->where('parent_id', '=', $fact['id'])
                    ->toArray();

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


                $responseSubCats = [];
                foreach ($subCats as $subCat) {

                    $subCatItem['id'] = $subCat['id'];
                    $subCatItem['name'] = $subCat['name'];
                    $subCatItem['language_key'] = $subCat['language_key'];
                    $subCatItem['title_language_key'] = $subCat['title_language_key'];
                    $subCatItem['icon'] = $subCat['icon'];
                    $subCatItem['priority'] = $subCat['order_number'];
                    $subCatItem['parent_id'] = $fact['id'];

                    if ($subCat['type'] == 1) {
                        $subCatItem['icon'] = 'far fa-tv-retro';
                    }

                    $subFacts = $factCollection->where('parent_id', '=', $subCat['id'])
                        ->toArray();

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

                    $responseSubFacts = [];

                    foreach ($subFacts as $subFact) {

                        $subFactItem['id'] = $subFact['id'];
                        $subFactItem['name'] = $subFact['name'];
                        $subFactItem['language_key'] = $subFact['language_key'];
                        $subFactItem['title_language_key'] = $subFact['title_language_key'];
                        $subFactItem['type'] = $subFact['type'];
                        $subFactItem['icon'] = $subFact['icon'];
                        $subFactItem['parent_id'] = $subCat['id'];

                        $checkMappingData = isset($propertyFactMapping[$subFact['id']]) ? $propertyFactMapping[$subFact['id']] : [];
                        $subFactItem['is_selected'] = $checkMappingData ? true : false;
                        $subFactItem['mapping_id'] = fillOnUndefined($checkMappingData, 'id');

                        // Todo Will be typed when 'attributes' is added
                        // $subFactItem['attributes'] = null;


                        $subFactItem['description'] = null;
                        if ($checkMappingData && fillOnUndefined($checkMappingData, 'description')) {
                            $descriptionLangContents = json_decode($checkMappingData['description'], 1);

                            if(isset($params['locale'])) {
                                $params['currentLanguage'] = $params['locale'];
                            }

                            if (isset($params['currentLanguage']) && isset($descriptionLangContents[$params['currentLanguage']])) {
                                $subFactItem['description'] = $descriptionLangContents[$params['currentLanguage']];
                            }
                        }

                        $responseSubFacts[] = $subFactItem;
                    }
                    $subCatItem['fact'] = $responseSubFacts;
                    $responseSubCats[$subCat['id']] = $subCatItem;
                }

                $mainFactItem['fact_subcategory'] = $responseSubCats;
                $return[$fact['id']] = $mainFactItem;

            }

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

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

        try {

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

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


            $propertyFactRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ]
            ];
            $propertyFactData = $this->propertyFactMappingRepository->findByCriteria($propertyFactRequest, ['id', 'property_id', 'fact_id']);
            $propertyFacts = collect($propertyFactData)->keyBy('fact_id')->keys()->toArray();

            if (!$propertyFacts) {
                throw new ApiErrorException(lang('Check fact data from your content'));
            }


            $searchFactRequest = [
                'whereIn' => [
                    ['field' => 'id', 'value' => $propertyFacts]
                ]
            ];

            if ($params['search_term']) {
                $searchFactRequest['criteria'][] = ['field' => 'name', 'condition' => 'like', 'value' => '%' . $params['search_term'] . '%'];
            }

            $searchFactData = $this->propertyFactRepository->findByCriteria($searchFactRequest, ['id', 'name', 'language_key']);

            if (!$searchFactData) {
                throw new ApiErrorException(lang('Fact data not loaded'));
            }

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

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

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

        try {
            $requestData = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'parent_id', 'condition' => '=', 'value' => 293],

                ],
                'with' => []
            ];
            $factData = $this->select($requestData);


            if ($factData['status'] != 'success') {
                throw new ApiErrorException(lang('Fact data not loaded'));
            }

            $subFacts = $factData['data'] ? $factData['data'] : [];

            $showRecommended = false;
            $propertyRoomFactMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ]
            ];

            $propertyRoomFactMappingData = $this->propertyRoomFactMappingService->select($propertyRoomFactMappingRequest);
            if ($propertyRoomFactMappingData['status'] != 'success') {
                throw new ApiErrorException(lang('Fact data not loaded'));
            }

            $propertyRoomFactMappingCollection = collect($propertyRoomFactMappingData['data']);
            $propertyRoomFactMappingData = $propertyRoomFactMappingData['data'] ? $propertyRoomFactMappingData['data'] : [];
            $propertyFactMapping = [];
            foreach ($propertyRoomFactMappingData as $mappingItem) {
                $propertyFactMapping[$mappingItem['fact_id']] = $mappingItem;
                $propertyRoomFactMapping[$mappingItem['room_id'] . '|' . $mappingItem['fact_id']] = $mappingItem;
            }
            if ($propertyRoomFactMappingData) {
                $showRecommended = true;
            }


            $responseSubFacts = [];


            if ($showRecommended) {
                $showRecommendedData = $propertyRoomFactMappingCollection
                    ->where('room_id', '=', $params['room_id'])
                    ->first();
                if ($showRecommendedData) {
                    $showRecommended = false;
                }
            }


            foreach ($subFacts as $subFact) {

                $subFactItem['id'] = $subFact['id'];
                $subFactItem['name'] = $subFact['name'];
                $subFactItem['language_key'] = $subFact['language_key'];
                $subFactItem['title_language_key'] = $subFact['title_language_key'];
                $subFactItem['type'] = $subFact['type'];
                if ($subFact['type'] == 1) {
                    $subFactItem['icon'] = $subFact['icon'];
                }

                $checkMappingData = isset($propertyRoomFactMapping[$params['room_id'] . '|' . $subFact['id']]) ? $propertyRoomFactMapping[$params['room_id'] . '|' . $subFact['id']] : [];

                $checkRecommended = isset($propertyFactMapping[$subFact['id']]) ? $propertyFactMapping[$subFact['id']] : [];

                $subFactItem['is_selected'] = $checkMappingData ? true : false;
                $subFactItem['is_recommended'] = $checkRecommended ? true : false;
                $subFactItem['mapping_id'] = fillOnUndefined($checkMappingData, 'id');
                $subFactItem['is_feature'] = fillOnUndefined($checkMappingData, 'is_feature', 0);

                $responseSubFacts[] = $subFactItem;
            }

            if (collect($responseSubFacts)->where('is_recommended', 'true')->count() == 0) {
                $showRecommended = false;
            }

            $response = [
                'status' => true,
                'data' => [
                    'get_room_facts' => $responseSubFacts,
                    'show_recommended' => $showRecommended,
                ],
            ];

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

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

        try {
            $requestData = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'type', 'condition' => '=', 'value' => 1],
                    ['field' => 'parent_id', 'condition' => '=', 'value' => $params['sub_category_id']],
                ],
                'orderBy' => [
                    ["field" => "order_number", "value" => "ASC"],
                    ["field" => "name", "value" => "ASC"],
                ]

            ];
            $factData = $this->select($requestData);

            if ($factData['status'] != 'success') {
                throw new ApiErrorException(lang('Fact data not loaded'));
            }

            $factCollection = collect($factData['data']);

            $propertyFactMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ]
            ];

            $propertyFactMappingData = $this->propertyFactMappingService->select($propertyFactMappingRequest);
            if ($propertyFactMappingData['status'] != 'success') {
                throw new ApiErrorException(lang('Fact data not loaded'));
            }

            $propertyFactMappingData = $propertyFactMappingData['data'] ? $propertyFactMappingData['data'] : [];
            $propertyFactMapping = [];
            foreach ($propertyFactMappingData as $propertyFactItem) {
                $propertyFactMapping[$propertyFactItem['fact_id']] = $propertyFactItem;
            }

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

            $subFacts = $factCollection->toArray();
            $responseSubFacts = [];

            foreach ($subFacts as $subFact) {

                $subFactItem['id'] = $subFact['id'];
                $subFactItem['name'] = $subFact['name'];
                $subFactItem['language_key'] = $subFact['language_key'];
                $subFactItem['title_language_key'] = $subFact['title_language_key'];
                $subFactItem['type'] = $subFact['type'];
                $subFactItem['icon'] = $subFact['icon'];

                $checkMappingData = isset($propertyFactMapping[$subFact['id']]) ? $propertyFactMapping[$subFact['id']] : [];
                $subFactItem['is_selected'] = $checkMappingData ? true : false;
                $subFactItem['mapping_id'] = fillOnUndefined($checkMappingData, 'id');

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


                $responseSubFacts[] = $subFactItem;
            }

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

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

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

        try {
            $requestData = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'type', 'condition' => '=', 'value' => 0],
                    ['field' => 'id', 'condition' => '!=', 'value' => 9], // Accommodation
                ]
            ];
            $factData = $this->select($requestData);

            if ($factData['status'] != 'success') {
                throw new ApiErrorException(lang('Fact data not loaded'));
            }
            $factCollection = collect($factData['data']);
            $mainFacts = $factCollection->where('parent_id', '=', null)->sortBy('order_number')->toArray();
            $responseSubFacts = [];
            $isFoundItem = false;
            $nextItem = '/app/content/rooms';
            $prevItem = '/app/content/photos';
            $isDisable = true;
            $foundIndex = -1;
            $logData = [];

            foreach ($mainFacts as $mainFact) {
                $subFacts = $factCollection->where('parent_id', '=', $mainFact['id'])->sortBy('order_number')->toArray();
                foreach ($subFacts as $subFact) {

                    $logData[] = $subFact;

                    if ($params['parent_id'] == $subFact['parent_id']) {
                        $subFactItem['id'] = $subFact['id'];
                        $subFactItem['name'] = $subFact['name'];
                        $subFactItem['language_key'] = $subFact['language_key'];
                        $subFactItem['title_language_key'] = $subFact['title_language_key'];
                        $subFactItem['type'] = $subFact['type'];
                        $subFactItem['icon'] = $subFact['icon'];
                        $subFactItem['alias'] = 'Property.Fact.SubCategoryFacts.' . $subFact['id'];
                        $subFactItem['url'] = '/app/content/facts/' . $subFact['id'];
                        $subFactItem['is_disable'] = $isDisable;

                        $responseSubFacts[] = $subFactItem;
                    }
                    if ($params['sub_category_id'] == $subFact['id']) {
                        $isDisable = false;
                    }

                    if ($isFoundItem) {
                        $subFactItem['icon'] = $subFact['icon'];
                        $foundIndex++;
                    }

                    if ($params['sub_category_id'] == $subFact['id']) {
                        $isFoundItem = true;
                        $foundIndex = 0;
                    }

                    if ($isFoundItem && $foundIndex == 1) {
                        $nextItem = '/app/content/facts/' . $subFact['id'];
                    }

                    if (!$isFoundItem) {
                        $prevItem = '/app/content/facts/' . $subFact['id'];
                    }


                }

            }

            $response = [
                'status' => true,
                'data' => [
                    'menu' => $responseSubFacts,
                    'prev' => $prevItem,
                    'next' => $nextItem,

                ],
            ];

        } 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 getPropertyOfferFilter($params = [], $offerAllFactIds = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $categories = $params;
            $responseArray = [];
            $accommodationTypes = [];
            foreach ($categories as $category) {
                $categoryArray = [];
                $categoryItem = $category;
                foreach ($category['fact_subcategory'] as $subCategory) {
                    $subCategoryItem = $subCategory;
                    if ($subCategory['id'] == 9) {
                        $facts = collect($subCategory['fact'])->map(function ($value) use ($offerAllFactIds) {
                            $value['is_selected'] = array_search($value['id'], $offerAllFactIds) > -1;
                            return $value;
                        })->values()->all();
                        $subCategoryItem['fact'] = $facts ? $facts : [];
                        $accommodationTypes = $subCategoryItem['fact'];
                    } else {
                        $facts = collect($subCategory['fact'])->where('is_selected', '=', true)->map(function ($value) use ($offerAllFactIds) {
                            $value['is_selected'] = array_search($value['id'], $offerAllFactIds) > -1;
                            return $value;
                        })->values()->all();
                        $subCategoryItem['fact'] = $facts ? $facts : [];

                        $categoryArray[$subCategory['id']] = $subCategoryItem;
                    }
                }
                $categoryItem['fact_subcategory'] = $categoryArray;
                $responseArray[$category['id']] = $categoryItem;
            }
            $response = [
                'status' => true,
                'data' => [
                    'get_facts' => $responseArray,
                    'accommodation_types' => $accommodationTypes,
                ],
            ];

        } 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 getPropertyOfferFilterForHtml($params = [], $offerAllFactIds = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $categories = $params;
            $responseArray = [];
            foreach ($categories as $category) {
                $categoryArray = [];
                $categoryItem = $category;
                foreach ($category['fact_subcategory'] as $subCategory) {
                    $subCategoryItem = $subCategory;
                    $facts = collect($subCategory['fact'])
                        ->where('is_selected', '=', true)
                        ->whereIn('id', $offerAllFactIds)
                        ->map(function ($value) use ($offerAllFactIds) {
                            return $value;
                        })->values()->all();
                    $subCategoryItem['fact'] = $facts ? $facts : [];

                    if ($facts) {
                        $categoryArray[$subCategory['id']] = $subCategoryItem;
                    }
                }
                $categoryItem['fact_subcategory'] = $categoryArray;
                $responseArray[$category['id']] = $categoryItem;
            }

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

        } 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 checkPropertyFactMapping($param = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $request = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $param['property_id']],
                ],
                'whereIn' => [
                    ['field' => 'fact_id', 'value' => $param['fact_ids']],
                ],
                'count' => 1
            ];
            $data = $this->propertyFactMappingRepository->findByCriteria($request);
            if ($data < count($param['fact_ids'])) {
                throw new ApiErrorException('Property - Fact Mapping not validate.');
            }
            $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);
    }

}
