<?php

use Mtc\Shop\Checkout\OrderPaypal;

header('HTTP/1.1 200 OK');

// INITIALISE
$path = "../../../";
require($path . 'core/includes/header.inc.php');

// Logging
$log = false;
if (DEV_MODE) {
    $log = SITE_PATH . '/paypal_log.txt';
}

// email DEV
if (DEV_MODE && PAYPAL_TEST && defined('DEV_EMAIL') && DEV_EMAIL != '') {
    @mail(DEV_EMAIL, config('app.name') . ' - paypal callback', print_r($_REQUEST, true));
}

// build callback request
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
    $req .= "&" . $key . "=" . urlencode($value);
}
if (!empty($log)) file_put_contents($log, date("Y-m-d H:i:s") . " - " . $req . "\r\n", FILE_APPEND);


// choose gateway
$port = 443;
$protocol = 'ssl://';
$gateway = 'www.paypal.com';
if (PAYPAL_TEST) {
    $gateway = 'www.sandbox.paypal.com';
    if (!empty($log)) file_put_contents($log, date("Y-m-d H:i:s") . " - Using sandbox gateway\r\n", FILE_APPEND);
}

// build callback headers
$header .= "POST /cgi-bin/webscr HTTP/1.1\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n";
$header .= "Host: " . $gateway . "\r\n";
$header .= "Connection: close\r\n";
$header .= "\r\n";

// callback PayPal
$fp = fsockopen($protocol . $gateway, $port, $errno, $errstr, 30);

// connection failed
if (!$fp) {
    if (!empty($log)) file_put_contents($log, date("Y-m-d H:i:s") . " - Failed to open HTTP connection\r\n", FILE_APPEND);
    if (!empty($log)) file_put_contents($log, "[" . $errno . "] " . $errstr . "\r\n", FILE_APPEND);
} // connection successful
else {

    // send data
    fputs($fp, $header . $req);

    // read response
    while (!feof($fp)) {
        $res = fgets($fp, 1024);
        if (!empty($log)) file_put_contents($log, date("Y-m-d H:i:s") . " - Response: " . trim($res) . "\r\n", FILE_APPEND);

        // verified
        if (strstr($res, "VERIFIED")) {

            // payment status completed
            if (strcmp($_POST['payment_status'], "Completed") == 0) {

                // check if order already received
                $paymentExists = OrderPaypal::query()
                    ->where('txn_id', $_REQUEST['txn_id'])
                    ->exists();

                // if new order, process
                if (!$paymentExists) {

                    $invoice = $_REQUEST['invoice'];
                    $invoiceOrderPart = $invoice;
                    if (strpos($invoice, '-') !== false) {
                        $invoiceOrderPart = strstr($invoice, '-', true);
                    }

                    $orderId = null;
                    $prefixPattern = '/^' . preg_quote(config('site.tnx_prefix'), '/') . '(\d+)$/';
                    if (preg_match($prefixPattern, $invoiceOrderPart, $matches)) {
                        $orderId = (int)$matches[1];
                    }

                    if ($orderId === null) {
                        http_response_code(400);
                        if (!empty($log)) file_put_contents($log, date("Y-m-d H:i:s") . " - Unable to resolve order id from invoice: " . $invoice . "\r\n", FILE_APPEND);
                        continue;
                    }

                    $newbasket = new Order($orderId);

                    // check if the amount matches approximately, ie up to 2 pennies
                    if ($newbasket->matchesTotal($_REQUEST['mc_gross'])) {
                        // google analytics tracking is done in the OrderPaid event handler
                        // fired in the markPaid method.
                        $newbasket->markPaid(\Order::PAYMENT_TYPE_PAYPAL);
                        $newbasket->savePaypal($_REQUEST);
                        if (PPC_TRACKING) {
                            track('sale', $newbasket->getTotalCost(), $newbasket->ref, $newbasket->keywords);
                        }
                        $newbasket->sendOrderConfirmation();
                        if (!empty($log)) file_put_contents($log, date("Y-m-d H:i:s") . " - Transaction accepted\r\n", FILE_APPEND);
                    } else {
                        http_response_code(400);
                        if (!empty($log)) file_put_contents($log, date("Y-m-d H:i:s") . " - Transaction cost_total != mc_gross: " . sprintf("%.2f", $newbasket->getTotalCost()) . " != " . sprintf("%.2f", $_REQUEST['mc_gross']) . "\r\n", FILE_APPEND);
                    }
                } else {
                    http_response_code(400);
                    if (!empty($log)) file_put_contents($log, date("Y-m-d H:i:s") . " - Transaction already processed\r\n", FILE_APPEND);
                }
            } else {
                // payment status other
                if (!empty($log)) file_put_contents($log, date("Y-m-d H:i:s") . " - Transaction verified but not completed\r\n", FILE_APPEND);
            }
        }
    }

    // close socket
    fclose($fp);
}
