<?php

namespace App\Core\Service;

use App\Core\Repository\PropertyChannel\PropertyChannelRepository;
use App\Core\Validator\PropertyChannel\PropertyChannelAddValidator;
use App\Core\Validator\PropertyChannel\PropertyChannelUpdateValidator;
use App\Core\Validator\PropertyChannel\PropertyChannelDeleteValidator;
use App\Core\Repository\PropertyChannelMapping\PropertyChannelMappingRepository ;

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

class PropertyChannelService
{

    private $propertyChannelRepository;
    private $propertyChannelAddValidator;
    private $propertyChannelUpdateValidator;
    private $propertyChannelDeleteValidator;
    private $propertyChannelMappingRepository;


    public function __construct(

        PropertyChannelRepository $propertyChannelRepository,
        PropertyChannelUpdateValidator $propertyChannelUpdateValidator,
        PropertyChannelDeleteValidator $propertyChannelDeleteValidator,
        PropertyChannelAddValidator $propertyChannelAddValidator,
        PropertyChannelMappingRepository $propertyChannelMappingRepository

    )
    {

        $this->propertyChannelRepository = $propertyChannelRepository;
        $this->propertyChannelAddValidator = $propertyChannelAddValidator;
        $this->propertyChannelUpdateValidator = $propertyChannelUpdateValidator;
        $this->propertyChannelDeleteValidator = $propertyChannelDeleteValidator;
        $this->propertyChannelMappingRepository = $propertyChannelMappingRepository;

    }

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

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

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

            $insertData =
                [
                    'parent_id' => fillOnUndefined($params, 'parent_id'),
                    'name' => fillOnUndefined($params, 'name'),
                    'official_name' => fillOnUndefined($params, 'official_name'),
                    'description' => fillOnUndefined($params, 'description'),
                    'channel_category_id' => fillOnUndefined($params, 'channel_category_id'),
                    'country_code' => fillOnUndefined($params, 'country_code'),
                    'currency_code' => fillOnUndefined($params, 'currency_code'),
                    'logo' => fillOnUndefined($params, 'logo'),
                    'address' => fillOnUndefined($params, 'address'),
                    'zip_code' => fillOnUndefined($params, 'zip_code'),
                    'email' => fillOnUndefined($params, 'email'),
                    'phone' => fillOnUndefined($params, 'phone'),
                    'phone2' => fillOnUndefined($params, 'phone2'),
                    'fax' => fillOnUndefined($params, 'fax'),
                    'score' => fillOnUndefined($params, 'score'),
                    "status" => fillOnUndefined($params, "status", 1),
                    "created_by" => fillOnUndefined($params, "created_by", 0),
                    "updated_by" => fillOnUndefined($params, "updated_by", 0)

                ];

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

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

        try {

            $data = $this->propertyChannelRepository->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($id, $param = [])
    {


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


            $updateResult = $this->propertyChannelRepository->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);
    }

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

            $insertData =
                [
                    'parent_id' => fillOnUndefined($params, 'parent_id'),
                    'name' => fillOnUndefined($params, 'name'),
                    'official_name' => fillOnUndefined($params, 'official_name'),
                    'description' => fillOnUndefined($params, 'description'),
                    'channel_category_id' => fillOnUndefined($params, 'channel_category_id'),
                    'country_code' => fillOnUndefined($params, 'country_code'),
                    'currency_code' => json_encode(fillOnUndefined($params, 'currency_code', [])),
                    'logo' => fillOnUndefined($params, 'logo'),
                    'address' => fillOnUndefined($params, 'address'),
                    'zip_code' => fillOnUndefined($params, 'zip_code'),
                    'email' => fillOnUndefined($params, 'email'),
                    'phone' => fillOnUndefined($params, 'phone'),
                    'phone2' => fillOnUndefined($params, 'phone2'),
                    'fax' => fillOnUndefined($params, 'fax'),
                    'score' => fillOnUndefined($params, 'score'),
                    "status" => fillOnUndefined($params, "status", 1),
                    "created_by" => fillOnUndefined($params, "user_id"),
                    "updated_by" => fillOnUndefined($params, "user_id")
                ];


