<?php
class ControllerExtensionPaymentDivido extends Controller {
    const
        STATUS_ACCEPTED = 'ACCEPTED',
        STATUS_ACTION_LENDER = 'ACTION-LENDER',
        STATUS_CANCELED = 'CANCELED',
        STATUS_COMPLETED = 'COMPLETED',
        STATUS_DEPOSIT_PAID = 'DEPOSIT-PAID',
        STATUS_DECLINED = 'DECLINED',
        STATUS_DEFERRED = 'DEFERRED',
        STATUS_REFERRED = 'REFERRED',
        STATUS_FULFILLED = 'FULFILLED',
        STATUS_SIGNED = 'SIGNED';

    private $status_id = array(
        self::STATUS_ACCEPTED      => 1,
        self::STATUS_ACTION_LENDER => 2,
        self::STATUS_CANCELED      => 0,
        self::STATUS_COMPLETED     => 2,
        self::STATUS_DECLINED      => 8,
        self::STATUS_DEFERRED      => 1,
        self::STATUS_REFERRED      => 1,
        self::STATUS_DEPOSIT_PAID  => 1,
        self::STATUS_FULFILLED     => 1,
        self::STATUS_SIGNED        => 2,
    );
    private $history_messages = array(
        self::STATUS_ACCEPTED      => 'Credit request accepted',
        self::STATUS_ACTION_LENDER => 'Lender notified',
        self::STATUS_CANCELED      => 'Credit request canceled',
        self::STATUS_COMPLETED     => 'Credit application completed',
        self::STATUS_DECLINED      => 'Credit request declined',
        self::STATUS_DEFERRED      => 'Credit request deferred',
        self::STATUS_REFERRED      => 'Credit request referred',
        self::STATUS_DEPOSIT_PAID  => 'Deposit paid',
        self::STATUS_FULFILLED     => 'Credit request fulfilled',
        self::STATUS_SIGNED        => 'Contract signed',
    );

    public function index() {
        $this->load->language('extension/payment/divido');
        $this->load->model('extension/payment/divido');
        $this->load->model('checkout/order');

        $api_key = $this->config->get('divido_api_key');
        $key_parts = explode('.', $api_key);
        $js_key = strtolower(array_shift($key_parts));

        list($total, $totals) = $this->model_extension_payment_divido->getOrderTotals();

        $this->model_extension_payment_divido->setMerchant($this->config->get('divido_api_key'));

        $plans = $this->model_extension_payment_divido->getCartPlans($this->cart);
        foreach ($plans as $key => $plan) {
            $planMinTotal = $total - ($total * ($plan->min_deposit / 100));
            if ($plan->min_amount > $planMinTotal) {
                unset($plans[$key]);
            }
        }

        $plans_ids = array_map(function ($plan) {
            return $plan->id;
        }, $plans);
        $plans_ids = array_unique($plans_ids);
        $plans_list = implode(',', $plans_ids);

        $data = array(
            'button_confirm'           => $this->language->get('divido_checkout'),
            'text_loading'             => $this->language->get('text_loading'),
            'text_choose_deposit'      => $this->language->get('text_choose_deposit'),
            'text_choose_plan'         => $this->language->get('text_choose_plan'),
            'text_checkout_title'      => $this->language->get('text_checkout_title'),
            'text_monthly_payments'    => $this->language->get('text_monthly_payments'),
            'text_months'              => $this->language->get('text_months'),
            'text_term'                => $this->language->get('text_term'),
            'text_deposit'             => $this->language->get('text_deposit'),
            'text_credit_amount'       => $this->language->get('text_credit_amount'),
            'text_amount_payable'      => $this->language->get('text_amount_payable'),
            'text_total_interest'      => $this->language->get('text_total_interest'),
            'text_monthly_installment' => $this->language->get('text_monthly_installment'),
            'text_redirection'         => $this->language->get('text_redirection'),
            'merchant_script'          => "//cdn.divido.com/calculator/{$js_key}.js",
            'grand_total'              => $total,
            'plan_list'                => $plans_list,
            'generic_credit_req_error' => 'Credit request could not be initiated',
        );

        return $this->load->view('extension/payment/divido', $data);
    }

