<?php


namespace App\Core\Service\PropertyAdditionalInfo;

use App\Core\Repository\GeneralTimezone\GeneralTimezoneRepository;
use App\Core\Repository\PropertyAdditionalInfo\PropertyAdditionalInfoRepository;
use App\Core\Repository\PropertyAdditionalInfo\PropertyAdditionalInfoKeyRepository;
use App\Exceptions\ApiErrorException;
use Exception;
use Illuminate\Support\Facades\Log;


class PropertyAdditionalInfoService
{

    private $propertyAdditionalInfoRepository;
    private $propertyAdditionalInfoKeyRepository;

    public function __construct
    (
        PropertyAdditionalInfoRepository    $additionalInfoRepository,
        PropertyAdditionalInfoKeyRepository $additionalInfoKeyRepository,
        GeneralTimezoneRepository           $generalTimezoneRepository
    )
    {
        $this->propertyAdditionalInfoRepository = $additionalInfoRepository;
        $this->propertyAdditionalInfoKeyRepository = $additionalInfoKeyRepository;
        $this->generalTimezoneRepository = $generalTimezoneRepository;
    }


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

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

        try {

            $data = $this->propertyAdditionalInfoRepository->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 create($param = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $insertData =
                [
                    "property_id" => fillOnUndefined($param, "property_id"),
                    "additional_info_key_id" => fillOnUndefined($param, "additional_info_key_id"),
                    "value" => fillOnUndefined($param, "value"),
                    "status" => fillOnUndefined($param, "status", 1),
                    "created_by" => fillOnUndefined($param, "created_by"),
                    "updated_by" => fillOnUndefined($param, "updated_by"),

                ];


            /*
            $validationResult = $this->propertyExecutiveCreateValidator->validate($insertData);

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

            */


            $userCreateResult = $this->propertyAdditionalInfoRepository->create($insertData);
            if ($userCreateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $userData = $userCreateResult["data"];
            $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 update($id, $param = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {


            $updateResult = $this->propertyAdditionalInfoRepository->update($id, $param);

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


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

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

    /**
     * @param array $params property_id and locale code
     *
     */
    public function getPropertyAdditionalInfo($params)
    {
        try {
            $locale = $params['locale'];
            $propertyId = $params['property_id'];

            $getPropertyAdditionalInfoKeyCriteria =
                [
                    'criteria' =>
                        [
                            ['field' => 'status', 'condition' => '=', 'value' => 1],
                        ],
                ];
            $getPropertyAdditionalInfoKey = $this->propertyAdditionalInfoKeyRepository->findByCriteria($getPropertyAdditionalInfoKeyCriteria, ['id', 'additional_info_key']);
            $getPropertyAdditionalInfoCriteria =
                [
                    'criteria' =>
                        [
                            ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                            ['field' => 'status', 'condition' => '=', 'value' => 1],
                        ],
                ];
            $getPropertyAdditionalInfo = $this->propertyAdditionalInfoRepository->findByCriteria($getPropertyAdditionalInfoCriteria);
            $getPropertyAdditionalInfoHasInfoKey = collect($getPropertyAdditionalInfo)->keyBy('additional_info_key_id')->toArray();

            $filteredPropertyAdditionalInfo = [];
            foreach ($getPropertyAdditionalInfoKey as $key => $propertyAdditionalInfoKeys) {
                $value = null;
                $additionalId = null;

                $additionalId = $propertyAdditionalInfoKeys['id'];
                if (array_key_exists($additionalId, $getPropertyAdditionalInfoHasInfoKey)) {
                    $value = $getPropertyAdditionalInfoHasInfoKey[$additionalId]['value'];
                }

                $filteredPropertyAdditionalInfo[$additionalId] =
                    [
                        'id' => $additionalId,
                        'name' => $propertyAdditionalInfoKeys['additional_info_key'],
                        'value' => $value,
                    ];
            }


        } 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 $filteredPropertyAdditionalInfo;
        return output($response);
    }

    /**
     * @param array $params
     * @param string $locale 'en','tr', etc..
     * @return array
     */

    public function insertPropertyAdditionalInfo($params)
    {
        $response = ['status' => false, 'statusCode' => 500, 'message' => '', 'data' => null];

        try {
            $responseData = $params['data'];
            $insertPropertyAdditionalInfoData = [];

            foreach ($responseData as $perData) {
                $insertPropertyAdditionalInfoData[] =
                    [
                        'property_id' => $params['property_id'],
                        'additional_info_key_id' => $perData['additional_info_key_id'],
                        'value' => $perData['value'],
                        'created_by' => $params['user_id'],
                        'updated_by' => $params['user_id'],
                    ];
            }

            $response = $this->propertyAdditionalInfoRepository->createAll($insertPropertyAdditionalInfoData);

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

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


        } catch (ApiErrorException $e) {
            $response = ['status' => 0, 'statusCode' => 500, 'message' => $e->getMessage(), 'data' => null];
        } catch (Exception $e) {

            $message = $e->getFile() . ' ' . $e->getLine() . ' ' . $e->getMessage();
            Log::error($message);
        }

        return output($response);

    }

    public function updatePropertyAdditionalInfo($params)
    {
        $response = ['status' => false, 'statusCode' => 500, 'message' => '', 'data' => null];

        try {
            $responseData = $params['data'];
            $updatePropertyAdditionalInfoData = [];
            $responseDataCount = count($responseData);
            $countOfUpdatedData = 0;
            //TODO : update'i gerçekleştirilmeyen datanında bildirilmesi gerekiyor.
            foreach ($responseData as $perData) {
                $id = $perData['id'];

                $updatePropertyAdditionalInfoData =
                    [
                        'property_id' => $params['property_id'],
                        'additional_info_key_id' => $perData['additional_info_key_id'],
                        'value' => $perData['value'],
                        'updated_by' => $params['user_id'],
                    ];

                $update = $this->propertyAdditionalInfoRepository->update($id, $updatePropertyAdditionalInfoData);
                if ($update['status'] != 'success') {
                    throw new Exception('api-unknown_error');
                }

                if ($update['status'] === "success" && !empty($update['data'])) {
                    $countOfUpdatedData++;
                }
            }


            if ($countOfUpdatedData != $responseDataCount) {
                throw new ApiErrorException(lang('Your update did not take place!'));
            }

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


        } catch (ApiErrorException $e) {
            $response = ['status' => 0, 'statusCode' => 500, 'message' => $e->getMessage(), 'data' => null];
        } catch (Exception $e) {

            $message = $e->getFile() . ' ' . $e->getLine() . ' ' . $e->getMessage();
            Log::error($message);
        }

        return output($response);
    }

    public function updateOrCreatePropertyAdditionalInfo($params)
    {
        $response = ['status' => false, 'statusCode' => 500, 'message' => '', 'data' => null];

        try {


            // Get All Keys
            $getPropertyAdditionalKeyCriteria = [
                'criteria' =>
                    [
                        ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ]
            ];
            $getPropertyAdditionalKeyResponse = $this->propertyAdditionalInfoKeyRepository->findByCriteria($getPropertyAdditionalKeyCriteria, ['id', 'additional_info_key']);
            $getPropertyAdditionalKeyResponse = $getPropertyAdditionalKeyResponse ? $getPropertyAdditionalKeyResponse : [];
            $keyArray = collect($getPropertyAdditionalKeyResponse)->keyBy('additional_info_key')->all();

            // get all property additional info
            $propertyAdditionalInfoRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                ]
            ];

            $propertyAdditionalInfoResponse = $this->select($propertyAdditionalInfoRequest);
            if ($propertyAdditionalInfoResponse['status'] != 'success') {
                throw new ApiErrorException(lang('Additional Data Not Loaded'));
            }
            $propertyAdditionalInfoCollection = collect($propertyAdditionalInfoResponse['data']);
            foreach ($params['additional_info'] as $key => $value) {

                if (!isset($keyArray[$key])) {
                    continue;
                }

                if (!isset($keyArray[$key])) {
                    throw new ApiErrorException($key . ' not found');
                }

                $value = $value != null ? $value : "";


                $additionalInfoCheck = $propertyAdditionalInfoCollection
                    ->where('additional_info_key_id', '=', $keyArray[$key]['id'])
                    ->first();
                /*
                                $kvkkKeys = ['kvkk_mersis_no', 'kvkk_data_controller', 'kvkk_contact_person'];
                                if(in_array($key, $kvkkKeys)){
                                    if($value === "" || $value === NULL){
                                        continue;
                                    }
                                }
                */
                if ($additionalInfoCheck) {
                    $updateData = [
                        'value' => $value,
                        'updated_by' => $params['user_id'],
                        'status' => 1,
                    ];
                    $updateStatus = $this->update($additionalInfoCheck['id'], $updateData);

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

                } else {
                    $createData = [
                        'property_id' => $params['property_id'],
                        'additional_info_key_id' => $keyArray[$key]['id'],
                        'value' => $value,
                        'updated_by' => $params['user_id'],
                        'created_by' => $params['user_id'],
                    ];
                    $createStatus = $this->create($createData);
                    if ($createStatus['status'] != 'success') {
                        throw new Exception($createStatus['message']);
                    }
                }

            }

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


        } catch (ApiErrorException $e) {
            $response = ['status' => 0, 'statusCode' => 500, 'message' => $e->getMessage(), 'data' => null];
        } catch (Exception $e) {

            $message = $e->getFile() . ' ' . $e->getLine() . ' ' . $e->getMessage();
            Log::error($message);
        }

        return output($response);
    }

    public function getPropertyAdditionalInfo2KeyBy($params)
    {
        $response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];
        try {


            $getPropertyAdditionalKeyCriteria = [
                'criteria' =>
                    [
                        ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ]
            ];
            $getPropertyAdditionalKeyResponse = $this->propertyAdditionalInfoKeyRepository->findByCriteria($getPropertyAdditionalKeyCriteria, ['id', 'additional_info_key']);
            $getPropertyAdditionalKeyResponse = $getPropertyAdditionalKeyResponse ? $getPropertyAdditionalKeyResponse : [];

            $getPropertyAdditionalInfoCriteria = [
                'criteria' =>
                    [
                        ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                        ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ]
            ];
            $getPropertyAdditionalInfoResponse = $this->propertyAdditionalInfoRepository->findByCriteria($getPropertyAdditionalInfoCriteria, ['id', 'additional_info_key_id', 'value']);
            $getPropertyAdditionalInfoResponse = $getPropertyAdditionalInfoResponse ? $getPropertyAdditionalInfoResponse : [];
            $getPropertyAdditionalInfoResponse = collect($getPropertyAdditionalInfoResponse)->keyBy('additional_info_key_id')->all();

            $newMap = [];
            foreach ($getPropertyAdditionalKeyResponse as $keyItem) {
                $newMap[$keyItem['additional_info_key']] = isset($getPropertyAdditionalInfoResponse[$keyItem['id']]) ? $getPropertyAdditionalInfoResponse[$keyItem['id']]['value'] : null;

                //property_timezone
                if ($keyItem['additional_info_key'] == 'property_timezone') {
                    $generalTimezoneRepositoryCriteria = [
                        'criteria' => [
                            ['field' => 'id', 'condition' => '=', 'value' => $getPropertyAdditionalInfoResponse[$keyItem['id']]['value']],
                        ],
                        'firstRow' => true
                    ];
                    $propertyTimeZoneDetail = $this->generalTimezoneRepository->findByCriteria($generalTimezoneRepositoryCriteria, ['location', 'action_type', 'hour', 'minute']);
                    $newMap['property_timezone_detail'] = $propertyTimeZoneDetail ?? null;
                }
            }

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

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

        return output($response);
    }

    public function deletePropertyAdditionalInfos($params)
    {

        $keyIdCriteria = [
            'whereIn' =>
                [
                    ['field' => 'additional_info_key', 'value' => $params['key_array']],
                ],
        ];
        $keyData = $this->propertyAdditionalInfoKeyRepository->findByCriteria($keyIdCriteria);
        $keyIds = collect($keyData)->keyBy('id')->keys();

        $propertyExecutiveDeleteRequest = [
            'criteria' => [
                ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
            ],
            'whereIn' => [
                ['field' => 'additional_info_key_id', 'value' => $keyIds],
            ]
        ];

        $this->propertyAdditionalInfoRepository->delete($propertyExecutiveDeleteRequest);

    }

}
