<?php

namespace twa\omnipay\controllers;

use Illuminate\Support\Facades\Http;
use twa\ecomcart\models\EcomPurchasesAttemptModel;

class PaypalController
{
    private $data;

    private $provider;

    public function __construct($data, $provider)
    {
        $this->provider = $provider;
        $required_data = ['client_id', 'client_secret'];
        \twa\omnipay\controllers\GeneralFunctions::checkRequiredData($data, $required_data);
        $this->data = collect($data);
    }

    public function createPayment($id, $value, $currency, $customer_name = null, $customer_email = null, $url_success = null, $url_cancel = null)
    {
        $access_token = self::getSession();

        if ($access_token == '') {
            dd('Unexpected Error: PaypalController createPayment() : unable to get session');
        }

        $mdata = [
            'intent' => 'CAPTURE',
            'purchase_units' => [
                [
                    'amount' => [
                        'currency_code' => $currency,
                        'value' => (string) $value,
                    ],
                ],
            ],
            'application_context' => [
                'landing_page' => "LOGIN",
                'shipping_preference' => 'NO_SHIPPING',
                'return_url' => $url_success,
                'cancel_url' => $url_cancel,
            ],
        ];

        $url = 'https://api-m.paypal.com/v2/checkout/orders';

        if (isset($this->data['test']) && $this->data['test']) {
            $url = 'https://api-m.sandbox.paypal.com/v2/checkout/orders';
        }

        $response = Http::withHeaders([
            'Authorization' => 'Bearer '.$access_token,
            'Content-Type' => 'application/json',
        ])->post($url, $mdata);

        if ($response->status() != '200' && $response->status() != '201') {
            dd($response->body());
            dd('Unexpected Error: Paypal createPayment() : unable to create order');
        }

        $output = json_decode($response->body(), 1);

        if (! is_array($output) || (is_array($output) && ! array_key_exists('links', $output))) {
            dd('Unexpected Error: PaypalController createPayment() : response is not valid');
        }

        try {
            $redirect = collect($output['links'])->where('rel', 'approve')->first();
            $redirect_url = $redirect['href'];
        } catch (\Throwable $th) {
            dd('Unexpected Error: PaypalController createPayment() : approve link is not found');
        }

        return collect(['redirect' => ['link' => $redirect_url], 'response' => $response->body()]);
    }

    public function capturePayment($id)
    {
        $attempt = EcomPurchasesAttemptModel::find($id);

        if (! $attempt) {
            return false;
        }

        $authorizationID = $attempt->gateway_init;

        if (is_null($authorizationID) || empty($authorizationID)) {
            $attempt->response_gateway = 'INVALID AUTHORIZATION ID';
            $attempt->save();

            return false;
        }

        $access_token = self::getSession();

        if ($access_token == '') {
            $attempt->response_gateway = 'PAYPAL AUTHENTICATION FAIL';
            $attempt->save();

            return false;
        }

        $curl = curl_init();

        $url = 'https://api-m.paypal.com/v2/payments/authorizations/'.$authorizationID.'/capture';

        if (isset($this->data['test']) && $this->data['test']) {
            $url = 'https://api-m.sandbox.paypal.com/v2/payments/authorizations/'.$authorizationID.'/capture';
        }

        curl_setopt_array($curl, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 0,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer '.$access_token,
                'Content-Type: application/json',
            ],
        ]);

        $response = curl_exec($curl);

        curl_close($curl);
        $output = json_decode($response, 1);
        $attempt->response_gateway = $response;
        $attempt->save();

        if (! is_array($output) || (is_array($output) && ! array_key_exists('status', $output))) {
            return false;
        }

        if ($output['status'] == 'COMPLETED') {
            return true;
        }

        return false;
    }

    public function getSession()
    {
        $curl = curl_init();

        $url = 'https://api-m.paypal.com/v1/oauth2/token';
        if (isset($this->data['test']) && $this->data['test']) {
            $url = 'https://api-m.sandbox.paypal.com/v1/oauth2/token';
        }

        curl_setopt_array($curl, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 0,
            CURLOPT_USERPWD => $this->data['client_id'].':'.$this->data['client_secret'],
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => 'grant_type=client_credentials',
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/x-www-form-urlencoded',
            ],
        ]);

        $response = curl_exec($curl);

        curl_close($curl);
        $session = json_decode($response, 1);

        if (! is_array($session) || (is_array($session) && ! array_key_exists('access_token', $session))) {
            return '';
        }

        return $session['access_token'];
    }

    public function checkPayment($id)
    {
        $purchase_attempt = EcomPurchasesAttemptModel::find($id);

        if (! $purchase_attempt) {
            return response(['status' => 'fail', 'response' => ["error" => "Purchase attempt not found"]], 400);
        }

        $capture_url = null;
        try {
            $response_gateway = json_decode($purchase_attempt->gateway_init);
            $redirect = collect(json_decode($response_gateway->response)->links)->where('rel', 'capture')->first();
            $capture_url = $redirect->href;
        } catch (\Throwable $th) {
            $capture_url = null;
        }

        if (!$capture_url) {
            return response(['status' => 'fail', 'response' => ["error" => "Capture ID and URL are null"]], 400);
        }

        $url = $capture_url;
        $method = 'POST';

        $access_token = $this->getSession();
        if ($access_token == '') {
            return response(['status' => 'fail', 'response' => ["error" => "Access token is null or empty"]], 400);
        }

        $curl = curl_init();

        curl_setopt_array($curl, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 0,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer '.$access_token,
                'Content-Type: application/json',
            ],
        ]);

        $response = curl_exec($curl);
        curl_close($curl);

        $output = json_decode($response, 1);

        //Specific Case
        try {
            if (isset($output["details"])) {
                $details = collect($output["details"])->where('issue', 'ORDER_ALREADY_CAPTURED')->first();
                if ($details) {
                    return response(['status' => 'success', 'response' => $output], 200);
                }
            }
        }catch(\Throwable $th){
//            return response(['status' => 'fail', 'response' => $output], 400);
        }

        //Specific Case

        if (isset($output['status']) && $output['status'] == 'COMPLETED') {
            return response(['status' => 'success', 'response' => $output], 200);
        }

        return response(['status' => 'fail', 'response' => $output], 400);
    }

    public function checkPaymentComplete($id){
        $purchase_attempt = EcomPurchasesAttemptModel::find($id);

        if (! $purchase_attempt) { response(['status' => 'fail', 'response' => ["error" => "Purchase attempt not found"]], 400); }
        $url = null;
        try {
            $response_gateway = json_decode($purchase_attempt->gateway_init);
            $redirect = collect(json_decode($response_gateway->response)->links)->where('rel', 'self')->first();
            $url = $redirect->href;
        } catch (\Throwable $th) {
            $url = null;
        }

        if (!$url) {
            return response(['status' => 'fail', 'response' => ["error" => "Capture ID and URL are null"]], 400);
        }

        $method = 'GET';

        $access_token = $this->getSession();
        if ($access_token == '') {
            return response(['status' => 'fail', 'response' => ["error" => "Access token is null or empty"]], 400);
        }

        $curl = curl_init();

        curl_setopt_array($curl, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 0,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer '.$access_token,
                'Content-Type: application/json',
            ],
        ]);

        $response = curl_exec($curl);
        curl_close($curl);

        $output = json_decode($response, 1);

        if (isset($output['status']) && $output['status'] == 'COMPLETED') {
            return response(['status' => 'success', 'response' => $output], 200);
        }

        return response(['status' => 'fail', 'response' => $output], 400);
    }
}
