<?php

namespace App\Http\Controllers\BookingEngine\V1;

use App\Core\Service\BookingService;
use App\Core\Service\BookingRoomService;
use App\Core\Service\BookingRoomPaxService;
use App\Core\Service\BookingContactService;
use App\Core\Service\BookingPaymentService;
use App\Core\Service\PropertyRoomAvailabilityService;
use App\Core\Service\PropertyChannelMappingService;
use App\Core\Service\PropertyPaymentService;
use App\Core\Service\NewBookingMailService;
use App\Core\Service\PropertyService;
use App\Core\Service\LanguageService;
use App\Core\Service\ManualPaymentMailService;

use Carbon\Carbon;
use Illuminate\Http\Request;

use App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
use Exception;
use App\Exceptions\ApiErrorException;
use phpDocumentor\Reflection\Types\Collection;

class PaymentLinkController extends BookingEngineBaseController
{

    private $request;
    private $newBookingMailService;
    private $propertyPaymentService;
    private $propertyService;
    private $languageService;
    private $manualPaymentMailService;

    public function __construct(
        Request $request,
        PropertyPaymentService $propertyPaymentService,
        PropertyService $propertyService,
        LanguageService $languageService,
        ManualPaymentMailService $manualPaymentMailService,
        PropertyChannelMappingService $propertyChannelMappingService
    )
    {
        $this->request = $request;
        $this->propertyPaymentService = $propertyPaymentService;
        $this->propertyService = $propertyService;
        $this->languageService = $languageService;
        $this->manualPaymentMailService = $manualPaymentMailService;
        $this->propertyChannelMappingService = $propertyChannelMappingService;
    }