    public function update() {
        $this->load->language('extension/payment/divido');
        $this->load->model('extension/payment/divido');
        $this->load->model('checkout/order');

        $data = json_decode(file_get_contents('php://input'));

        if (!isset($data->status)) {
            $this->response->setOutput('');
            return;
        }

        $lookup = $this->model_extension_payment_divido->getLookupByOrderId($data->metadata->order_id);
        if ($lookup->num_rows != 1) {
            $this->response->setOutput('');
            return;
        }

        $hash = $this->model_extension_payment_divido->hashOrderId($data->metadata->order_id, $lookup->row['salt']);
        if ($hash !== $data->metadata->order_hash) {
            $this->response->setOutput('');
            return;
        }

        $order_id = $data->metadata->order_id;
        $order_info = $this->model_checkout_order->getOrder($order_id);
        $status_id = $order_info['order_status_id'];
        $message = "Status: {$data->status}";
        if (isset($this->history_messages[$data->status])) {
            $message = $this->history_messages[$data->status];
        }

        if ($data->status == self::STATUS_SIGNED) {
            $status_override = $this->config->get('divido_order_status_id');
            if (!empty($status_override)) {
                $this->status_id[self::STATUS_SIGNED] = $status_override;
            }
        }

        if (isset($this->status_id[$data->status]) && $this->status_id[$data->status] > $status_id) {
            $status_id = $this->status_id[$data->status];
        }

        if ($data->status == self::STATUS_DECLINED && $order_info['order_status_id'] == 0) {
            $status_id = 0;
        }

        $this->model_extension_payment_divido->saveLookup($data->metadata->order_id, $lookup->row['salt'], null, $data->application);
        $this->model_checkout_order->addOrderHistory($order_id, $status_id, $message, false);
        $this->response->setOutput('ok');
    }

