<?php


namespace App\Http\Controllers\V1;

use App\Core\Service\LanguageService;
use App\Core\Service\PropertyAddonService;
use App\Core\Service\PropertyChannelMappingService;
use App\Core\Validator\PropertyAddon\PropertyAddonValidator;
use App\Exceptions\ApiErrorException;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Log;
use Exception;

class PropertyAddonController extends Controller
{

    private $params;
    private $propertyAddonService;
    private $propertyChannelMappingService;
    private $propertyAddonValidator;
    private $languageService;


    public function __construct(
        PropertyAddonService $propertyAddonService,
        PropertyChannelMappingService $propertyChannelMappingService,
        PropertyAddonValidator $propertyAddonValidator,
        LanguageService $languageService
    )
    {
        $this->params = Input::all();
        $this->params = $this->params['params'];
        $this->propertyAddonService = $propertyAddonService;
        $this->propertyChannelMappingService = $propertyChannelMappingService;
        $this->propertyAddonValidator = $propertyAddonValidator;
        $this->languageService = $languageService;
    }

    protected function propertyChannelMappingCheck($propertyId, $channelId)
    {


        $propertyChannelMappingCriteria = [
            'criteria' => [
                ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
                ['field' => 'channel_id', 'condition' => '=', 'value' => $channelId],
                ['field' => 'status', 'condition' => '=', 'value' => 1],
            ],
            'firstRow' => true
        ];

        $propertyChannelMapping = $this->propertyChannelMappingService->select($propertyChannelMappingCriteria);

        if ($propertyChannelMapping['status'] == 'success') {
            if (empty($propertyChannelMapping['data'])) {
                return false;
            } else {
                return true;
            }
        } else {
            return false;
        }

    }

    public function getPropertyAddon(Request $request)
    {

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

        try {

            //TODO: Validator

            $propertyChannelMappingCheck = $this->propertyChannelMappingCheck($this->params['property_id'], $this->params['channel_id']);
            if (!$propertyChannelMappingCheck) {
                throw new ApiErrorException('Transactions cannot be made through a unconnected channel.');
            }

            $requestSelectCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $this->params['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $this->params['channel_id']],
                    ['field' => 'status', 'condition' => '!=', 'value' => 3],
                ],
                //'with' => ['propertyAddon']
            ];
            $columns = ['id', 'property_id', 'channel_id', 'property_addon_id', 'title', 'description', 'amount', 'type', 'min_stay','status'];
            $requestSelectResult = $this->propertyAddonService->selectPropertyChannelAddon($requestSelectCriteria, $columns);

            $propertyChannelAddon = [];
            if ($requestSelectResult['status'] == 'success') {
                $propertyChannelAddon = $requestSelectResult['data'];
            }

            $propertyChannelAddonCollect = collect($propertyChannelAddon);


            $requestSelectCriteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'with' => ['fact'],
                'orderBy' => [
                    ['field' => 'order_number', 'value' => 'ASC']
                ],
            ];

            $columns = ['id', 'fact_id', 'title', 'attribute', 'order_number'];
            $propertyAddonResult = $this->propertyAddonService->selectPropertyAddon($requestSelectCriteria, $columns);

            $propertyAddon = [];
            if ($requestSelectResult['status'] == 'success') {
                $propertyAddon = $propertyAddonResult['data'];
            }

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

