<?php


/**
 * insert order function
 */
function salesloo_insert_order($data = [])
{
    $data = apply_filters('salelsoo/order/insert/data', $data);

    if (empty($data) || !is_array($data)) return false;

    $order_args = [
        'status' => 'inactive'
    ];

    foreach (Salesloo\Models\Order::get_columns() as $key => $type) {

        if (isset($data[$key])) {
            $order_args[$key] = $data[$key];
        }
    }

    $order_id = Salesloo\Models\Order::data($order_args)->create();

    if (is_wp_error($order_id)) {
        return $order_id;
    }

    salesloo_insert_order_log($order_id, 'Order Created');

    return $order_id;
}


/**
 * update order
 *
 * @param  array $data
 * @return mixed
 */
function salesloo_update_order($data = [])
{
    $data = apply_filters('salelsoo/order/update/data', $data);

    if (empty($data) || !is_array($data)) return false;

    $order_id = isset($data['ID']) ? intval($data['ID']) : 0;
    $order = salesloo_get_order($order_id);

    $order_args = [];
    foreach (Salesloo\Models\Order::get_columns() as $key => $type) {

        if ('ID' == $key) continue;

        if (isset($data[$key])) {
            $order_args[$key] = $data[$key];
        }
    }

    if (false === $order) {
        return salesloo_insert_order($order_args);
    }

    $updated = Salesloo\Models\Order::data($order_args)->update([
        'ID' => $order_id,
    ]);

    return $updated;
}

/**
 *delete order
 *
 * @param  mixed $order
 * @return mixed
 */
function salesloo_delete_order($order)
{

    $order = salesloo_get_order($order);

    if (false === $order) return $order;

    $deleted = Salesloo\Models\Order::delete(['invoice_id' => $order->invoice_id]);
    if ($deleted) {
        Salesloo\Models\Invoice::delete(['ID' => $order->invoice_id]);
        Salesloo\Models\Order_Log::delete(['order_id' => $order->ID]);
    }
    return $deleted;
}

/**
 * get single order
 *
 * @param  mixed $order
 * @return mixed
 */
function salesloo_get_order($order = null)
{

    if (is_object($order) && isset($order->ID)) :
        $order_id = intval($order->ID);
    elseif (is_array($order) && isset($order['ID'])) :
        $order_id = intval($order['ID']);
    elseif (is_int($order) || is_string($order)) :
        $order_id = intval($order);
    else :
        return false;
    endif;

    $order = Salesloo\Models\Order::query('WHERE ID = %d', $order_id)->first();

    return $order->ID > 0 ? $order : false;
}

function salesloo_add_order_meta($order_id, $meta_key, $meta_value, $unique = false)
{

    if (!is_numeric($order_id) || !$meta_key || !$meta_value) {
        return false;
    }

    if ($unique == true) {
        $meta = Salesloo\Models\Order_Meta::query('WHERE order_id = %d AND meta_key = %s', $order_id, $meta_key)->get();

        if ($meta->meta_id > 0) {
            return false;
        }
    }

    $args = [
        'order_id' => intval($order_id),
        'meta_key'   => wp_unslash($meta_key),
        'meta_value' => wp_unslash($meta_value)
    ];

    $order_meta_id = Salesloo\Models\Order_Meta::data($args)->create();

    return $order_meta_id;
}


function salesloo_update_order_meta($order_id, $meta_key, $meta_value)
{

    if (!is_numeric($order_id) || !$meta_key) {
        return false;
    }

    $args = [
        'order_id' => intval($order_id),
        'meta_key'   => wp_unslash($meta_key),
        'meta_value' => maybe_serialize($meta_value)
    ];

    /**
     * check if meta key is exists
     */
    $check_meta = Salesloo\Models\Order_Meta::query('WHERE order_id = %d AND meta_key = %s', $order_id, $meta_key)->first();

    /**
     * update if meta key exists otherwise insert new one.
     */
    if ($check_meta->meta_id > 0) {

        Salesloo\Models\Order_Meta::data($args)->update([
            'meta_id' => $check_meta->meta_id
        ]);
        $meta_id = $check_meta->meta_id;
    } else {
        $meta_id = Salesloo\Models\Order_Meta::data($args)->create();
    }

    return $meta_id;
}


