<?php

namespace app\libraries\paypal;

use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\PaymentExecution;
use PayPal\Api\RedirectUrls;
use PayPal\Api\ShippingAddress;
use PayPal\Api\Transaction;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Rest\ApiContext;


class PaypalClient
{
    private $account = 'sb-aec5v1009492@business.example.com';
    private $account_password = '2FIL^]k@';
    private $client_id = 'AcuzXJmSt-M86PmasDDjTlFCu0OfYrwU0TJPqMbNfbCV5SBhYWMwpGbe3RwIHSpyvLCzFVYQMJzDlLRv';
    private $client_secret = 'EAxmFuHgckmXgiG1sfn6Lx-1fv_kahe9Tx91opgkhgsDSSg7wESeYboTT2jPb4WECHXXwTei-Nbf404u';
    private $mode = 'sandbox';
    private $http_connection_timeout = 30;
    private $cache_enabled = true;
    private $http_curlopt_cainfo = APPPATH . 'libraries/paypal/conf/cacert.pem';
    // Log files
    private $log_enabled = true;
    private $log_pathname = APPPATH . 'libraries/paypal/paypal.log';
    private $log_level = 'INFO';
    private $validation_level = 'log';

    public $payment_intent = 'sale';
    public $payment_description;
    public $payment_currency = 'HKD';
    public $payment_total = 520 + 920 - 2;
    public $shipping_fee = 0;
    public $tax = 0;

    public $success_url;
    public $cancel_url;

    private $itemList;
    private $paypal;


    public function migrate_to_paypal_item_list($itemList, $recipient = [])
    {
        if ($this->payment_description == '') exit;

        // $itemList = [
        //     ['sku' => '123', 'name' => '賬單支付', 'quantity' => 1, 'currency' => 'HKD', 'price' => doubleval(520)],
        //     ['sku' => '456', 'name' => '賬單支付', 'quantity' => 1, 'currency' => 'HKD', 'price' => doubleval(920)],
        //     ['sku' => null, 'name' => 'Discount', 'quantity' => 1, 'currency' => 'HKD', 'price' => doubleval(-2)],
        // ];
        // $itemSubtotal = 520 + 920 - 2;

        $paymentItemList = [];
        foreach ($itemList as $item) {
            $paymentItem = new Item();
            if (isset($item['sku'])) {
                $paymentItem
                    ->setSku($item['sku'])
                    ->setName($item['name'])
                    ->setQuantity($item['quantity'])
                    ->setCurrency($item['currency'])
                    // ->setPrice(doubleval($item['price']));
                    ->setPrice($item['price']);
            } else {
                $paymentItem
                    ->setName($item['name'])
                    ->setQuantity($item['quantity'])
                    ->setCurrency($item['currency'])
                    // ->setPrice(doubleval($item['price']));
                    ->setPrice($item['price']);
            }
            array_push($paymentItemList, $paymentItem);
        }
        $this->itemList = new ItemList();
        $this->itemList->setItems($paymentItemList);
        if (!empty($recipient)) {
            $address = new ShippingAddress();
            $address
                ->setRecipientName($recipient['recipient_name'])
                ->setCountryCode($recipient['country_code'])
                ->setLine1(trim($recipient['line_1']))
                ->setLine2(trim($recipient['line_2']))
                ->setPhone($recipient['phone']);
            $this->itemList->setShippingAddress($address);
        }
    }

    // public function create_payment_info() {}

    public function create_payment()
    {
        // set payer
        $payer = new Payer();
        $payer->setPaymentMethod('paypal');

        $details = new Details();
        $details
            ->setShipping(0)
            ->setTax(0)
            ->setSubtotal($this->payment_total);

        $amount = new Amount();
        $amount
            ->setCurrency($this->payment_currency)
            ->setTotal($this->payment_total)
            ->setDetails($details);

        // set transactions
        $transaction = new Transaction();
        $transaction
            ->setItemList($this->itemList)
            ->setDescription($this->payment_description)
            ->setAmount($amount)
            ->setInvoiceNumber(uniqid());

        // set redirect urls
        $redirects = new RedirectUrls();

        // $returnUrl = $this->getHttpsHost() . route_to('paypal_success') . sprintf('?student_id=%s&invoice_id=%s', $paypal->studentId, $paypal->invoiceId);
        // $cancelUrl = $this->getHttpsHost() . route_to('paypal_cancel') . sprintf('?student_id=%s&invoice_id=%s', $paypal->studentId, $paypal->invoiceId);


        $redirects
            ->setReturnUrl($this->success_url)
            ->setCancelUrl($this->cancel_url);

        $payment = new Payment();
        $payment
            ->setIntent($this->payment_intent)
            ->setPayer($payer)
            ->setRedirectUrls($redirects)
            ->setTransactions([$transaction]);

        $payment = $this->paymentCreate($payment);
        $payment_transaction = $payment->transactions[0];
        return [
            'approval_link' => $payment->getApprovalLink(),
            'transaction' => [
                'payment_id' => $payment->id,
                'state'        => $payment->state,
                'intent'       => $payment->intent,
                'payer'        => $payment->payer,
                'transactions' => $payment_transaction,
            ],
            'amount' => $payment_transaction->getAmount()->toArray()
        ];
    }

    public function execute($payment_id, $payer_id)
    {
        $payment = $this->paymentGet($payment_id);

        $execution = new PaymentExecution();
        $execution->setPayerId($payer_id);

        $payment = $this->paymentExecute($payment, $execution);
        $payment_transaction = $payment->transactions[0];

        return [
            'transaction' => [
                'payment_id' => $payment->id,
                'state'        => $payment->state,
                'intent'       => $payment->intent,
                'payer'        => $payment->payer,
                'transactions' => $payment_transaction,
            ],
            'amount' => $payment_transaction->getAmount()->toArray()
        ];
    }

    private function paymentCreate(Payment $payment)
    {
        return $payment->create($this->getApi());
    }

    // Used when success / get payment info
    private function paymentGet($payment_id)
    {
        return Payment::get($payment_id, $this->getApi());
    }

    // Used when success / get payment info
    private function paymentExecute(Payment $payment,  $paymentExecution)
    {
        return $payment->execute($paymentExecution, $this->getApi());
    }

    private function getApi()
    {
        $api = new ApiContext(
            new OAuthTokenCredential($this->client_id, $this->client_secret)
        );

        $configParams = [
            'mode'                   => $this->mode,
            'http.ConnectionTimeOut' => $this->http_connection_timeout,
            'http.CURLOPT_CAINFO'    => $this->http_curlopt_cainfo,
            'log.LogEnabled'         => $this->log_enabled,
            'log.FileName'           => $this->log_pathname,
            'log.LogLevel'           => $this->log_level,
            'validation.level'       => $this->validation_level,
            'cache.enabled'          => $this->cache_enabled,
        ];

        $api->setConfig($configParams);

        return $api;
    }
}
