<?php


namespace App\Core\Service;

use App\Core\Repository\PropertyChannelBookingPaymentSetup\PropertyChannelBookingPaymentSetupRepository;
use App\Core\Service\PropertyChannelService;
use App\Core\Service\PropertyChannelMappingService;
use App\Core\Validator\PropertyChannelBookingPaymentSetup\PropertyChannelBookingPaymentSetupAddValidator;
use App\Core\Repository\PropertyChannel\PropertyChannelTaxRepository;

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


class PropertyChannelBookingPaymentSetupService
{
    private $propertyChannelBookingPaymentSetupRepository;
    private $propertyBookingPaymentTypeService;
    private $propertyChannelService;
    private $propertyChannelMappingService;
    private $propertyChannelBookingPaymentSetupAddValidator;


    public function __construct
    (
        Request $request,
        PropertyChannelBookingPaymentSetupRepository $propertyChannelBookingPaymentSetupRepository,
        PropertyBookingPaymentTypeService $propertyBookingPaymentTypeService,
        PropertyChannelService $propertyChannelService,
        PropertyChannelBookingPaymentSetupAddValidator $propertyChannelBookingPaymentSetupAddValidator,
        PropertyChannelMappingService $propertyChannelMappingService,
        PropertyChannelTaxRepository $propertyChannelTaxRepository
    )
    {
        $this->request = $request;
        $this->propertyChannelBookingPaymentSetupRepository = $propertyChannelBookingPaymentSetupRepository;
        $this->propertyBookingPaymentTypeService = $propertyBookingPaymentTypeService;
        $this->propertyChannelService = $propertyChannelService;
        $this->propertyChannelMappingService = $propertyChannelMappingService;
        $this->propertyChannelBookingPaymentSetupAddValidator = $propertyChannelBookingPaymentSetupAddValidator;
        $this->propertyChannelTaxRepository = $propertyChannelTaxRepository;

    }



    public function select($param = [], $column = ['*'])
    {
        $response = ['status' => -1, 'message' => '', 'data' => null];
        try {
            $data = $this->propertyChannelBookingPaymentSetupRepository->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 {

            $propertyCreateResult = $this->propertyChannelBookingPaymentSetupRepository->createAll($param);
            if ($propertyCreateResult['status'] != 'success') {
                throw new Exception('api-unknown_error');
            }
            $response = [
                'status' => true,
                'data' => $propertyCreateResult["data"]
            ];

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

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

            $propertyBookingPaymentTypeList = $this->propertyBookingPaymentTypeService->getPropertyBookingPaymentTypeList();

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

            $propertyChannelBookingPaymentSetup = $this->select($propertyChannelBookingPaymentSetupRequest, ['id','property_id', 'channel_id','cancellation_policy', 'property_channel_mapping_id',  'payment_type_id', 'is_affected_price', 'action_type', 'value_type', 'value','is_get_payment_data', 'is_selected']);

            if($propertyChannelBookingPaymentSetup['status'] != 'success'){
                throw new ApiErrorException('Property Channel Booking Payment Setup data not found');
            }

            $dataList = [];
            $dataList['channel_id'] = $params['channel_id'];
            foreach ($propertyBookingPaymentTypeList['data']['booking_payment_types'] as $propertyBookingPaymentType){

                if($propertyBookingPaymentType['code'] == 'CHN') {
                    //continue;
                }

                $setup = collect($propertyChannelBookingPaymentSetup['data'])
                    ->where('payment_type_id', '=', $propertyBookingPaymentType['id'])->first();

                $paymentCancellationPolicy = [];
                if(!empty($setup['cancellationPolicyArray'])) {
                    $paymentCancellationPolicy = $setup['cancellationPolicyArray'];
                }

                $dataList['payments'][] = [
                    "payment_type_id" =>  $propertyBookingPaymentType['id'],
                    "name" =>  $propertyBookingPaymentType['name'],
                    "code" =>  $propertyBookingPaymentType['code'],
                    "language_key" =>  $propertyBookingPaymentType['language_key'],
                    "is_affected_price" => isset($setup['is_affected_price']) ? $setup['is_affected_price'] : null,
                    "action_type" => isset($setup['action_type']) ? $setup['action_type'] : null,
                    "value_type" => isset($setup['value_type']) ? $setup['value_type'] : null,
                    "value" => isset($setup['value']) ? $setup['value'] : null,
                    "is_get_payment_data" => isset($setup['is_get_payment_data']) ? $setup['is_get_payment_data'] : null,
                    "is_selected" =>  $setup['is_selected'] ? true : false,
                    "cancellation_policy" =>  $paymentCancellationPolicy
                ];
            }

            $propertyChannelMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $params['channel_id']]
                ],
                'firstRow' => true
            ];

            $propertyCurrencyCode = $this->propertyChannelMappingService->select($propertyChannelMappingRequest, ['currency_code']);

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


