<?php

namespace Salesloo;

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

use WP_Error;
use Salesloo\Models\Invoice;

/**
 * Renew classes
 */
class Renew
{
    private $data;

    private static $instance =  null;

    public $unique_number = null;

    /**
     * Instance.
     *
     * Ensures only one instance of the renew class is loaded or can be loaded.
     *
     * @since 1.0.0
     * @access public
     */
    public static function instance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * set_order_id
     *
     * @param  string $order_id
     * @return void
     */
    public function prepare($order_id)
    {
        $order = Models\Order::query('WHERE ID = %d', $order_id)->first();

        $data = [
            'order_id'   => $order->ID,
            'order_code' => $order->code,
            'user_id'    => $order->user_id,
            'product_id' => $order->product_id,
            'status'     => $order->status,
            'expired_at' => $order->expired_at,
            'created_at' => $order->created_at,
            'updated_at' => $order->updated_at,
        ];

        salesloo_update_order_meta($order->ID, 'unique_number', '');
        $this->data = wp_parse_args($order->meta(), $data);
        self::$instance = $this;
    }

    public function invoice_exists()
    {
        $invoice = Invoice::select([
            'salesloo_invoice.*',
            'salesloo_invoice_order.order_id'
        ])
            ->leftJoin('salesloo_invoice_order', ['salesloo_invoice.ID', 'salesloo_invoice_order.invoice_id'])
            ->query('WHERE order_id = %d AND status = %s', $this->order_id, 'unpaid')
            ->first();

        return $invoice->ID > 0 ? $invoice->ID : 0;
    }

    /**
     * getter
     *
     * @param  string $name
     * @return mixed
     */
    public function __get($name)
    {
        if (array_key_exists($name, $this->data))
            return maybe_unserialize($this->data[$name]);

        return NULL;
    }

    /**
     * get_item
     *
     * @return mixed
     */
    public function get_items()
    {
        $products = Models\Product::query('WHERE ID = %d', $this->product_id)->get();
        return $products;
    }

    public function get_price()
    {
        return salesloo_convert_price($this->renew_price);
    }

    /**
     * choose_payment_method
     *
     * @param  string $method_name
     * @param  mixed $checkout_id
     * @return mixed
     */
    public function choose_payment_method($method_name, $checkout_id = false)
    {
        if (false === $checkout_id) {
            $checkout_id = $this->ID;
        }

        $payment_method = Plugin::instance()->payment_method->get($method_name);

        $updated = salesloo_update_order_meta($this->order_id, 'payment_method', $payment_method->get_id());

        return $updated;
    }

    /**
     * summary
     *
     * @return array
     */
    public function summary()
    {
        $items = [];
        $subtotal = 0;
        $additional_calculations = [];
        $payment_method = null;

        if ($this->payment_method) {
            $payment_method = Plugin::instance()->payment_method->get($this->payment_method);
        }

        foreach ($this->get_items() as $product) {

            $product_price = $this->get_price();

            $items[$product->ID] = [
                'label' => $product->title,
                'value' => salesloo_convert_price($product_price),
                'print' => salesloo_convert_money($product_price),
                'price' => [
                    'value' => salesloo_convert_price($product_price),
                    'print' => salesloo_convert_money($product_price)
                ],
                'duration' => salesloo_translate_product_duration($product->duration)
            ];

            $subtotal = $subtotal + floatval($product_price);
        }

        $subtotal = salesloo_convert_price($subtotal);

        if ($payment_method && $payment_method->use_unique_number()) {
            if (!$this->unique_number) {
                $this->unique_number = salesloo_generate_unique_number();
                salesloo_update_order_meta($this->order_id, 'unique_number', $this->unique_number);
            }

            $unique_number = salesloo_convert_price($this->unique_number);
            $additional_calculations['unique']  = [
                'label'     => salesloo_get_option('unique_number_label'),
                'value'     => $unique_number,
                'print'     => salesloo_get_option('unique_number_operation') . salesloo_convert_money($unique_number),
                'message'   => '',
                'operation' => salesloo_get_option('unique_number_operation')
            ];
        }

        $first_item = reset($items);

        $summary = [
            'products' => $items,
            'subtotal' => [
                'label'   => $first_item['label'],
                'value'   => $subtotal,
                'print'   => salesloo_convert_money($subtotal),
                'message' => $first_item['duration']
            ]
        ];

        $additional_calculations = apply_filters('salesloo/summary', $additional_calculations, $this);

        $total = $subtotal;
        foreach ($additional_calculations as $key => $val) {
            if ($val['operation'] == '+') {
                $total = $total + salesloo_convert_price($val['value']);
            } else {
                $minus = salesloo_convert_price($val['value']);
                if ($total >= $minus) {
                    $total = $total - salesloo_convert_price($val['value']);
                } else {
                    unset($additional_calculations[$key]);
                }
            }
        }

        $total_message = '';
        $converted = false;
        $default_currency = salesloo_get_option('currency');
        if ($payment_method && $default_currency != $payment_method->get_currency()) {
            $total_message = sprintf(
                __('%s Converted to %s with rate %s/%s 1'),
                salesloo_convert_money($total),
                $payment_method->get_currency(),
                $payment_method->get_currency_rate(),
                $default_currency
            );

            $rate = str_replace(',', '.', $payment_method->get_currency_rate());
            $rate = floatval($rate);

            $converted_total = $total * $rate;

            $converted = [
                'value'    => salesloo_convert_price($converted_total),
                'print'    => salesloo_convert_money($converted_total, $payment_method->get_currency_symbol()),
                'currency' => $payment_method->get_currency_symbol()
            ];
        }

        $total = salesloo_convert_price($total);

        $summary = wp_parse_args($additional_calculations, $summary);

        $summary['total'] = [
            'label'     => __('Total', 'salesloo'),
            'value'     => $total,
            'print'     => salesloo_convert_money($total),
            'message'   => $total_message,
            'converted' => $converted
        ];

        return $summary;
    }

