<?php
/**
 * 2013 - 2018 PayPlug SAS
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to http://www.prestashop.com for more information.
 *
 *  @author    PayPlug SAS
 *  @copyright 2013 - 2018 PayPlug SAS
 *  @license   http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 *  International Registered Trademark & Property of PayPlug SAS
 */

//Inclusions
require_once(dirname(__FILE__).'/../../../../config/config.inc.php');
require_once(_PS_MODULE_DIR_.'../init.php');
require_once(_PS_MODULE_DIR_.'payplug/payplug.php');
require_once(_PS_MODULE_DIR_.'payplug/classes/PayplugBackward.php');
require_once(_PS_MODULE_DIR_.'payplug/classes/PayplugLock.php');
require_once(_PS_MODULE_DIR_.'payplug/lib/init.php');


//Settings
$debug = PayplugBackward::getConfiguration('PAYPLUG_DEBUG_MODE');

if ($debug) {
    require_once(dirname(__FILE__).'/../../classes/MyLogPHP.class.php');
    $log = new MyLogPHP(_PS_MODULE_DIR_.'payplug/log/validation-'.date("Y-m-d").'.csv');
    $log->info('Validation Starting.');
} else {
    $log = false;
}
addLog($debug, $log, 'validation_1_4', 'debug');
$payplug = new Payplug();

$redirect_url_error = 'index.php?controller=order&step=1';
if (version_compare(_PS_VERSION_, '1.5', '<')) {
    $order_confirmation_url = 'order-confirmation.php?';
} else {
    $order_confirmation_url = 'index.php?controller=order-confirmation&';
}


//Cancelling
/*
if (!$payplug->active) {
    addLog($debug, $log, 'Payplug module is not enabled.', 'error');
    Payplug::redirectForVersion($redirect_url_error);
} elseif (!($cart_id = Tools::getValue('cartid'))) {
*/
if (!($cart_id = Tools::getValue('cartid'))) {
    addLog($debug, $log, 'No Cart ID.', 'error');
    Payplug::redirectForVersion($redirect_url_error);
} elseif (!($ps = Tools::getValue('ps')) || $ps != 1) {
    if ($ps == 2) {
        addLog($debug, $log, 'Order has been cancelled on PayPlug page', 'info');
    } else {
        addLog($debug, $log, 'Wrong GET parameter ps = '.$ps, 'error');
    }
    Payplug::redirectForVersion($redirect_url_error);
}