            $getChannelRequest = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $params['channel_id']],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'with' => ['parentChannel'],
                'firstRow' => 1
            ];
            $getChannelResponse = $this->propertyChannelService->select($getChannelRequest, ['id', 'name','default_currency', 'currency_code']) ;
            if($getChannelResponse['status'] != 'success'){
                throw new ApiErrorException($getChannelResponse['message']);
            }
            $channelData['channel'] = $getChannelResponse['data'] ;


            $dataList['currency_code'] = isset($propertyCurrencyCode['data']) && !empty($propertyCurrencyCode['data']['currency_code'])
                ? $propertyCurrencyCode['data']['currency_code'] : $channelData['channel']['default_currency'];



            $getChannelMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $params['channel_id']],
                ],
                'firstRow' => 1
            ];
            $getChannelMappingResponse = $this->propertyChannelMappingService->select($getChannelMappingRequest) ;

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


            $channelTaxCriteria = ["criteria" => [["field" => "status", "condition" => "=", "value" => 1]]];
            $channelTaxes = $this->propertyChannelTaxRepository->findByCriteria($channelTaxCriteria, ['id', 'name', 'language_key', 'code']);
            $channelTaxes = $channelTaxes ? $channelTaxes : [];

            $channelTaxList = [];
            foreach ($channelTaxes as $channelTax) {
                $channelTaxList[] = [
                    "id" =>  $channelTax['id'],
                    "name" =>  $channelTax['name'],
                    "language_key" =>  $channelTax['language_key'],
                    "code" =>  $channelTax['code'],
                    "is_selected" =>  $channelTax['id'] == $getChannelMappingResponse['data']['channel_tax_id'] ? true : false,
                ];
            }

            $dataList['channel_tax'] = $channelTaxList;

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

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

        try {

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

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

            $oldMappingList = $this->propertyChannelBookingPaymentSetupRepository->findByCriteria($criteria);

            $criteria =
                [
                    "criteria" =>
                        [
                            ["field" => "property_id", "condition" => "=", "value" => $params['property_id']],
                            ["field" => "channel_id", "condition" => "=", "value" => $params['channel_id']],
                        ],
                    "firstRow" => 1
                ];

            $channelMapping = $this->propertyChannelMappingService->select($criteria);

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

            if(empty($oldMappingList)){
                $setupData = [];
                foreach ($params['payments'] as $channelSetup) {
                    $setupData[] =
                        [
                            "property_id" => $params['property_id'],
                            "channel_id" => $params['channel_id'],
                            "property_channel_mapping_id" => $channelMapping['id'],
                            "payment_type_id" => fillOnUndefinedAndEmpty($channelSetup, 'payment_type_id', null),
                            "cancellation_policy" => !empty($channelSetup['cancellation_policy']) ? json_encode($channelSetup['cancellation_policy']) : null,
                            "is_affected_price" => fillOnUndefinedAndEmpty($channelSetup, 'is_affected_price', 0),
                            "is_get_payment_data" => fillOnUndefinedAndEmpty($channelSetup, 'is_get_payment_data', 0),
                            "action_type" => fillOnUndefinedAndEmpty($channelSetup, 'action_type', null),
                            "value_type" => fillOnUndefinedAndEmpty($channelSetup, 'value_type', null),
                            "value" => fillOnUndefinedAndEmpty($channelSetup, 'value', null),
                            "is_selected" => $channelSetup['is_selected'],
                            "status" => 1,
                            "created_by" => $params['user_id'],
                            "updated_by" => $params['user_id'],
                            "created_at" => time(),
                            "updated_at" => time(),
                        ];
                }

                $createStatus =   $this->create($setupData);

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

            }else{

                foreach ($params['payments'] as $channelSetup) {

                    $updateData = collect($oldMappingList)->firstWhere('payment_type_id',$channelSetup['payment_type_id']);
                    if(!empty($updateData)){
                        $setupData =
                            [
                                "property_id" => $params['property_id'],
                                "channel_id" => $params['channel_id'],
                                "payment_type_id" => fillOnUndefinedAndEmpty($channelSetup, 'payment_type_id', null),
                                "cancellation_policy" => !empty($channelSetup['cancellation_policy']) ? json_encode($channelSetup['cancellation_policy']) : null,
                                "action_type" => fillOnUndefinedAndEmpty($channelSetup, 'action_type', null),
                                "value_type" => fillOnUndefinedAndEmpty($channelSetup, 'value_type', null),
                                "value" => fillOnUndefinedAndEmpty($channelSetup, 'value', null),
                                "is_affected_price" => fillOnUndefinedAndEmpty($channelSetup, 'is_affected_price', 0),
                                "is_get_payment_data" => fillOnUndefinedAndEmpty($channelSetup, 'is_get_payment_data', 0),
                                "is_selected" => $channelSetup['is_selected'],
                                "status" => 1,
                                "updated_by" => $params['user_id'],
                                "updated_at" => time()
                            ];

                        $updateStatus =  $this->update($updateData['id'], $setupData);

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

            }


            $getChannelMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => $params['channel_id']],
                ],
                'firstRow' => 1
            ];
            $getChannelMappingResponse = $this->propertyChannelMappingService->select($getChannelMappingRequest);
            $getChannelMappingResponse = $getChannelMappingResponse['status'] ? $getChannelMappingResponse['data'] : [];

            $channelTaxCriteria = ["criteria" => [["field" => "status", "condition" => "=", "value" => 1]]];
            $channelTaxes = $this->propertyChannelTaxRepository->findByCriteria($channelTaxCriteria, ['id', 'name', 'language_key', 'code']);
            $channelTaxes = $channelTaxes ? $channelTaxes : [];

            if(isset($params['channel_tax']) ||  is_null($params['channel_tax'])) {
                $this->propertyChannelMappingService->update($getChannelMappingResponse['id'], ['channel_tax_id' => $params['channel_tax']]);
            }

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

        } catch (ApiErrorException $e) {
            $response['status'] = 0;
            $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);
    }



}