    public function confirm() {
        $this->load->language('extension/payment/divido');

        $this->load->model('extension/payment/divido');

        ini_set('html_errors', 0);
        if (!$this->session->data['payment_method']['code'] == 'divido') {
            return false;
        }

        $this->model_extension_payment_divido->setMerchant($this->config->get('divido_api_key'));

        $api_key = $this->config->get('divido_api_key');

        $deposit = $this->request->post['deposit'];
        $finance = $this->request->post['finance'];

        $address = $this->session->data['payment_address'];
        if (isset($this->session->data['shipping_address'])) {
            $address = $this->session->data['shipping_address'];
        }

        $country = $address['iso_code_2'];
        $language = strtoupper($this->language->get('code'));
        $currency = strtoupper($this->session->data['currency']);
        $order_id = $this->session->data['order_id'];

        if ($this->customer->isLogged()) {
            $this->load->model('account/customer');
            $customer_info = $this->model_account_customer->getCustomer($this->customer->getId());

            $firstname = $customer_info['firstname'];
            $lastname = $customer_info['lastname'];
            $email = $customer_info['email'];
            $telephone = $customer_info['telephone'];
        } elseif (isset($this->session->data['guest'])) {
            $firstname = $this->session->data['guest']['firstname'];
            $lastname = $this->session->data['guest']['lastname'];
            $email = $this->session->data['guest']['email'];
            $telephone = $this->session->data['guest']['telephone'];
        }

        $postcode = $address['postcode'];

        $products = array();
        foreach ($this->cart->cartProducts as $product) {
            $products[] = array(
                'type'     => 'product',
                'text'     => $product['name'],
                'quantity' => $product['quantity'],
                'value'    => $product['price'],
            );
        }

        list($total, $totals) = $this->model_extension_payment_divido->getOrderTotals();

        $sub_total = $total;
        $cart_total = $this->cart->getSubTotal();
        $shiphandle = $sub_total - $cart_total;

        $products[] = array(
            'type'     => 'product',
            'text'     => 'Shipping & Handling',
            'quantity' => 1,
            'value'    => $shiphandle,
        );

        $deposit_amount = round(($deposit / 100) * $total, 2, PHP_ROUND_HALF_UP);

        $shop_url = $this->config->get('config_url');
        if (isset($this->request->server['HTTPS']) && (($this->request->server['HTTPS'] == 'on') || ($this->request->server['HTTPS'] == '1'))) {
            $shop_url = $this->config->get('config_ssl');
        }

        $callback_url = $this->url->link('extension/payment/divido/update', '', true);
        $return_url = $this->url->link('checkout/success', '', true);
        $checkout_url = $this->url->link('checkout/checkout', '', true);

        $salt = uniqid('', true);
        $hash = $this->model_extension_payment_divido->hashOrderId($order_id, $salt);

        $request_data = array(
            'merchant'     => $api_key,
            'deposit'      => $deposit_amount,
            'finance'      => $finance,
            'country'      => $country,
            'language'     => $language,
            'currency'     => $currency,
            'metadata'     => array(
                'order_id'   => $order_id,
                'order_hash' => $hash,
            ),
            'customer'     => array(
                'title'         => '',
                'first_name'    => $firstname,
                'middle_name'   => '',
                'last_name'     => $lastname,
                'country'       => $country,
                'postcode'      => $postcode,
                'email'         => $email,
                'mobile_number' => '',
                'phone_number'  => $telephone,
            ),
            'products'     => $products,
            'response_url' => $callback_url,
            'redirect_url' => $return_url,
            'checkout_url' => $checkout_url,
        );

        $response = Divido_CreditRequest::create($request_data);

        if ($response->status == 'ok') {

            $this->model_extension_payment_divido->saveLookup($order_id, $salt, $response->id, null, $deposit_amount);

            $data = array(
                'status' => 'ok',
                'url'    => $response->url,
            );
        } else {
            $data = array(
                'status'  => 'error',
                'message' => $this->language->get($response->error),
            );
        }

        $this->response->setOutput(json_encode($data));
    }

    public function calculator($args) {
        $this->load->language('extension/payment/divido');

        $this->load->model('extension/payment/divido');

        if (!$this->model_extension_payment_divido->isEnabled()) {
            return null;
        }

        $this->model_extension_payment_divido->setMerchant($this->config->get('divido_api_key'));

        $product_selection = $this->config->get('divido_productselection');
        $price_threshold = $this->config->get('divido_price_threshold');
        $product_id = $args['product_id'];
        $product_price = $args['price'];
        $type = $args['type'];

        if ($product_selection == 'threshold' && $product_price < $price_threshold) {
            return null;
        }

        $plans = $this->model_extension_payment_divido->getProductPlans($product_id);
        if (empty($plans)) {
            return null;
        }

        $plans_ids = array_map(function ($plan) {
            return $plan->id;
        }, $plans);

        $plan_list = implode(',', $plans_ids);

        $data = array(
            'planList'                 => $plan_list,
            'productPrice'             => $product_price,
            'text_loading'             => $this->language->get('text_loading'),
            'text_choose_deposit'      => $this->language->get('text_choose_deposit'),
            'text_choose_plan'         => $this->language->get('text_choose_plan'),
            'text_checkout_title'      => $this->language->get('text_checkout_title'),
            'text_monthly_payments'    => $this->language->get('text_monthly_payments'),
            'text_months'              => $this->language->get('text_months'),
            'text_term'                => $this->language->get('text_term'),
            'text_deposit'             => $this->language->get('text_deposit'),
            'text_credit_amount'       => $this->language->get('text_credit_amount'),
            'text_amount_payable'      => $this->language->get('text_amount_payable'),
            'text_total_interest'      => $this->language->get('text_total_interest'),
            'text_monthly_installment' => $this->language->get('text_monthly_installment'),
        );

        $filename = ($type == 'full') ? 'extension/payment/divido_calculator' : 'extension/payment/divido_widget';

        return $this->load->view($filename, $data);
    }

}