function salesloo_delete_order_meta($order_id, $meta_key, $meta_value = '')
{
    if (!is_numeric($order_id) || !$meta_key) {
        return false;
    }

    $args = [
        'order_id' => intval($order_id),
        'meta_key' => wp_unslash($meta_key)
    ];

    if ($meta_value) {
        $args['meta_value'] = wp_unslash($meta_value);
    }

    return Salesloo\Models\Order_Meta::delete($args);
}

function salesloo_get_order_meta($order_id, $meta_key, $single = false)
{
    if (!is_numeric($order_id) || !$meta_key) {
        return false;
    }


    /**
     * check if meta key is exists
     */
    $query = Salesloo\Models\Order_Meta::query('WHERE order_id = %d AND meta_key = %s', $order_id, $meta_key);

    if ($single === false) {
        $meta = [];

        $all_meta = $query->get();
        if ($all_meta) {
            foreach ($all_meta as $key => $value) {
                $meta[] = maybe_unserialize($value->meta_value);
            }
        }

        return $meta;
    } else {

        $single_meta = $query->first();

        if ($single_meta)
            return maybe_unserialize($single_meta->meta_value);
    }

    return false;
}

function salesloo_insert_order_log($order_id, $note)
{

    $args = [
        'order_id'  => intval($order_id),
        'note'    => wp_kses_post($note),
    ];

    $log_id = Salesloo\Models\Order_Log::data($args)->create();

    return $log_id;
}


function salesloo_generate_order_code()
{
    $code = '';
    $loop = true;

    while ($loop == true) {
        $code = substr(base_convert(sha1(uniqid(microtime(true))), 16, 36), 0, 30);
        $check = Salesloo\Models\Order::query('WHERE code = %s', $code)->first();

        if ($check->ID <= 0) {
            $loop = false;
        }
    }

    return strtoupper($code);
}

function salesloo_get_order_statuses($status = false)
{
    $statuses = [
        'inactive' => __('Inactive', 'salesloo'),
        'active'   => __('Active', 'salesloo'),
        'expired'  => __('Expired', 'salesloo'),
    ];

    $statuses = apply_filters('salesloo/order/statuses', $statuses, $status);

    if ($status) {
        return isset($statuses[$status]) ? $statuses[$status] : false;
    }

    return $statuses;
}

/**
 * change order status
 *
 * @param  mixed $order
 * @param  string $new_status
 * @return mixed
 */
function salesloo_update_order_status($order, $status)
{
    $status = strtolower($status);
    $is_status_exists = salesloo_get_order_statuses($status);
    if (false === $is_status_exists) {
        return new WP_Error('error', __('Invalid order status', 'salesloo'));
    }

    $order = salesloo_get_order($order);
    if (false === $order) {
        return new WP_Error('error', __('Invalid order', 'salesloo'));
    }

    if ($status == $order->status) {
        return new WP_Error('error', __('Status same', 'salesloo'));
    }

    $updated = Salesloo\Models\Order::data(['status' => $status, 'updated_at' => date('Y-m-d H:i:s')])
        ->update([
            'ID' => $order->ID,
        ]);

    return $updated;
}

function salesloo_update_order_access($order_id)
{
    $order = salesloo_get_order($order_id);
    if ($order) {
        $product = salesloo_get_product($order->product_id);
        $items = $product->items;

        $renew_price = salesloo_convert_price($product->get_price('renew'));
        salesloo_update_order_meta($order_id, 'renew_price', $renew_price);

        $accesses = \Salesloo\Models\Access::query('WHERE order_id = %d', $order->ID)->get();
        if ($accesses->found() > 0) {
            foreach ($accesses as $acc) {
                if (!in_array($acc->item_id, $items)) {
                    salesloo_delete_access($acc->ID);
                    do_action('salesloo/delete/access', $acc->ID, $order_id, $acc->item_id);
                }
            }
        }

        foreach ($items as $key => $item_id) {

            $item = get_post($item_id);
            if (!$item) continue;

            $access_args = [
                'order_id' => $order->ID,
                'item_id' => $item_id
            ];

            $access = \Salesloo\Models\Access::query('WHERE order_id = %d AND item_id = %d', $order->ID, $item->ID)->first();

            if ($access->ID == false) {
                $access_id = salesloo_insert_access($access_args);
                do_action('salesloo/insert/access', $access_id, $order_id, $item_id);
            } else {
                do_action('salesloo/update/access', $access->ID, $order_id, $item_id);
            }
        }

        return $order;
    }

    return new WP_Error('error', __('Invalid order id'));
}