            $propertyAddonList = [];
            foreach ($propertyAddon as $addon) {

                $channelAddon = [];
                $channelAddons = $propertyChannelAddonCollect->where('property_addon_id', $addon['id'])->toArray();

                $isSelected = false;
                if ($channelAddons) {
                    $channelAddons = array_values($channelAddons);

                    foreach ($channelAddons as $channelAddonItem) {

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

                        $channelAddonItem['description'] = $responseLangDescription;
                        $channelAddon[] = $channelAddonItem;

                    }

                    $isSelected = true;

                } else {

                    $responseLangDescription = [];
                    foreach ($applicationLanguages as $applicationLanguage) {
                        $langKey = $applicationLanguage['code'];
                        $responseLangDescription[] = [
                            'language_code' => $langKey,
                            'description' => null
                        ];
                    }

                    $channelAddon[] = [
                        'property_id' => $this->params['property_id'],
                        'channel_id' => $this->params['channel_id'],
                        'property_addon_id' => $addon['id'],
                        'title' => '',
                        'description' => $responseLangDescription,
                        'amount' => '',
                        'type' => '',
                        'min_stay' => null,
                        'status' => 1
                    ];
                }

                $propertyAddonList[] = [
                    'id' => $addon['id'],
                    'fact_id' => $addon['fact_id'],
                    'name' => $addon['fact']['name'],
                    'language_key' => $addon['fact']['language_key'],
                    'icon' => $addon['fact']['icon'],
                    'attributeArray' => $addon['attributeArray'],
                    'is_selected' => $isSelected,
                    'channelAddon' => $channelAddon
                ];

            }

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

        } 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 apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);

    }

    public function syncPropertyAddon(Request $request)
    {

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

        try {

            /*$validationResult = $this->propertyAddonValidator->validate($this->params);

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

            $propertyChannelMappingCheck = $this->propertyChannelMappingCheck($this->params['property_id'], $this->params['channel_id']);
            if (!$propertyChannelMappingCheck) {
                throw new ApiErrorException('Transactions cannot be made through a unconnected channel.');
            }


            $requestSelectCriteria = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $this->params['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $this->params['channel_id']],
                    ['field' => 'property_addon_id', 'condition' => '=', 'value' => $this->params['property_addon_id']],
                ]
            ];
            $columns = ['id', 'property_id', 'channel_id', 'property_addon_id', 'amount', 'type'];
            $requestSelectResult = $this->propertyAddonService->selectPropertyChannelAddon($requestSelectCriteria, $columns);

            $propertyChannelAddon = [];
            if ($requestSelectResult['status'] == 'success') {
                $propertyChannelAddon = $requestSelectResult['data'];
            }

            $currentPropertyChannelAddon = $propertyChannelAddon;
            $propertyChannelAddon = collect($propertyChannelAddon);

            DB::beginTransaction();

            //Status Delete All ChannelAddon
            foreach ($currentPropertyChannelAddon as $channelAddon) {
                $updateParam = [
                    'property_id' => $channelAddon['property_id'],
                    'channel_id' => $channelAddon['channel_id'],
                    'property_addon_id' => $channelAddon['property_addon_id'],
                    'status' => 3,
                    'updated_by' => $request->auth->id,
                ];
                $this->propertyAddonService->updatePropertyChannelAddon($channelAddon['id'], $updateParam);
            }
            //Status Delete All ChannelAddon


            $channelAddonProcessed = [];
            foreach ($this->params['channelAddon'] as $channelAddon) {


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

                if (!isset($channelAddon['id'])) {

                    $createParam = [
                        'property_id' => $this->params['property_id'],
                        'channel_id' => $this->params['channel_id'],
                        'property_addon_id' => $this->params['property_addon_id'],
                        'title' => fillOnUndefined($channelAddon, 'title'),
                        'description' => json_encode($description),
                        'amount' => $channelAddon['amount'],
                        'type' => $channelAddon['type'],
                        'min_stay' => fillOnUndefined($channelAddon,'min_stay'),
                        'status' => fillOnUndefined($channelAddon, 'status', 1) == 1 ? 1 : 0,
                        'created_by' => $request->auth->id,
                        'updated_by' => $request->auth->id,
                    ];

                    $syncPropertyAddon = $this->propertyAddonService->createPropertyChannelAddon($createParam);

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

                    $channelAddonProcessed[] = $syncPropertyAddon['data'];

                } elseif (isset($channelAddon['id']) && $propertyChannelAddon->where('id', $channelAddon['id'])->isNotEmpty()) {

                    $updateParam = [
                        'property_id' => $this->params['property_id'],
                        'channel_id' => $this->params['channel_id'],
                        'property_addon_id' => $this->params['property_addon_id'],
                        'title' => fillOnUndefined($channelAddon, 'title'),
                        'description' => json_encode($description),
                        'amount' => $channelAddon['amount'],
                        'type' => $channelAddon['type'],
                        'min_stay' => fillOnUndefined($channelAddon,'min_stay'),
                        'status' => fillOnUndefined($channelAddon, 'status', 1) == 1 ? 1 : 0,
                        'updated_by' => $request->auth->id,
                    ];

                    $syncPropertyAddon = $this->propertyAddonService->updatePropertyChannelAddon($channelAddon['id'], $updateParam);

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

                    $channelAddonProcessed[] = $syncPropertyAddon['data'];
                }


            }

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

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

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

        return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);

    }


}