//Treatment
addLog($debug, $log, 'Cart ID : '.(int)$cart_id, 'info');
$cart = new Cart((int)$cart_id);
if (!Validate::isloadedObject($cart)) {
    addLog($debug, $log, 'Cart cannot be loaded.', 'error');
    Payplug::redirectForVersion($redirect_url_error);
} else {
    if (!$pay_id = $payplug->getPaymentByCart((int)$cart_id)) {
        addLog($debug, $log, 'Payment is not stored or is already consumed.', 'error');
        $id_order = Order::getOrderByCartId($cart->id);
        $customer = new Customer((int)$cart->id_customer);
        $link_redirect = __PS_BASE_URI__.$order_confirmation_url.'id_cart='.$cart->id
            .'&id_module='.$payplug->id.'&id_order='.$id_order.'&key='.$customer->secure_key;
        Payplug::redirectForVersion($link_redirect);
    } else {
        addLog($debug, $log, 'Payment is not consumed yet.', 'info');
        try {
            $payment = \Payplug\Payment::retrieve($pay_id);
            addLog($debug, $log, 'Retrieving payment...', 'info');
            if ($payment->failure) {
                addLog($debug, $log, 'Payment failure : '.$payment->failure->message, 'error');
                Payplug::redirectForVersion($redirect_url_error);
            }
            $is_paid = $payment->is_paid;
        } catch (Exception $e) {
            addLog($debug, $log, 'Payment cannot be retrieved.', 'error');
            Payplug::redirectForVersion($redirect_url_error);
        }
    }

    if ($payment->save_card == 1 || ($payment->card->id != '' && $payment->hosted_payment != '')) {
        addLog($debug, $log, 'Saving card...', 'info');
        $res_payplug_card = $payplug->saveCard($payment);

        if (!$res_payplug_card) {
            addLog($debug, $log, 'Card cannot be saved.', 'error');
        }
    }

    $customer = new Customer((int)$cart->id_customer);
    if (!Validate::isLoadedObject($customer)) {
        addLog($debug, $log, 'Customer cannot be loaded.', 'error');
        Payplug::redirectForVersion($redirect_url_error);
    }

    if (version_compare(_PS_VERSION_, 1.4, '<')) {
        $total = (float)$cart->getOrderTotal(true, 3);
    } else {
        $total = (float)$cart->getOrderTotal(true, Cart::BOTH);
    }
    addLog($debug, $log, 'Total : '.$total, 'info');

    addLog($debug, $log, 'Lock checking start.', 'debug');
    PayplugLock::check($cart->id);
    addLog($debug, $log, 'Lock checking end.', 'debug');

    $cart_lock = PayplugLock::createLockG2($cart->id, 'validation');
    if (!$cart_lock) {
        addLog($debug, $log, 'Lock cannot be created.', 'error');
    } else {
        addLog($debug, $log, 'Lock created.', 'debug');
        switch ($cart_lock) {
            case 'ipn':
            case 'validation':
                $id_order = false;
                break;
            default:
                $id_order = (int)$cart_lock;
        }
    }

    $id_order = Order::getOrderByCartId($cart->id);

    if ($id_order) {
        addLog($debug, $log, 'Order already exists.', 'info');
        addLog($debug, $log, 'Deleting stored payment.', 'info');

        if ($payplug->isTransactionPending((int)$cart_id)) {
            addLog($debug, $log, 'Transaction is pending so stored payment will not be deleted.', 'info');
        } else {
            if (!$payplug->deletePayment($payment->id, (int)$cart_id)) {
                addLog($debug, $log, 'Stored payment cannot be deleted.', 'error');
            } else {
                addLog($debug, $log, 'Stored payment successfully deleted.', 'info');
            }
        }
    } else {
        addLog($debug, $log, 'Order does\'nt exists yet.', 'info');

        $state_addons = ($payment->is_live ? '' : '_TEST');
        $pending_state = (int)PayplugBackward::getConfiguration('PAYPLUG_ORDER_STATE_PENDING'.$state_addons);
        $paid_state = (int)PayplugBackward::getConfiguration('PAYPLUG_ORDER_STATE_PAID'.$state_addons);
        $error_state = (int)PayplugBackward::getConfiguration('PAYPLUG_ORDER_STATE_ERROR'.$state_addons);
        if ($is_paid) {
            $order_state = $paid_state;
            addLog($debug, $log, 'Deleting stored payment.', 'info');
            if (!$payplug->deletePayment($payment->id, (int)$cart_id)) {
                addLog($debug, $log, 'Stored payment cannot be deleted.', 'error');
            } else {
                addLog($debug, $log, 'Stored payment successfully deleted.', 'info');
            }
        } else {
            $order_state = $pending_state;
            addLog($debug, $log, 'Stored payment become pending.', 'info');
            if (!$payplug->registerPendingTransaction((int)$cart_id)) {
                addLog($debug, $log, 'Stored payment cannot be pending.', 'error');
            } else {
                addLog($debug, $log, 'Stored payment successfully set up yo pending.', 'info');
            }
        }
        addLog($debug, $log, 'Order state will be :'.$order_state, 'info');

        $extra_vars = array(
            'transaction_id' => $payment->id
        );

        /* 
         * For some reasons, secure key form cart can differ from secure key from customer
         * Maybe due to migration or Prestashop's Update
         */
        $secure_key = false;
        if (isset($customer->secure_key) && !empty($customer->secure_key)) {
            if (isset($cart->secure_key) && !empty($cart->secure_key) && $cart->secure_key !== $customer->secure_key) {
                $secure_key = $cart->secure_key;
                $this->addLog($debug, $log, 'Secure keys do not match.', 'error');
                $this->addLog($debug, $log, 'Customer Secure Key: '.$customer->secure_key, 'error');
                $this->addLog($debug, $log, 'Cart Secure Key: '.$cart->secure_key, 'error');
            } else {
                $secure_key = $customer->secure_key;
            }
        }
        $validateOrder_result = $payplug->validateOrder(
            $cart->id,
            $order_state,
            $total,
            $payplug->displayName,
            false,
            $extra_vars,
            (int)$cart->id_currency,
            false,
            $secure_key
        );
        $id_order = $payplug->currentOrder;

        if (!$validateOrder_result) {
            addLog($debug, $log, 'Order not validated', 'error');
            $cart_unlock = PayplugLock::deleteLockG2($cart->id);
            if (!$cart_unlock) {
                addLog($debug, $log, 'Lock cannot be deleted.', 'error');
            } else {
                addLog($debug, $log, 'Lock deleted.', 'debug');
            }
            Payplug::redirectForVersion($redirect_url_error);
        } else {
            addLog($debug, $log, 'Order validated', 'info');
            $api_key = Payplug::setAPIKey();
            $data = array();
            $data['metadata'] = $payment->metadata;
            $data['metadata']['Order'] = $id_order;
            $payplug->patchPayment($api_key, $payment->id, $data);
        }

        if (version_compare(_PS_VERSION_, '1.5', '<')) {
            if (!$payplug->addPayplugOrderPayment($id_order, $payment->id)) {
                addLog($debug, $log, 'Unable to create order payment.', 'error');
            }
        }

        addLog($debug, $log, 'Checking number of order passed with this id_cart...', 'info');
        $req_nb_orders = '
            SELECT o.* 
            FROM '._DB_PREFIX_.'orders o 
            WHERE o.id_cart = '.$cart->id;
        $res_nb_orders = Db::getInstance()->executeS($req_nb_orders);
        if (!$res_nb_orders) {
            addLog($debug, $log, 'No order can be found using id_cart '.(int)$cart->id, 'error');
            $cart_unlock = PayplugLock::deleteLockG2($cart->id);
            if (!$cart_unlock) {
                addLog($debug, $log, 'Lock cannot be deleted.', 'error');
            } else {
                addLog($debug, $log, 'Lock deleted.', 'debug');
            }
            Payplug::redirectForVersion($redirect_url_error);
        } elseif (count($res_nb_orders) > 1) {
            addLog($debug, $log, 'There is more than one order using id_cart '.(int)$cart->id, 'error');
            foreach ($res_nb_orders as $o) {
                addLog($debug, $log, 'Order ID : '.$o['id_order'], 'debug');
            }
        } else {
            addLog($debug, $log, 'Everything looks good.', 'info');
        }

        addLog($debug, $log, 'Checking number of transaction validated for this order...', 'info');
        if (version_compare(_PS_VERSION_, '1.5', '<')) {
            $req_order_payment = '
                SELECT pop.* 
                FROM '._DB_PREFIX_.'payplug_order_payment pop  
                WHERE pop.id_order = '.(int)$id_order;
            $payments = Db::getInstance()->executeS($req_order_payment);
        } else {
            $order = new Order((int)$id_order);
            $payments = $order->getOrderPaymentCollection();
        }
        if (!$payments) {
            addLog($debug, $log, 'No transaction can be found using id_order '.(int)$id_order, 'error');
            $cart_unlock = PayplugLock::deleteLockG2($cart->id);
            if (!$cart_unlock) {
                addLog($debug, $log, 'Lock cannot be deleted.', 'error');
            } else {
                addLog($debug, $log, 'Lock deleted.', 'debug');
            }
            Payplug::redirectForVersion($redirect_url_error);
        } elseif (count($payments) > 1) {
            addLog($debug, $log, 'There is more than one transaction using id_order '.(int)$id_order, 'error');
        } else {
            addLog($debug, $log, 'Everything looks good.', 'info');
        }
    }

    $cart_unlock = PayplugLock::deleteLockG2($cart->id);
    if (!$cart_unlock) {
        addLog($debug, $log, 'Lock cannot be deleted.', 'error');
    } else {
        addLog($debug, $log, 'Lock deleted.', 'debug');
    }

    $link_redirect = __PS_BASE_URI__.$order_confirmation_url.'id_cart='.$cart->id.'&id_module='.$payplug->id
        .'&id_order='.$id_order.'&key='.$customer->secure_key;
    addLog($debug, $log, 'Redirecting to :'.$link_redirect, 'info');
    Payplug::redirectForVersion($link_redirect);
}

function addLog($debug, $log, $str, $level)
{
    $debugBacktrace = debug_backtrace();
    $line_n = $debugBacktrace[0]['line'];
    if ($debug) {
        $log->$level($str, '--', $line_n);
    }
    return($str);
}