/**
 * get order statistics
 *
 * @param  mixed $filter
 * @return mixed
 */
function salesloo_get_order_statistics($filter = [])
{
    $invoice_status = array_keys(salesloo_get_invoice_statuses());
    $invoice_status = implode('\',\'', $invoice_status);

    $select_leads_case = "CASE WHEN {prefix}salesloo_invoice.status IN ('$invoice_status')";
    $select_sales_case = "CASE WHEN {prefix}salesloo_invoice.status IN ('completed')";
    $select_refund_case = "CASE WHEN {prefix}salesloo_invoice.status IN ('refunded')";
    $select_cancel_case = "CASE WHEN {prefix}salesloo_invoice.status IN ('cancelled')";

    if (isset($filter['products'])) {
        $products = is_array($filter['products']) ? implode('\',\'', array_map('sanitize_text_field', $filter['products'])) : sanitize_text_field($filter['products']);

        $select_leads_case .= " AND {prefix}salesloo_order.product_id IN ('$products')";
        $select_sales_case .= " AND {prefix}salesloo_order.product_id IN ('$products')";
        $select_refund_case .= " AND {prefix}salesloo_order.product_id IN ('$products')";
        $select_cancel_case .= " AND {prefix}salesloo_order.product_id IN ('$products')";
    }

    if (isset($filter['daterange'])) {
        $date = salesloo_split_daterange($filter['daterange']);

        $select_leads_case .= " AND created_at >= '$date->from'";
        $select_leads_case .= " AND created_at <= '$date->to'";

        $select_sales_case .= " AND created_at >= '$date->from'";
        $select_sales_case .= " AND created_at <= '$date->to'";

        $select_refund_case .= " AND created_at >= '$date->from'";
        $select_refund_case .= " AND created_at <= '$date->to'";

        $select_cancel_case .= " AND created_at >= '$date->from'";
        $select_cancel_case .= " AND created_at <= '$date->to'";
    }

    $order = Salesloo\Models\Order::leftJoin(
        'salesloo_invoice_order',
        [
            'salesloo_order.ID',
            'salesloo_invoice_order.order_id',
            '='
        ]
    )
        ->leftJoin(
            'salesloo_invoice',
            [
                'salesloo_invoice_order.invoice_id',
                'salesloo_invoice.ID',
                '='
            ]
        )
        ->select(
            "COUNT($select_leads_case THEN 1 ELSE NULL END) AS leads",
            "COUNT($select_sales_case THEN 1 ELSE NULL END) AS sales",
            "COUNT($select_refund_case THEN 1 ELSE NULL END) AS refund",
            "COUNT($select_cancel_case THEN 1 ELSE NULL END) AS cancel",
            "SUM($select_sales_case THEN {prefix}salesloo_invoice.total ELSE 0 END) AS order_total",
            "SUM($select_refund_case THEN {prefix}salesloo_invoice.total ELSE 0 END) AS order_refund"
        );

    $result = $order->result();

    return $result[0];
}


/**
 * salesloo_get_current_order_id
 *
 * @return mixed
 */
function salesloo_get_current_order_id()
{
    $vars = salesloo_vars();

    if (!isset($vars['__order'])) {
        return false;
    }

    $encoded_order_id = sanitize_text_field($vars['__order']);
    $order_id = salesloo_decrypt($encoded_order_id);

    if (empty($order_id)) {
        $order_id = $encoded_order_id;
    }

    return $order_id;
}


function salesloo_order_is_renewed($order)
{
    $order = salesloo_get_order($order);

    $renew = false;

    if ($order->status == 'expired') {
        $encoded_order_id = salesloo_encrypt($order->ID);
        $renew = salesloo_url_renew($encoded_order_id);
    }

    $expired_at = empty($order->expired_at) || date('Y-m-d', strtotime($order->expired_at)) == '1970-01-01' ? '~' : date('Y-m-d H:00', strtotime($order->expired_at));

    if ($expired_at != '~' && $order->status == 'active') {
        $expired = strtotime($order->expired_at);
        $last_date = strtotime('+ 7 days');
        if ($expired < $last_date) {
            $encoded_order_id = salesloo_encrypt($order->ID);
            $renew = salesloo_url_renew($encoded_order_id);
        }
    }

    return $renew;
}