    public function paymentLinkDetail(Request $request, $orderCode)
    {

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

            $paymentDetailParam = [
                'criteria' => [
                    ['field' => 'order_id', 'condition' => '=', 'value' => $orderCode],
                    ['field' => 'transaction_type', 'condition' => '=', 'value' => 'LNK'],
                    ['field' => 'status', 'condition' => '=', 'value' => 5],
                ],
                'with' => ['relatedTransactions', 'paymentTypeMapping.paymentType'],
                'firstRow' => true
            ];

            $paymentDetail = $this->propertyPaymentService->selectPaymentTransaction($paymentDetailParam);

            if ($paymentDetail['status'] != 'success' || empty($paymentDetail['data'])) {
                throw new ApiErrorException(lang('Payment not found'));
            }

            $paymentDetail = $paymentDetail['data'];

            if ($paymentDetail['status'] != 5) {
                throw new ApiErrorException(lang('Payment not link status'));
            }

            $paymentDetail['is_payed'] = false;
            if (!empty($paymentDetail['related_transactions'])) {
                $relatedTransactions = collect($paymentDetail['related_transactions']);
                if ($relatedTransactions->where('status', 1)->count() > 0) {
                    $paymentDetail['is_payed'] = true;
                }
            }

            $propertyId = $paymentDetail['property_id'];

            $propertyParam = [
                'criteria' => [
                    ['field' => 'id', 'condition' => '=', 'value' => $propertyId],
                ],
                'with' => ['propertyBrand', 'propertyContact'],
                'firstRow' => true
            ];

            $getProperty = $this->propertyService->select($propertyParam);

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

            $property = $getProperty['data'];

            $property['property_brand']['logo_url'] = $property['property_brand'] ? Config::get('app.imageUrl') . '/property-photos/' . $property['id'] . "/logo/" . $property['property_brand']['logo_name'] . '_250x250.' . $property['property_brand']['logo_file_ext'] : null;
            $property['property_contact']['social_media_addresses'] = json_decode($property['property_contact']['social_media_addresses'], 1);

            $availableLanguageRequest = [
                'criteria' => [
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                    ['field' => 'is_application', 'condition' => '=', 'value' => 1],
                    ['field' => 'is_published', 'condition' => '=', 'value' => 1]
                ],
            ];

            $availableLanguages = $this->languageService->select($availableLanguageRequest, ['code', 'name', 'language_key']);
            $availableLanguages = Collect($availableLanguages['data'])->keyBy('code')->all();


            //contract_file
            $property['contract_file'] = null;
            $channelMappingRequest = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => $property['id']],
                    ['field' => 'channel_id', 'condition' => '=', 'value' => 1],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'firstRow' => 1
            ];

            $channelMapping = $this->propertyChannelMappingService->select($channelMappingRequest, ['id', 'contract_file', 'currency_code']);
            if ($channelMapping['status'] == 'success' && !empty($channelMapping['data'])) {
                $property['contract_file'] = Config::get('app.propertyFilesUrl') . $channelMapping['data']['contract_file'];
            }
            //contract_file

            $responseData = [
                'payment_detail' => $paymentDetail,
                'property_detail' => $property,
                'available_languages' => $availableLanguages,
            ];

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

        } 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 paymentLinkInitialize(Request $request)
    {

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

            if (is_null($this->request->getContent())) {
                throw new ApiErrorException(lang('Parameter Error.'));
            }

            $params = json_decode($this->request->getContent(), 1);

            $orderCode = $params['orderCode'];

            $paymentDetailParam = [
                'criteria' => [
                    ['field' => 'order_id', 'condition' => '=', 'value' => $orderCode],
                    ['field' => 'transaction_type', 'condition' => '=', 'value' => 'LNK'],
                    ['field' => 'status', 'condition' => '=', 'value' => 5],
                ],
                'firstRow' => true
            ];

            $paymentDetail = $this->propertyPaymentService->selectPaymentTransaction($paymentDetailParam);

            if ($paymentDetail['status'] != 'success' || empty($paymentDetail['data'])) {
                throw new ApiErrorException(lang('Payment not found'));
            }

            $paymentDetail = $paymentDetail['data'];

            if ($paymentDetail['status'] != 5) {
                throw new ApiErrorException(lang('Payment not link status'));
            }

            $paymentStatusCheckParam = [
                'criteria' => [
                    ['field' => 'order_id', 'condition' => '=', 'value' => $orderCode],
                    ['field' => 'transaction_type', 'condition' => '=', 'value' => 'LNK'],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'firstRow' => true
            ];

            $paymentStatusCheck = $this->propertyPaymentService->selectPaymentTransaction($paymentStatusCheckParam);

            if ($paymentStatusCheck['status'] == 'success' && !empty($paymentStatusCheck['data'])) {
                throw new ApiErrorException(lang('Previously paid transaction'));
            }


            DB::beginTransaction();

            $initializePaymentParam = [
                'propertyId' => $paymentDetail['property_id'],
                'orderId' => $paymentDetail['order_id'],
                'installment' => 0,
                'amount' => (double)$paymentDetail['amount'],
                'currency' => $paymentDetail['currency'],
                'type' => 'LNK',
                'preferredPaymentTypeId' => $paymentDetail['payment_type_mapping_id'],
                'responseUrl' => $params['responseUrl'],
                'creditCard' => [
                    'name' => $params['creditCard']['cardHolder'],
                    'number' => $params['creditCard']['cardNumber'],
                    'month' => $params['creditCard']['cardExpireMonth'],
                    'year' => $params['creditCard']['cardExpireYear'],
                    'cvv' => $params['creditCard']['cardCvv'],
                ]
            ];

            $initializePayment = $this->propertyPaymentService->initializePayment($initializePaymentParam);

            if (!$initializePayment['status']) {
                throw new ApiErrorException(lang($initializePayment['message']));
            }

            $responseData = [
                'orderCode' => $paymentDetail['order_id'],
                'paymentCode' => $initializePayment['data']['paymentCode'],
            ];

            if (isset($initializePayment['data']['redirectUrl'])) {
                $responseData['redirectUrl'] = $initializePayment['data']['redirectUrl'];
            }


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

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

    }

    public function paymentLinkConfirm(Request $request)
    {

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

            if (is_null($this->request->getContent())) {
                throw new ApiErrorException(lang('Parameter Error.'));
            }

            $params = json_decode($this->request->getContent(), 1);

            $orderCode = $params['orderCode'];
            $paymentCode = $params['paymentCode'];

            $paymentDetailParam = [
                'criteria' => [
                    ['field' => 'order_id', 'condition' => '=', 'value' => $orderCode],
                    ['field' => 'code', 'condition' => '=', 'value' => $paymentCode],
                    ['field' => 'transaction_type', 'condition' => '=', 'value' => 'LNK'],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
                'firstRow' => true
            ];

            $paymentDetail = $this->propertyPaymentService->selectPaymentTransaction($paymentDetailParam);

            if ($paymentDetail['status'] != 'success' || empty($paymentDetail['data'])) {
                throw new ApiErrorException(lang('Payment not confirmed'));
            }

            $paymentDetailParam = [
                'orderCode' => $orderCode,
                'language_code' => isset($params['language_code']) ? $params['language_code'] : 'en'
            ];
            $this->manualPaymentMailService->process($paymentDetailParam);

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

        } 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 createManualPaymentForm(Request $request)
    {

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

        try {

            if (is_null($this->request->getContent())) {
                throw new ApiErrorException(lang('Parameter Error.'));
            }

            $params = $this->request->params;
            $createPaymentLink = $this->propertyPaymentService->createManualPaymentForm($params);

            if ($createPaymentLink['status'] != "success") {
                throw new ApiErrorException($createPaymentLink['message']);
            }
            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $createPaymentLink['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 apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);


    }

    public function createManualPayment(Request $request)
    {

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

        try {

            if (is_null($this->request->getContent())) {
                throw new ApiErrorException(lang('Parameter Error.'));
            }

            $params = $this->request->params;

            $params['user_id'] = $request->credentials->user_id;

            $createPaymentLink = $this->propertyPaymentService->createManualPayment($params);

            if ($createPaymentLink['status'] != "success") {
                throw new ApiErrorException($createPaymentLink['message']);
            }
            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $createPaymentLink['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 apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);


    }

    public function editManualPaymentForm(Request $request)
    {

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

        try {

            if (is_null($this->request->getContent())) {
                throw new ApiErrorException(lang('Parameter Error.'));
            }

            $params = $this->request->params;
            $createPaymentLink = $this->propertyPaymentService->editManualPaymentForm($params);

            if ($createPaymentLink['status'] != "success") {
                throw new ApiErrorException($createPaymentLink['message']);
            }
            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $createPaymentLink['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 apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);


    }

    public function updateManualPayment(Request $request)
    {

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

        try {

            if (is_null($this->request->getContent())) {
                throw new ApiErrorException(lang('Parameter Error.'));
            }

            $params = $this->request->params;
            $createPaymentLink = $this->propertyPaymentService->updateManualPayment($params);

            if ($createPaymentLink['status'] != "success") {
                throw new ApiErrorException($createPaymentLink['message']);
            }
            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $createPaymentLink['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 apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);


    }

    public function getManualPayment(Request $request)
    {

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

        try {

            if (is_null($this->request->getContent())) {
                throw new ApiErrorException(lang('Parameter Error.'));
            }

            $params = $this->request->params;
            $createPaymentLink = $this->propertyPaymentService->getManualPayment($params);

            if ($createPaymentLink['status'] != "success") {
                throw new ApiErrorException($createPaymentLink['message']);
            }
            $response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $createPaymentLink['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 apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);


    }

}