    public function order()
    {
        global $___salesloo;

        if ('POST' != $_SERVER['REQUEST_METHOD']) return;
        if (!isset($_POST['__nonce']) || !isset($_POST['_wp_http_referer'])) return;

        if (strpos($_POST['_wp_http_referer'], '/renew/') === false) return;
        if (wp_verify_nonce($_POST['__nonce'], 'salesloo-checkout')) {

            if (NULL == $this->payment_method) {
                return $___salesloo['warning'] = __('Please choose payment method', 'salesloo');
            }

            $user_id = get_current_user_id();

            do_action('salesloo/renew/before', $this->order_id, $user_id);

            $summary = $this->summary();

            $invoice_args = [
                'number'         => '',
                'user_id'        => $user_id,
                'summary'        => $summary,
                'total'          => floatval($summary['total']['value']),
                'payment_method' => $this->payment_method,
                'type' => 'renew_order',
                'status'         => 'unpaid',
                'due_date_at'    => salesloo_set_invoice_due_date(),
            ];

            $invoice_id = salesloo_insert_invoice($invoice_args);

            if (is_wp_error($invoice_id)) {
                return $___salesloo['warning'] = $invoice_id->get_error_message();
            }

            do_action('salesloo/insert/invoice/after', $invoice_id);

            $items = $summary['products'];

            $update_invoice_args = [
                'ID' => $invoice_id,
                'number' => salesloo_generate_invoice_format($invoice_id),
                'orders' => [$this->order_id]
            ];

            salesloo_update_invoice($update_invoice_args);

            $customer = get_userdata($user_id);
            $encoded_invoice_id = salesloo_encrypt($invoice_id);

            unset($summary['products']);

            $data = [
                'invoice_id'     => $invoice_id,
                'number'         => $invoice_args['number'],
                'payment_method' => $this->payment_method,
                'products'       => $items,
                'summary'        => $summary,
                'due_date'       => $invoice_args['due_date_at'],
                'customer_name'  => salesloo_user_get_name($customer),
                'customer_email' => $customer->user_email,
                'status'         => 'unpaid',
                'payment_url'    => salesloo_url_payment($encoded_invoice_id),
                'invoice_url'    => admin_url('admin.php?page=salesloo-payment')
            ];

            salesloo_add_notification('renew_order', $data);
            salesloo_add_event('renew_order', $data);

            wp_redirect(salesloo_url_payment($encoded_invoice_id));
            exit;
        }
    }

    public function get_warning()
    {
        global $___salesloo;

        if (isset($___salesloo['warning']) && $___salesloo['warning']) {
            $warning = sanitize_text_field($___salesloo['warning']);
            $warning = str_replace('\r', '', $warning);
            $warning = str_replace('\n', '', $warning);
            return $warning;
        }

        return false;
    }
}
