<?php

namespace App\Core\Service;

use App\Core\Repository\Booking\BookingPaymentRepository;
use App\Core\Repository\Booking\BookingRepository;
use App\Core\Repository\PropertyPaymentMapping\PropertyPaymentMappingRepository;
use App\Core\Repository\Booking\BookingPaymentDataRepository;
use App\Core\Repository\Booking\BookingPaymentDataCheckRepository;

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

class BookingPaymentService
{

    private $bookingRepository;
    private $bookingPaymentRepository;
    private $propertyPaymentMappingRepository;


    public function __construct(
        BookingPaymentRepository $bookingPaymentRepository,
        BookingPaymentDataRepository $bookingPaymentDataRepository,
        BookingPaymentDataCheckRepository $bookingPaymentDataCheckRepository,
        PropertyPaymentMappingRepository $propertyPaymentMappingRepository,
        BookingRepository $bookingRepository
    )
    {
        $this->bookingPaymentRepository = $bookingPaymentRepository;
        $this->bookingPaymentDataRepository = $bookingPaymentDataRepository;
        $this->bookingPaymentDataCheckRepository = $bookingPaymentDataCheckRepository;
        $this->bookingRepository = $bookingRepository ;
        $this->propertyPaymentMappingRepository = $propertyPaymentMappingRepository ;
    }

    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 = [
                'booking_id' => fillOnUndefined($params, 'booking_id'),
                'payment_code' => fillOnUndefined($params, 'payment_code'),
                'payment_type_code' => fillOnUndefined($params, 'payment_type_code'),
                'payment_source_code' => fillOnUndefined($params, 'payment_source_code'),
                'extra_param' => fillOnUndefined($params, 'extra_param'),
                'total' => fillOnUndefined($params, 'total'),
                'currency_code' => fillOnUndefined($params, 'currency_code'),
                'status' => fillOnUndefined($params, 'status', 1),
            ];

            $userCreateResult = $this->bookingPaymentRepository->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->bookingPaymentRepository->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->bookingPaymentRepository->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 getPaymentDashboard($param){

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



            $requestData = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($param, 'property_id')]
                ],
                'orderBy' => [["field" => "id", "value" => "DESC"]],
                'with' => ['bookingPaymentTransaction'],
            ];

            $bookingList = $this->bookingRepository->findByCriteria($requestData, ['id', 'channel_id','booking_code', 'checkin_date', 'checkout_date', 'payment_type_code', 'total', 'currency_code', 'created_at', 'updated_at', 'status']);
            $bookings = collect($bookingList);

            $bookingPayments = $bookings->map(function ($booking){

                $paymentTransactions = collect($booking['booking_payment_transaction']) ;
                $allTransactions = $paymentTransactions->count();
                $confirmedTransactions = $paymentTransactions->where('status' , '=' , 1)->count();
                $pendingTransactions = $paymentTransactions->where('status' , '=' , 2)->count();
                $errorTransactions = $paymentTransactions->where('status' , '=' , 0)->count();
                $startTransactions = $paymentTransactions->where('status' , '=' , 3)->count();
                $cancelTransactions = $paymentTransactions->where('status' , '=' , 4)->count();

                return  [
                    'booking_id' => $booking['id'],
                    'all_transactions' => $allTransactions,
                    'confirmed_transactions' => $confirmedTransactions,
                    'pending_transactions' => $pendingTransactions,
                    'error_transactions' => $errorTransactions,
                    'start_transactions' => $startTransactions,
                    'cancel_transactions' => $cancelTransactions,
                ] ;

            })->values()->all() ;

            $requestPropertyPaymentMapping = [
                'criteria' => [
                    ['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($param, 'property_id')],
                    ['field' => 'status', 'condition' => '=', 'value' => 1],
                ],
            ];

            $propertyPaymentMappingList = $this->propertyPaymentMappingRepository->findByCriteria($requestPropertyPaymentMapping);
            $paymentMappings = collect($propertyPaymentMappingList)->count();

            $totalAllTransactions = collect($bookingPayments)->sum('all_transactions') ;
            $totalConfirmedTransactions = collect($bookingPayments)->sum('confirmed_transactions') ;
            $conversionRate = $totalAllTransactions ?  ($totalConfirmedTransactions * 100) / $totalAllTransactions  : 0;
            $totalAllTransactions = collect($bookingPayments)->sum('all_transactions') ;


            $responseData = [
                'all_transactions' => $totalAllTransactions,
                'confirmed_transactions' => $totalConfirmedTransactions,
                'conversion_rate' => number_format($conversionRate, 2),
                'active_pos_count' => $paymentMappings
            ];

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

        } 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 createPaymentData($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 = [
                'booking_id' => fillOnUndefined($params, 'booking_id'),
                'type' => fillOnUndefined($params, 'type'),
                'data' => fillOnUndefined($params, 'data'),
                'status' => fillOnUndefined($params, 'status', 1),
            ];

            $createResult = $this->bookingPaymentDataRepository->create($insertData);

            if ($createResult['status'] != 'success') {
                throw new Exception($createResult['message']);
            }
            $createData = $createResult["data"];
            $response = [
                'status' => true,
                'data' => $createData,
            ];

        } 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 selectPaymentData($param = [], $column = ['*'])
    {

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

        try {

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


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


            $updateResult = $this->bookingPaymentDataRepository->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 createPaymentDataCheck($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 = [
                'booking_id' => fillOnUndefined($params, 'booking_id'),
                'code' => fillOnUndefined($params, 'code'),
                'status' => fillOnUndefined($params, 'status', 2),
                'request_time' => fillOnUndefined($params, 'request_time'),
                'expiry_time' => fillOnUndefined($params, 'expiry_time'),
                'confirm_time' => fillOnUndefined($params, 'confirm_time'),
                'created_by' => fillOnUndefined($params, 'created_by'),
                'updated_by' => fillOnUndefined($params, 'updated_by'),

            ];

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

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

        try {

            $data = $this->bookingPaymentDataCheckRepository->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);
    }

}
