<?php

namespace apexl\Io\modules\payment\providers;

use angelleye\PayPal\PayPal;
use apexl\Config\Singleton;
use apexl\Io\modules\payment\entities\paymentLogEntity;
use Stripe\Checkout\Session;
use Stripe\Stripe;
use Stripe\StripeClient;
use Stripe\Event;
use Stripe\Webhook;

class paypalProvider implements providerInterface {

    protected $config;
    protected $paypal;
    protected $testMode;

    public function __construct()
    {
        $this->config = Singleton::getInstance();
    }

    public function initialise()
    {
        if ($this->paypal) return;

        $this->paypal = new PayPal([
            'Sandbox' => $this->config->app->payments->paypal->sandbox,
            'APIUsername' => $this->config->app->payments->paypal->api_username,
            'APIPassword' => $this->config->app->payments->paypal->api_password,
            'APISignature' => $this->config->app->payments->paypal->api_signature,
            //'PrintHeaders' => false,
            //'LogResults' => false,
            //'LogPath' => $_SERVER['DOCUMENT_ROOT'].'/logs/',
        ]);

    }
    
    public function capturePaymentWithToken($paymentMethodId, $customerRef=null, $amount=0, $description = '', $currency='gbp', $data=null, $metaData=null, $transactionData, $threeDSecureReturnUrl=null)
    {
        //return ["6H363618J7528103X", "6H363618J7528103X", false, null];

        $this->initialise();

        $paymentLog = new paymentLogEntity();
        $paymentLog->ts = date('Y-m-d H:i:s');
        $paymentLog->provider = 'paypal';
        $paymentLog->api_name = $this->config->app->payments->paypal->sandbox ? 'paypal_sandbox' : 'paypal_live';
        $paymentLog->method_name = 'DoReferenceTransaction';
        $paymentLog->store();

        try {

            $PayPalRequestData = [
                'DRTFields' => [
                    'referenceid' => $paymentMethodId,
                    'paymentaction' => 'Sale',
                    'returnfmfdetails' => '1',
                    'softdescriptor' => 'Global M2M Sim'
                ],
                'PaymentDetails' => [
                    'amt' => $amount,                            // Required. Total amount of the order, including shipping, handling, and tax.
                    'currencycode' => 'GBP',                    // A three-character currency code.  Default is USD.
                    'itemamt' => $amount-$transactionData->vat,                        // Required if you specify itemized L_AMT fields. Sum of cost of all items in this order.
                    'taxamt' => $transactionData->vat,                // Required if you specify itemized L_TAXAMT fields.  Sum of all tax items in this order.
                    'insuranceoptionoffered' => '',            // If true, the insurance drop-down on the PayPal review page displays Yes and shows the amount.
                    'desc' => $transactionData->title,                // Description of items on the order.  127 char max.
                    'custom' => $transactionData->msisdn,            // Free-form field for your own use.  256 char max.
                    'invnum' => $transactionData->tracking_number,    // Your own invoice or tracking number.  127 char max.
                ]
            ];
            $paymentLog->request_data = json_encode($PayPalRequestData);
            $paymentLog->store();

            $PayPalResult = $this->paypal->DoReferenceTransaction($PayPalRequestData);


            $paymentLog->response_data = json_encode($PayPalResult);
            $paymentLog->store();

            if ($PayPalResult['ACK'] == 'Success') {
                return [$PayPalResult['TRANSACTIONID'], $PayPalResult['TRANSACTIONID'], false, null];
            } else {
                return [false, false, false, "Auto Topup for " . $transactionData->msisdn . " Failed with - " . $PayPalResult['L_LONGMESSAGE0'] . ", " . $PayPalResult['L_LONGMESSAGE1']];
            }

        } catch (\Exception $e) {
            $paymentLog->response_data = json_encode([$e->getMessage()]);
            $paymentLog->store();
            return [false, false, false, $e->getMessage()];
        }

    }

    public function getCardValidationUrl($successUrl, $cancelUrl, $localTokenId, $customerRef, $meta)
    {
        return null;
    }

    public function retrieveToken($sessionId)
    {
        return null;
    }

    public function attachCustomerToPaymentMethod($paymentMethodId, $email, $fullName, $customerId)
    {
        return null;
    }



    protected function makeRequest($apiName, $methodName, $id=null, $data=[], $subMethodName=null)
    {
        $logData = $data;

        try {

            if (!is_null($id)) {
                if ($subMethodName) {
                    $response = $this->stripe->$apiName->$methodName->$subMethodName($id, $data);
                    $methodName = "$methodName > $subMethodName";
                } else {
                    $response = $this->stripe->$apiName->$methodName($id, $data);
                }
            } else {
                $response = $this->stripe->$apiName->$methodName($data);
            }

            $logResponse = $response;

        } catch(\Stripe\Exception\CardException $e) { // Payment decline
            $logResponse = (object)[
                'Error' => 'Stripe API: Payment Exception. ' . $e->getMessage(),
                'Status' => $e->getHttpStatus(),
                'Type' => $e->getError()->type,
                'Code' => $e->getError()->code,
                'Param' => $e->getError()->param,
                'Message' => $e->getError()->message
            ];
        } catch (\Stripe\Exception\RateLimitException $e) {
            $logResponse = (object)['Error' => 'Stripe API: rate limit exceeded. ' . $e->getMessage()];
        } catch (\Stripe\Exception\InvalidRequestException $e) {
            $logResponse = (object)['Error' => 'Stripe API: Invalid parameters were supplied. ' . $e->getMessage()];
        } catch (\Stripe\Exception\AuthenticationException $e) {
            $logResponse = (object)['Error' => 'Stripe API: Authentication failed. ' . $e->getMessage()];
        } catch (\Stripe\Exception\ApiConnectionException $e) {
            $logResponse = (object)['Error' => 'Stripe API: Network communication failed. ' . $e->getMessage()];
        } catch (\Stripe\Exception\ApiErrorException $e) {
            $logResponse = (object)['Error' => 'Stripe API: Generic API failure. ' . $e->getMessage()];
        } catch (\Exception $e) {
            $logResponse = (object)['Error' => $e->getMessage()];
        }

        $hideFields = [
            'payment_method'
        ];
        foreach ($hideFields as $field) {
            if (isset($logResponse->$field)) $logResponse->field = 'hidden_for_security';
            if (isset($logData[$field])) $logData[$field] = 'hidden_for_security';
        }

        $hideIdsForApis = [
            'paymentMethods'
        ];
        foreach ($hideIdsForApis as $method) {
            if ($apiName == $method) {
                $id = 'hidden_for_security';
                if (isset($logResponse->id)) $logResponse = ['hidden_for_security'];
                if (isset($logData['id'])) $logData['id'] = 'hidden_for_security';
            }
        }

        $paymentLog = new paymentLogEntity();
        $paymentLog->ts = date('Y-m-d H:i:s');
        $paymentLog->provider = 'stripe';
        $paymentLog->api_name = $apiName;
        $paymentLog->method_name = $methodName;
        if ($id) $paymentLog->provider_id = $id;
        elseif (isset($logResponse->id)) $paymentLog->provider_id = $logResponse->id;
        $paymentLog->request_data = json_encode($logData);
        $paymentLog->response_data = json_encode($logResponse);
        $paymentLog->store();

        return $response ?? $logResponse;
    }


}