            $userCreateResult = $this->create($insertData);
            if ($userCreateResult['status'] != 'success') {
                throw new ApiErrorException($userCreateResult['message']);
            }
            $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 getPropertyChannels($params = [])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {


            $mappingData = [] ;

            if(isset($params['property_id'])){
                $criteria = [
                    'criteria' => [
                        ['field' => 'status', 'condition' => '=', 'value' => 1],
                        ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ]
                ];

                $mappingData = $this->propertyChannelMappingRepository->findByCriteria($criteria, ['id', 'property_id', 'channel_id','connected_channel_id', 'status']);
                $mappingData = $mappingData ? $mappingData : [] ;
                $mappingData = collect($mappingData)->keyBy('channel_id')->all() ;
            }

            $mappingDataPending = [] ;

            if(isset($params['property_id'])){
                $criteria = [
                    'criteria' => [
                        ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ]
                ];

                $mappingDataPending = $this->propertyChannelMappingRepository->findByCriteria($criteria, ['id', 'property_id', 'channel_id','connected_channel_id', 'status']);
                $mappingDataPending = $mappingDataPending ? $mappingDataPending : [] ;
                $mappingDataPending = collect($mappingDataPending)->keyBy('channel_id')->all() ;
            }

            $criteria = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1 ]
                ],
                'with' => ['propertyChannelCategory', 'parentChannel'],
                'orderBy' => [
                    ['field' => 'name', 'value' => 'ASC']
                ]
            ];


            if(isset($params['parent_id'])){
                $params['parent_id'] = $params['parent_id'] == "null" ? null : $params['parent_id'];
                $criteria['criteria'][] = ['field' => 'parent_id', 'condition' => '=', 'value' => $params['parent_id'] ] ;
            }
            if(isset($params['type'])){
                $criteria['criteria'][] = ['field' => 'type', 'condition' => '=', 'value' => $params['type'] ] ;
            }
            if(isset($params['channel_category_id'])){
                $criteria['criteria'][] = ['field' => 'channel_category_id', 'condition' => '=', 'value' => $params['channel_category_id'] ] ;
            }
            if(isset($params['country_code'])){
                $criteria['criteria'][] = ['field' => 'country_code', 'condition' => '=', 'value' => $params['country_code'] ] ;
            }


            $data = $this->propertyChannelRepository->findByCriteria($criteria,['id', 'parent_id', 'name', 'official_name', 'description', 'channel_category_id', 'country_code', 'restriction','currency_code', 'logo', 'address', 'zip_code', 'email', 'phone', 'phone2', 'fax', 'score', 'status']);


            $data = collect($data)->map(function ($channels) use ($params, $mappingData, $mappingDataPending){

                if($params['property_id']){
                    $channels['is_selected'] = isset($mappingData[$channels['id']]) ;
                    $channels['is_pending'] = isset($mappingDataPending[$channels['id']]) && $mappingDataPending[$channels['id']]['status'] == 2 ? true : false ;
                    $channels['connected_channel_id'] = isset($mappingData[$channels['id']]) ? $mappingData[$channels['id']]['connected_channel_id'] : null;
                }

                $channels["currency_code"] = json_decode($channels["currency_code"], 1);

                $channels['has_children'] = in_array($channels['channel_category_id'], [3,4]) ? true : false;

                return $channels;
            });

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

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

            if ($validationResult->errors()->first()) {
                $errors = $validationResult->errors()->all();
                throw new ApiErrorException($errors);
            }
            $updateData =
                [
                    'parent_id' => fillOnUndefined($params, 'parent_id'),
                    'name' => fillOnUndefined($params, 'name'),
                    'official_name' => fillOnUndefined($params, 'official_name'),
                    'description' => fillOnUndefined($params, 'description'),
                    'channel_category_id' => fillOnUndefined($params, 'channel_category_id'),
                    'country_code' => fillOnUndefined($params, 'country_code'),
                    'currency_code' => json_encode(fillOnUndefined($params, 'currency_code', [])),
                    'logo' => fillOnUndefined($params, 'logo'),
                    'address' => fillOnUndefined($params, 'address'),
                    'zip_code' => fillOnUndefined($params, 'zip_code'),
                    'email' => fillOnUndefined($params, 'email'),
                    'phone' => fillOnUndefined($params, 'phone'),
                    'phone2' => fillOnUndefined($params, 'phone2'),
                    'fax' => fillOnUndefined($params, 'fax'),
                    'score' => fillOnUndefined($params, 'score'),
                    "updated_by" => fillOnUndefined($params, "user_id", 0)
                ];

            $updateResult = $this->update($params['id'], $updateData);
            if ($updateResult['status'] != 'success') {
                throw new ApiErrorException($updateResult['message']);
            }
            $userData = $updateResult["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 checkChannelCategory($channel_id=0, $category_id=0){

        $response = false;

        $channel = $this->propertyChannelRepository->find($channel_id);
        if(isset($channel["channel_category_id"]) && $channel["channel_category_id"] == $category_id){
            $response = true;
        }

        return $response;
    }


}
