<?php
if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * Anbaarak | Best Inventory management plugin for WooCommerce.
 * All rights reserved for WP LEGEND team (wplegend.ir)
 */


use Anbarak\Input;
use Anbarak\Tables;
use Anbarak\ProductsInfo;
use Anbarak\VersionChecker;

/**
 * get current version
 */
function anbarak_get_db_version()
{
    return get_option('anbarak_version');
}



function anbarak_get_template_part($slug, $args = [])
{
    if (!empty($args)) {
        extract($args);
    }

    require ANBARAK_PATH . "admin/views/partials/{$slug}.php";
}

/**
 * Get an option from the database with autoload default false
 *
 * @param string $option_name The option name to retrieve
 * @param mixed $default_value Default value if option doesn't exist
 * @return mixed The option value or default value
 */
function anbarak_get_option($option_name, $default_value = null)
{
    $value = get_option('anbarak_' . $option_name, $default_value);
    return $value;
}

/**
 * Update an option in the database with autoload default false
 *
 * @param string $option_name The option name to update
 * @param mixed $option_value The value to save
 * @param bool $autoload Whether to load this option on every page load (default: false)
 * @return bool True if option value changed, false if not or if update failed
 */
function anbarak_update_option($option_name, $option_value, $autoload = false)
{

    $option_name = 'anbarak_' . $option_name;
    $existing_value = get_option($option_name, null);

    if ($existing_value === null) {
        return add_option($option_name, $option_value, '', $autoload);
    } else {
        return update_option($option_name, $option_value, $autoload);
    }
}


function anbarak_get_order_default_country()
{
    $setting = anbarak_get_option('country_selector_mode', 'default');
    if ($setting === 'dropdown') {
        return '';
    }
    $default = wc_get_base_location()['country'];
    return $default ?: 'IR';
}

function anbarak_wc_provinces($country = '')
{
    if ($country === '') {
        $country = anbarak_get_order_default_country();
    }
    if (empty($country)) {
        return [];
    }
    return WC()->countries->get_states($country);
}

/**
 * Normalizes a phone number for storage.
 *
 * The helper converts localized digits to English, strips separators, and
 * returns a compact phone string suitable for storage and lookups.
 *
 * International numbers are kept in digit-only form. Iranian mobile numbers
 * keep the legacy `09xxxxxxxxx` shape for backward compatibility.
 *
 * @param string $phoneNumber The input phone number to be normalized.
 *
 * @return string|bool The normalized phone number (or false if invalid).
 */
function anbarak_normalize_phone($phoneNumber)
{
    $phoneNumber = anbarak_normalize_number($phoneNumber);
    $phoneNumber = trim((string) $phoneNumber);

    if ($phoneNumber === '') {
        return false;
    }

    $phoneNumber = preg_replace('/[\s\-\(\)\.\[\]\/\\\\]+/', '', $phoneNumber);
    $phoneNumber = ltrim($phoneNumber, '+');
    $phoneNumber = preg_replace('/\D+/', '', $phoneNumber);

    if ($phoneNumber === '') {
        return false;
    }

    $is_international = false;

    if (substr($phoneNumber, 0, 4) === '0098') {
        $phoneNumber = '0' . substr($phoneNumber, 4);
    } elseif (substr($phoneNumber, 0, 2) === '00') {
        $phoneNumber = substr($phoneNumber, 2);
        $is_international = true;
    } elseif (substr($phoneNumber, 0, 2) === '98' && strlen($phoneNumber) === 12) {
        $phoneNumber = '0' . substr($phoneNumber, 2);
    }

    if (!$is_international && strlen($phoneNumber) === 10 && $phoneNumber[0] !== '0') {
        $phoneNumber = '0' . $phoneNumber;
    }

    if (preg_match('/^0\d{10}$/', $phoneNumber)) {
        return $phoneNumber;
    }

    if (preg_match('/^[1-9]\d{7,14}$/', $phoneNumber)) {
        return $phoneNumber;
    }

    return false;
}

/**
 * Backward-compatible wrapper for older code paths.
 *
 * @deprecated 1.0.0 Use anbarak_normalize_phone() instead.
 */
function anbarak_normalize_iranian_phone($phoneNumber)
{
    return anbarak_normalize_phone($phoneNumber);
}

function anbarak_get_user_customer_data($user_id)
{
    $user_id = (int) $user_id;
    $user = get_userdata($user_id);

    if (!$user) {
        return [];
    }

    $first_name = get_user_meta($user_id, 'billing_first_name', true);
    if ('' === $first_name) {
        $first_name = get_user_meta($user_id, 'first_name', true);
    }

    $last_name = get_user_meta($user_id, 'billing_last_name', true);
    if ('' === $last_name) {
        $last_name = get_user_meta($user_id, 'last_name', true);
    }

    $phone = get_user_meta($user_id, 'billing_phone', true);
    if ('' === $phone && anbarak_normalize_phone($user->user_login)) {
        $phone = $user->user_login;
    }

    $email = get_user_meta($user_id, 'billing_email', true);
    if ('' === $email) {
        $email = $user->user_email;
    }

    return [
        'user_id'    => $user_id,
        'phone'      => $phone,
        'first_name' => $first_name,
        'last_name'  => $last_name,
        'email'      => $email,
        'country'    => get_user_meta($user_id, 'billing_country', true),
        'province'   => get_user_meta($user_id, 'billing_state', true),
        'address'    => get_user_meta($user_id, 'billing_address_1', true),
        'postal'     => get_user_meta($user_id, 'billing_postcode', true),
    ];
}

function anbarak_format_price($price, $currency = 'USD')
{

    if (!$price) return;

    $decimals = 2;

    if (strtoupper($currency) === 'IRT') {
        $decimals = 0;
    }

    return number_format($price, $decimals, '.', ',');
}

/**
 * sanitizes price for storing.
 */
/**
 * Sanitizes price for storing (from thousand-separated input)
 */
function anbarak_sanitize_price($price_string)
{
    if (empty($price_string) || !is_string($price_string)) {
        return 0.0;
    }

    // Remove all characters except digits and decimal point
    $clean = preg_replace('/[^0-9.]/', '', $price_string);

    // If multiple decimal points exist, keep only the last one
    if (substr_count($clean, '.') > 1) {
        $parts = explode('.', $clean);
        $clean = $parts[0] . '.' . implode('', array_slice($parts, 1));
    }

    // Remove leading zeros (except for numbers < 1)
    $clean = preg_replace('/^0+(?=\d)/', '', $clean);

    return $clean === '' || $clean === '.' ? 0.0 : (float) $clean;
}

/**
 * Check if HPOS(High-Performance Order Storage) is enabled
 */
function anbarak_is_wc_hpos_enabled()
{
    return class_exists('Automattic\WooCommerce\Utilities\OrderUtil') &&
        Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled();
}

/**
 * Inserts or updates order metadata in the most efficient way possible
 * Works for both HPOS and legacy modes
 * 
 * @param int    $order_id   Order ID
 * @param string $meta_key   Meta key
 * @param mixed  $meta_value Meta value
 * @return bool True on success, false on failure
 */
function anbarak_upsert_order_metadata($order_id, $meta_key, $meta_value)
{
    global $wpdb;

    $table = "{$wpdb->prefix}wc_orders_meta";
    $serialized_value = maybe_serialize($meta_value);

    if (anbarak_is_wc_hpos_enabled()) {

        $wpdb->delete(
            $table,
            ['order_id' => $order_id, 'meta_key' => $meta_key],
            ['%d', '%s']
        );

        return (bool) $wpdb->insert(
            $table,
            [
                'order_id' => $order_id,
                'meta_key' => $meta_key,
                'meta_value' => $serialized_value
            ],
            ['%d', '%s', '%s']
        );
    }

    return update_post_meta($order_id, $meta_key, $meta_value);
}



/**
 * Safely inserts or updates order item meta (no duplicates).
 * Uses atomic operations for best performance.
 * 
 * @param int    $item_id    Order item ID
 * @param string $meta_key   Meta key
 * @param mixed  $meta_value Meta value
 * @return bool True on success, false on failure
 */
function anbarak_upsert_order_item_meta($item_id, $meta_key, $meta_value)
{
    global $wpdb;

    $table = "{$wpdb->prefix}woocommerce_order_itemmeta";
    $serialized_value = maybe_serialize($meta_value);

    // First try to update (will affect 0 rows if meta doesn't exist)
    $updated = $wpdb->update(
        $table,
        ['meta_value' => $serialized_value],
        ['order_item_id' => $item_id, 'meta_key' => $meta_key],
        ['%s'],
        ['%d', '%s']
    );

    // If no rows were updated, do an insert
    if ($updated === 0) {
        return (bool) $wpdb->insert(
            $table,
            [
                'order_item_id' => $item_id,
                'meta_key' => $meta_key,
                'meta_value' => $serialized_value
            ],
            ['%d', '%s', '%s']
        );
    }

    return true;
}


function anbarak_should_use_jalali_date()
{
    $locale = get_locale();
    return in_array($locale, ['fa_IR', 'fa_IR_FORMAL', 'fa_IR', 'fa']);
}

function anbarak_date($timestamp)
{
    if (anbarak_should_use_jalali_date()) {
        return \Morilog\Jalali\Jalalian::forge($timestamp)->format('%A %d %B %Y');
    }
    return wp_date('l, F j, Y', $timestamp);
}

function anbarak_datetime($timestamp)
{
    if (anbarak_should_use_jalali_date()) {
        return \Morilog\Jalali\Jalalian::forge($timestamp)->format('%A %d %B %Y - H:i:s');
    }
    return wp_date('l, F j, Y - H:i:s', $timestamp);
}

function anbarak_date_format($format, $timestamp)
{
    if (anbarak_should_use_jalali_date()) {
        return \Morilog\Jalali\Jalalian::forge($timestamp)->format($format);
    }
    return wp_date($format, $timestamp);
}


function anbarak_make_datetime($modifier = 'now')
{
    if (anbarak_should_use_jalali_date()) {
        return \Morilog\Jalali\Jalalian::forge($modifier)->getTimestamp();
    }
    return (new DateTime($modifier))->getTimestamp();
}

if (!function_exists('anbarak_get_user_ip')) {
    function anbarak_get_user_ip()
    {
        foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
            if (array_key_exists($key, $_SERVER) === true) {
                foreach (array_map('trim', explode(',', sanitize_text_field(wp_unslash($_SERVER[$key])))) as $ip) {
                    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
                        return $ip;
                    }
                }
            }
        }
    }
}

function anbarak_get_beginning_of_day($timestamp)
{
    $date = getdate($timestamp);
    return mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']);
}

/**
 * Creates timestamp range between two date
 */
function anbarak_date_range($first, $last, $step = 86400)
{
    $dates = array();
    $current = $first;
    while ($current <= $last) {
        $timestamp = $current;
        $day_start_sec = anbarak_get_beginning_of_day($timestamp) * 1000;
        $dates[$day_start_sec] = [$day_start_sec, 0];
        $current += $step;
    }
    return $dates;
}



function anbarak_get_total_products_count(): int
{
    $productsInfo = ProductsInfo::getInstance();
    return $productsInfo->getTotal();
}

function anbarak_get_low_stock_products()
{
    $productsInfo = ProductsInfo::getInstance();
    return $productsInfo->getLowStock();
}

function anbarak_get_total_managed_stock_products_count()
{
    $productsInfo = ProductsInfo::getInstance();
    return $productsInfo->getManagedCount();
}

function anbarak_get_out_of_stock_products()
{
    $productsInfo = ProductsInfo::getInstance();
    return $productsInfo->getOutOfStock();
}


function anbarak_get_in_stock_products()
{
    $productsInfo = ProductsInfo::getInstance();
    return $productsInfo->getInStock();
}


/**
 * Search products by name or sku
 * RESULT INCLUDES PARENT PRODUCTS AS WELL (like parent product id of a variable product)
 */
function anbarak_get_products($query, $type = 'title', $ids_only = false)
{
    $args = [];

    $defaults = array(
        'post_status' => 'publish',
        'post_type'      => ['product', 'product_variation'],
        'posts_per_page' => -1,
        'orderby' => [
            'post_date_gmt' => 'DESC',
            'parent' => 'DESC'
        ],
        'meta_query'    => []
    );

    if ($ids_only) {
        $defaults['fields'] = 'ids';
    }

    $args = wp_parse_args($args, $defaults);

    if ($query) {

        if ('title' === $type) {
            $args['s']  = $query;
        }

        if ('sku' === $type) {
            $args['meta_query'] = array(
                array(
                    'key' => '_sku',
                    'value' => $query,
                    'compare' => '='
                    // 'compare' => 'REGEXP'
                )
            );
        }
    }

    return new WP_Query($args);
}


function anbarak_get_total_products_worth()
{
    $inStockProducts = anbarak_get_in_stock_products();

    $total = 0;
    foreach ($inStockProducts as $product) {
        if (
            !$product->stock ||
            !$product->price
        ) continue;
        $total += (int)$product->price * (int)$product->stock;
    }

    return $total;
}


function anbarak_get_total_products_net_worth()
{
    $inStockProducts = anbarak_get_in_stock_products();

    $total = 0;
    foreach ($inStockProducts as $product) {

        if (
            !$product->stock ||
            !$product->price
        ) continue;

        $total += (int)$product->price * (int)$product->stock;
        if (!$product->total_buy_cost) continue;
        $total -= $product->total_buy_cost;
    }

    return $total;
}

/**
 * 
 */
function anbarak_get_product_latest_buy_price($product_id)
{
    global $wpdb;

    $expenses_table = $wpdb->prefix . Tables::EXPENSES;

    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom table name is fixed from $wpdb->prefix and Tables.
    $expense = $wpdb->get_row($wpdb->prepare("
        SELECT
            price,qty
        FROM 
            {$expenses_table} e 
        WHERE 
            e.product_id = %d
            AND qty IS NOT NULL
            AND deleted_at IS NULL
        ORDER BY id DESC
        LIMIT 0,1
    ", (int) $product_id));
    // phpcs:enable

    if (!$expense || !$expense->qty) return null;
    $buyPrice = $expense->price / $expense->qty;
    return $buyPrice ?? 0;
}

function anbarak_get_param($name)
{
	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by caller.
    return isset($_GET[$name]) && !empty($_GET[$name]) ? sanitize_text_field(wp_unslash($_GET[$name])) : '';
}

function anbarak_is_fullscreen()
{
    return isset($_COOKIE['anbarak_fullscreen']) && '1' === sanitize_text_field(wp_unslash($_COOKIE['anbarak_fullscreen']));
}

function anbarak_post_param($name)
{
	// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by caller.
    return isset($_POST[$name]) && !empty($_POST[$name]) ? sanitize_text_field(wp_unslash($_POST[$name])) : '';
}

function anbarak_timestamp_param($name, $default = 0, $method = 'get')
{
    // phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended -- Nonce verified by caller.
    $sources = [];
    if ('post' === $method) {
        $sources[] = isset($_POST) ? wp_unslash($_POST) : [];
    } else {
        $sources[] = isset($_GET) ? wp_unslash($_GET) : [];
    }
    $value = null;

    foreach ($sources as $source) {
        if (isset($source[$name . '-ts']) && '' !== $source[$name . '-ts']) {
            $value = $source[$name . '-ts'];
            break;
        }

        if (isset($source[$name]) && is_numeric($source[$name])) {
            $value = $source[$name];
            break;
        }
    }

    if (null === $value) {
        return $default;
    }

    $timestamp = (int) $value;
    if ($timestamp > 9999999999) {
        $timestamp = (int) floor($timestamp / 1000);
    }

    return $timestamp;
    // phpcs:enable
}

/**
 * Create in-store custom order
 */
function anbarak_add_order($products, $buyer_data = [], $discount = 0, $order_notes = '')
{

    $current_user_id = get_current_user_id();
    $order_country = $buyer_data['country'] ?? anbarak_get_order_default_country();
    $order_province = $buyer_data['province'] ?? '';
    $states = anbarak_wc_provinces($order_country);
    $buyer_phone = '';
    if (!empty($buyer_data['phone'])) {
        $buyer_phone = anbarak_normalize_phone($buyer_data['phone']) ?: $buyer_data['phone'];
    }

    $customer_data = array(
        'first_name' => $buyer_data['name'] ?? esc_html__('In-store sell', 'anbarak'),
        'last_name'  => $buyer_data['last_name'] ?? '',
        'company'    => '',
        'email'      => $buyer_data['email'] ?? 'unknown@unknown.com',
        'phone'      => $buyer_phone,
        'address_1'  => $buyer_data['address'] ?? '',
        'address_2'  => '',
        'city'       => '',
        'country'    => $order_country,
        'state'      => isset($states[$order_province]) ? $states[$order_province] : $order_province,
        'postcode'   => $buyer_data['postal'] ?? '',
    );

    $order = wc_create_order();

    $product_discount = 0;
    if ($discount) {
        $discount = (int) str_replace(',', '', $discount);
        $product_discount = $discount / count($products);
    }

    $grouped_products = [];
    foreach ($products as $p) {
        $product_id = isset($p['id']) ? (int) $p['id'] : 0;
        $qty = isset($p['qty']) ? (int) $p['qty'] : 0;
        $price = isset($p['price']) ? (float) str_replace(',', '', $p['price']) : 0.0;

        if (!$product_id || $qty <= 0) {
            continue;
        }

        $key = (string) $product_id;

        if (!isset($grouped_products[$key])) {
            $grouped_products[$key] = [
                'id' => $product_id,
                'qty' => $qty,
                'price' => $price,
            ];
        } else {
            $grouped_products[$key]['qty'] += $qty;
        }
    }

    foreach ($grouped_products as $product) {
        $productObj = wc_get_product($product['id']);
        if (!$productObj) {
            continue;
        }

        $order->add_product($productObj, $product['qty'], [
            'subtotal' => (float) str_replace(',', '', $product['price'] * $product['qty']),
            'total' => (float)str_replace(',', '', $product['price']) * $product['qty'] - $product_discount,
        ]);
    }

    $order->set_address($customer_data, 'billing');
    $order->set_address($customer_data, 'shipping');

    if (!empty($buyer_data['user_id'])) {
        $order->set_customer_id($buyer_data['user_id']);
    }

    $order->calculate_totals();
    $order->update_status('completed');

    $order->update_meta_data('_is_anbarak_order', 'yes');

    $author = get_userdata($current_user_id);
    $order->update_meta_data('_anbarak_author', $current_user_id);
    $order->update_meta_data('_anbarak_author_role', implode(',', $author->roles));

    // save private notes
    if (!empty($order_notes)) {
        $order->add_order_note(wp_kses_post($order_notes), true, true);
    }

    // also save as customer note (like checkout field)
    if (!empty($order_notes)) {
        $order->set_customer_note(wc_clean($order_notes));
    }

    $order->save();

    anbarak_calculate_buy_costs($order->get_id());

    return $order;
}

function anbarak_get_order_items_avg(int $time_start, int $time_end)
{
    global $wpdb;

    $orderItemsAvg = $wpdb->get_var($wpdb->prepare("
    SELECT AVG(item_count) AS avg_items_per_order
    FROM (
        SELECT
            o.ID AS order_id,
            COUNT(oi.order_item_id) AS item_count
        FROM {$wpdb->posts} o
        JOIN {$wpdb->postmeta} om ON o.ID = om.post_id
        JOIN {$wpdb->prefix}woocommerce_order_items oi ON o.ID = oi.order_id
        WHERE o.post_type = 'shop_order'
            AND UNIX_TIMESTAMP(o.post_date_gmt) > %d
            AND UNIX_TIMESTAMP(o.post_date_gmt) < %d
            AND o.post_status IN('wc-completed','wc-processing')
            AND (om.meta_key = '_order_total' OR om.meta_key = '_order_items')
            AND oi.order_item_type = 'line_item'
        GROUP BY o.ID
    ) AS item_counts;", $time_start, $time_end));

    return $orderItemsAvg ?? 0;
}

/**
 * Returns the array of sold products in a time range
 * 
 * @return array array of sold products
 */
function anbarak_get_sales_legacy(int $time_start, int $time_end, $type = 'all')
{
    global $wpdb;

    $orders_table = $wpdb->prefix . Tables::ORDERS;

    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table names are fixed from $wpdb and Tables; values are prepared below.
    $orders = $wpdb->get_results($wpdb->prepare("SELECT 
            (meta.meta_value - IFNULL(shipping_meta.meta_value, 0)) AS order_price, -- Subtract shipping from order total
            posts.ID AS order_id,
            UNIX_TIMESTAMP(posts.post_date_gmt) as order_date,
            mt1.meta_value as total_buy_price,
            mt2.meta_value as total_vendor_price,
            anbarak.orderid as anbarak
        FROM {$wpdb->posts} AS posts
            LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id 
            LEFT JOIN (SELECT * FROM {$wpdb->postmeta} WHERE meta_key = '_anbarak_total_buy_cost') AS mt1 ON posts.ID = mt1.post_id  
            LEFT JOIN (SELECT * FROM {$wpdb->postmeta} WHERE meta_key = '_anbarak_total_buy_cost_partner') AS mt2 ON posts.ID = mt2.post_id  
            LEFT JOIN {$orders_table} AS anbarak ON posts.ID = anbarak.orderid
            LEFT JOIN {$wpdb->postmeta} AS shipping_meta ON posts.ID = shipping_meta.post_id AND shipping_meta.meta_key = '_order_shipping' -- Join shipping cost
        WHERE 
            UNIX_TIMESTAMP(posts.post_date_gmt) > %d
            AND UNIX_TIMESTAMP(posts.post_date_gmt) < %d
            AND meta.meta_key = '_order_total' 
            AND posts.post_type = 'shop_order' 
            AND posts.post_status IN ( 'wc-completed', 'wc-processing', 'wc-on-hold')
            AND (
                %s = 'all'
                OR ( %s = 'in-store' AND anbarak.orderid IS NOT NULL )
                OR ( %s = 'online' AND anbarak.orderid IS NULL )
            )
        ORDER BY order_date ASC
    ", $time_start, $time_end, $type, $type, $type), 'ARRAY_A');
    // phpcs:enable


    return $orders;
}

/**
 * Returns the array of sold products in a time range (HPOS compatible)
 * 
 * @param int $time_start Unix timestamp for start time
 * @param int $time_end Unix timestamp for end time
 * @param string $type 'all', 'in-store', or 'online'
 * @return array Array of sold products
 */
function anbarak_get_sales_hpos(int $time_start, int $time_end, $type = 'all')
{
    global $wpdb;

    // HPOS tables
    $orders_table = $wpdb->prefix . 'wc_orders';
    $order_meta_table = $wpdb->prefix . 'wc_orders_meta';
    $order_stats_table = $wpdb->prefix . 'wc_order_stats';
    $anbarak_orders_table = $wpdb->prefix . Tables::ORDERS;

    $date_start = gmdate('Y-m-d H:i:s', $time_start);
    $date_end = gmdate('Y-m-d H:i:s', $time_end);


    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- HPOS/custom table names are fixed from $wpdb->prefix and Tables; values are prepared below.
    $orders = $wpdb->get_results($wpdb->prepare("SELECT 
            (orders.total_amount - IFNULL(shipping_meta.meta_value, 0)) AS order_price,
            orders.id AS order_id,
            UNIX_TIMESTAMP(orders.date_created_gmt) as order_date,
            MIN(buy_cost_meta.meta_value) as total_buy_price,
             MIN(vendor_cost_meta.meta_value) as total_vendor_price,
            anbarak.orderid as anbarak
        FROM {$orders_table} AS orders
            LEFT JOIN {$order_stats_table} AS stats ON orders.id = stats.order_id
            LEFT JOIN {$order_meta_table} AS buy_cost_meta ON orders.id = buy_cost_meta.order_id 
                AND buy_cost_meta.meta_key = '_anbarak_total_buy_cost'
            LEFT JOIN {$order_meta_table} AS vendor_cost_meta ON orders.id = vendor_cost_meta.order_id 
                AND vendor_cost_meta.meta_key = '_anbarak_total_buy_cost_partner'
            LEFT JOIN {$anbarak_orders_table} AS anbarak ON orders.id = anbarak.orderid
            LEFT JOIN {$order_meta_table} AS shipping_meta ON orders.id = shipping_meta.order_id 
                AND shipping_meta.meta_key = '_order_shipping'
        WHERE 
            orders.date_created_gmt >= %s
            AND orders.date_created_gmt <= %s
            AND orders.type = 'shop_order'
            AND orders.status IN ( 'wc-completed', 'wc-processing', 'wc-on-hold' )
            AND (
                %s = 'all'
                OR ( %s = 'in-store' AND anbarak.orderid IS NOT NULL )
                OR ( %s = 'online' AND anbarak.orderid IS NULL )
            )
        GROUP BY orders.id, orders.total_amount, shipping_meta.meta_value, orders.date_created_gmt, anbarak.orderid
        ORDER BY order_date ASC
    ", $date_start, $date_end, $type, $type, $type), 'ARRAY_A');
    // phpcs:enable

    return $orders;
}

/**
 * get orders of given date range
 */
function anbarak_get_sales(int $time_start, int $time_end, $type = 'all')
{
    if (anbarak_is_wc_hpos_enabled()) {
        return  anbarak_get_sales_hpos($time_start, $time_end, $type);
    }

    return anbarak_get_sales_legacy($time_start, $time_end, $type);
}

/**
 * Returns the total cost of sold products in a time range
 * 
 * @return int total price
 */
function anbarak_get_total_sale_price(int $time_start, int $time_end, $type = 'all')
{
    $price_arr = anbarak_get_sales($time_start,  $time_end, $type);

    if (!is_array($price_arr)) {
        return 0;
    }

    return array_sum(
        array_column($price_arr, 'order_price')
    );
}


/**
 * calculate order buy costs when for NEW orders
 * based on the price at order time
 * 
 */
function anbarak_calculate_buy_costs($order_id)
{
    $order = wc_get_order($order_id);

    // its a new order
    // coming from "woocommerce_before_order_object_save" hook
    if (!$order) return;

    $total_buy_cost = 0;

    foreach ($order->get_items() as $item_id => $item) {

        $product = $item->get_product();
        if (!$product) continue;

        $product_id = $product->get_id();
        $qty = (int) $item->get_quantity();

        $buy_price = anbarak_get_product_latest_buy_price($product_id);
        $item_buy_cost = $buy_price * $qty;

        $total_buy_cost += $item_buy_cost;

        anbarak_upsert_order_item_meta($item_id, '_anbarak_buy_cost', $item_buy_cost);
    }

    anbarak_upsert_order_metadata($order_id, '_anbarak_total_buy_cost', $total_buy_cost);

    return $order;
}


/**
 * Returns the total net order profits in given range
 * 
 * @return int total price
 */
function anbarak_get_orders_gross_profit(int $time_start, int $time_end, $type = 'all')
{
    $price_arr = anbarak_get_sales($time_start,  $time_end, $type);

    if (!is_array($price_arr)) {
        return 0;
    }

    $total_price = array_sum(
        array_column($price_arr, 'order_price')
    );
    $total_buy_cost = array_sum(
        array_column($price_arr, 'total_buy_price')
    );

    return $total_price - $total_buy_cost;
}

function anbarak_get_month_expenses($month_start_timestamp, $month_end_timestamp, $tag = null)
{
    $days_arr = anbarak_date_range($month_start_timestamp, $month_end_timestamp);
    $sales_arr = anbarak_get_expenses($month_start_timestamp, $month_end_timestamp, $tag);
    foreach ($sales_arr as $sale) {
        $day_start_sec = anbarak_get_beginning_of_day((int)$sale['timestamp']);
        $day_start_sec = $day_start_sec * 1000;
        if (!isset($days_arr[$day_start_sec])) continue;

        if (0 == $days_arr[$day_start_sec][1]) {
            $days_arr[$day_start_sec] = array(
                $day_start_sec,
                (int)$sale['price']
            );
        } else {
            $days_arr[$day_start_sec][1] += (int)$sale['price'];
        }
    }
    array_multisort($days_arr);
    return array_values($days_arr);
}

/**
 *  Returns the total price of products sold in current month
 * 
 * @return array array of sold products
 */
function anbarak_get_month_sales_prices($month_start_timestamp, $month_end_timestamp, $type = 'all')
{
    $days_arr = anbarak_date_range($month_start_timestamp, $month_end_timestamp);
    $sales_arr = anbarak_get_sales($month_start_timestamp, $month_end_timestamp, $type);

    foreach ($sales_arr as $sale) {
        $day_start_sec = anbarak_get_beginning_of_day((int)$sale['order_date']);
        $day_start_sec = $day_start_sec * 1000;
        if (!isset($days_arr[$day_start_sec])) continue;
        if (0 == $days_arr[$day_start_sec][1]) {
            $days_arr[$day_start_sec] = array(
                $day_start_sec,
                (int)$sale['order_price']
            );
        } else {
            $days_arr[$day_start_sec][1] += (int)$sale['order_price'];
        }
    }
    array_multisort($days_arr);
    return array_values($days_arr);
}

/**
 *  Returns the total price of products sold in current month
 * 
 * @return array array of sold products
 */
function anbarak_get_month_sales_profit($month_start_timestamp, $month_end_timestamp, $type = 'all')
{
    $days_arr = anbarak_date_range($month_start_timestamp, $month_end_timestamp);
    $sales_arr = anbarak_get_sales($month_start_timestamp, $month_end_timestamp, $type);

    foreach ($sales_arr as $sale) {
        $day_start_sec = anbarak_get_beginning_of_day((int)$sale['order_date']);
        $day_start_sec = $day_start_sec * 1000;
        if (!isset($days_arr[$day_start_sec])) continue;
        if (0 == $days_arr[$day_start_sec][1]) {
            $days_arr[$day_start_sec] = array(
                $day_start_sec,
                (int)$sale['order_price'] - (int)$sale['total_buy_price']
            );
        } else {
            $days_arr[$day_start_sec][1] += ((int)$sale['order_price'] - (int)$sale['total_buy_price']);
        }
    }

    array_multisort($days_arr);
    return array_values($days_arr);
}

/**
 * Returns the array of expenses between time ranges.
 * 
 * @param int $time_start Start timestamp
 * @param int $time_end End timestamp
 * @param int|null $tag Optional tag ID to filter by
 * @return array Array of expenses
 */
function anbarak_get_expenses(int $time_start, int $time_end, $tag = null)
{
    global $wpdb;

    $expenses_table = $wpdb->prefix . Tables::EXPENSES;
    $expenses_tags_table = $wpdb->prefix . Tables::EXPENSES_TAGS;
    $tag_id = $tag ? (int) $tag : 0;

    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom table names are fixed from $wpdb->prefix and Tables.
    return $wpdb->get_results($wpdb->prepare("SELECT expenses.id, expenses.product_id, expenses.price, expenses.timestamp, 
               expenses.qty, expenses.tag_id,
               p.post_title as product_name,
               t.name as tag_name, t.color as tag_color
        FROM {$expenses_table} AS expenses
        LEFT JOIN {$wpdb->prefix}posts p ON expenses.product_id = p.ID
        LEFT JOIN {$expenses_tags_table} t ON expenses.tag_id = t.id
        WHERE
            expenses.timestamp > %d
            AND expenses.timestamp <= %d
            AND expenses.deleted_at IS NULL
            AND ( %d = 0 OR expenses.tag_id = %d )
        ORDER BY expenses.timestamp DESC
    ", $time_start, $time_end, $tag_id, $tag_id), 'ARRAY_A');
    // phpcs:enable
}

/**
 * Returns the total cost of sold products in a time range
 * 
 * @return int total price
 */
function anbarak_get_total_expenses_price(int $time_start, int $time_end, $tag = '')
{
    $price_arr = anbarak_get_expenses($time_start,  $time_end, $tag);

    if (!is_array($price_arr)) {
        return 0;
    }

    return array_sum(
        array_column($price_arr, 'price')
    );
}

function anbarak_render_products_table_items($args)
{
    global $wpdb;

    if (isset($args['posts_per_page'])) {
        $per_page = $args['posts_per_page'];
    } else {
        $per_page = isset($_COOKIE['anbarak_ipp']) ? sanitize_text_field(wp_unslash($_COOKIE['anbarak_ipp'])) : ANBARAK_PRODUCTS_PER_PAGE;
    }

    if (!isset($args['paged'])) {
        $args['paged'] = anbarak_get_param('paged');
    }

    $productsInfo = ProductsInfo::getInstance();
    $excludedPosts = $productsInfo->getNonManagedVariablesIds();

    $defaults = array(
        'post_status' => 'publish',
        'post_type'      => ['product', 'product_variation'],
        'posts_per_page' => $per_page,
        'post__not_in' => $excludedPosts,
        'orderby' => [
            'post_date_gmt' => 'DESC',
            'parent' => 'DESC'
        ],
        'meta_query'    => []
    );

    $args = wp_parse_args($args, $defaults);

    $meta_query = $args['meta_query'];

    $meta_query[] = [
        'key'     => '_manage_stock',
        'value'   => 'yes',
    ];

    if (isset($args['group_variables'])) {
        $args['orderby'] = [
            'post_parent' => 'DESC',
            'post_date_gmt' => 'DESC'
        ];
    }

    if (isset($args['low-stock'])) {
        $meta_query[] = [
            'key'     => '_stock',
            'value'   => [1, ANBARAK_PRODUCTS_LOW_STOCK_THRESHOLD],
            'compare' => 'BETWEEN',
            'type'      => 'numeric'
        ];
    }

    if (isset($args['out-of-stock'])) {
        $meta_query[] = [
            'key' => '_stock',
            'value' => 0,
            'compare' => '<=',
            'type'      => 'numeric'
        ];
    }


    if (isset($args['in-stock'])) {
        $meta_query[] = [
            'key' => '_stock',
            'value' => 0,
            'compare' => '>',
            'type'      => 'numeric'
        ];
    }


    $args['meta_query'] = $meta_query;

    $loop = new WP_Query($args);

    anbarak_render_products_list_table($loop);
}

/**
 * Prints the table with pagination
 */
function anbarak_render_products_list_table($loop)
{
    $page = anbarak_get_param('paged');

    $base = admin_url('admin.php?page=anbarak');

?>
    <table class="anbarak-products-wrapper-table table wp-list-table">
        <thead>
            <tr>
                <th class="product-image"><?php esc_html_e('Image', 'anbarak') ?></th>
                <th class="product-id"><?php esc_html_e('ID', 'anbarak'); ?></th>
                <th class="product-name"><?php esc_html_e('Name', 'anbarak') ?></th>
                <?php if (anbarak_is_inventory_column_active('sku')) : ?>
                    <th class="product-sku"><?php esc_html_e('SKU', 'anbarak'); ?></th>
                <?php endif ?>
                <?php if (anbarak_is_inventory_column_active('weight')) : ?>
                    <th class="product-weight"><?php esc_html_e('Weight', 'anbarak'); ?></th>
                <?php endif ?>
                <?php if (anbarak_user_is_admin_or_manager() && anbarak_is_inventory_column_active('online_sell')) : ?>
                    <th class="product-online-sell"><?php esc_html_e('Online Sell', 'anbarak') ?></th>
                <?php endif ?>
                <?php if (anbarak_user_is_admin_or_manager() && anbarak_is_inventory_column_active('backorders')) : ?>
                    <th class="product-backorders"><?php esc_html_e('Backorders', 'anbarak') ?></th>
                <?php endif ?>
                <?php if (anbarak_user_is_admin_or_manager() && anbarak_is_inventory_column_active('last_buy_price')) : ?>
                    <th class="product-last-buy-price" data-tippy-content="<?php echo esc_html__('Product last purchase price (Product charge price)', 'anbarak') ?>"><?php esc_html_e('Buy Price', 'anbarak') ?></th>
                <?php endif ?>
                <th class="product-price"><?php esc_html_e('Price', 'anbarak') ?></th>
                <th class="product-sale-price"><?php esc_html_e('Sale Price', 'anbarak') ?></th>
                <th class="product-stock"><?php esc_html_e('Stock', 'anbarak') ?></th>
                <th class="product-actions"><?php esc_html_e('Actions', 'anbarak') ?></th>
            </tr>
        </thead>
        <tbody>
            <?php
            while ($loop->have_posts()) {
                $loop->the_post();
                anbarak_render_product_table_item_loop();
            }
            wp_reset_postdata(); ?>
        </tbody>
    </table>

    <div class="footer-actions flex flex-col lg:flex-row gap-4">
        <?php anbarak_pagination(
            $base,
            max(1, $page),
            $loop->query['posts_per_page'] ?: 20,
            $loop->found_posts ?? 0
        ); ?>
    </div>
<?php
}

function anbarak_get_variation_attributes($product)
{
    $vars = [];
    if ($product->is_type('variation')) {
        foreach ($product->get_attributes() as $attribute => $term_slug) {
            $taxonomy = str_replace('attribute_', '', $attribute);
            $attr_label_name = wc_attribute_label($taxonomy);
            $term_name = get_term_by('slug', $term_slug, $taxonomy);
            if (!$term_name) {
                $term_name = $term_slug;
            } else {
                $term_name = $term_name->name;
            }
            $attr_label_name = str_replace('pa_', '', $attr_label_name);
            $vars[] =  urldecode($attr_label_name) . ': ' . urldecode($term_name);
        }
    }

    return implode(', ', $vars);
}


function anbarak_render_product_table_item_loop($id = null)
{
    $id = $id ?: get_the_ID();
    $_product = wc_get_product($id);
    $stock = $_product->get_stock_quantity();
    $low_stock_threshold = (int)$_product->get_low_stock_amount() ?: ANBARAK_PRODUCTS_LOW_STOCK_THRESHOLD;
    $is_variation = $_product->is_type('variation');
    $is_variable = $_product->is_type('variable');

    $variations_using_parent_stock = [];
    $variations = [];
    if ($is_variable) {
        $variations = $_product->get_available_variations();

        foreach ($variations as $variation_data) {
            $variation_id = $variation_data['variation_id'];
            $variation = wc_get_product($variation_id);

            if ($variation) {
                $manage_stock = $variation->get_manage_stock();

                if ('parent' === $manage_stock) {
                    $variations_using_parent_stock[] = $variation->get_id();
                }
            }
        }
    }

    $low_stock = false;
    if ($stock <= $low_stock_threshold) {
        $low_stock = true;
    }
    $out_of_stock = false;
    if ($stock <= ANBARAK_PRODUCTS_OUT_OF_STOCK_THRESHOLD) {
        $out_of_stock = true;
    }

    $last_buy_price = anbarak_get_product_latest_buy_price($id);
    $profitPercent = 0;
    $profitPercentBySalePrice = 0;

    if (anbarak_user_is_admin_or_manager()) {
        if ($_product->get_regular_price() && $last_buy_price) {
            $profitPercent = (((int)$_product->get_regular_price() - (int)$last_buy_price) / (int)$last_buy_price)  * 100;
        }
        if ($_product->get_sale_price() && $last_buy_price) {
            $profitPercentBySalePrice = (((int)$_product->get_sale_price() - (int)$last_buy_price) / (int)$last_buy_price)  * 100;
        }
    }

    $vars = anbarak_get_variation_attributes($_product);

?>
    <tr class="product-item <?php echo $low_stock ? ' low-stock' : '' ?><?php echo $out_of_stock ? ' out-of-stock' : '' ?>" data-id="<?php the_ID() ?>" data-title="<?php the_title() ?>" data-stock="<?php echo esc_attr($stock) ?>">
        <td>
            <div class="product-item__pic">
                <?php echo wp_kses_post(woocommerce_get_product_thumbnail()) ?>
                <div class="product-item__pic__zoommed">
                    <?php echo wp_kses_post(woocommerce_get_product_thumbnail()) ?>
                </div>
            </div>
        </td>
        <td class="product-item__id"><?php the_ID(); ?></td>
        <td class="product-item__name relative">
            <div class="group relative">
                <?php if (current_user_can('edit_product', $_product->get_id())) : ?>
                    <?php if ($is_variation): ?>
                        <a class="-start-5 absolute me-2" href="<?php echo esc_url(get_edit_post_link($_product->get_parent_id())); ?>#woocommerce-product-data" class="edit-product-link" target="_blank" rel="noopener noreferrer">
                            <span class="icon icon-edit text-base opacity-0 transition group-hover:opacity-70"></span>
                        </a>
                    <?php else: ?>
                        <a class="-start-5 absolute me-2" href="<?php echo esc_url(get_edit_post_link($_product->get_id())); ?>" class="edit-product-link" target="_blank" rel="noopener noreferrer">
                            <span class="icon icon-edit text-base opacity-0 transition group-hover:opacity-70"></span>
                        </a>
                    <?php endif; ?>
                <?php endif; ?>
                <a href="<?php the_permalink() ?>"><?php echo esc_html($_product->get_title()) ?>
                    <?php if ($vars) : ?>
                        <small><bdi>(<?php echo esc_html($vars)  ?> )</bdi></small>
                    <?php endif ?>
                </a>
                <?php if ($is_variable && $variations_using_parent_stock) : ?>
                    <span class="badge me-2 text-xs" data-tippy-content="<?php echo  count($variations_using_parent_stock) . ' ' . esc_html__('Variations are using stock quantity of this parent products because they don\'t have their own stock management.', 'anbarak') ?>">
                        <?php esc_html_e('Parent Product', 'anbarak') ?>
                        (<?php echo count($variations_using_parent_stock) ?>)
                    </span>
                <?php endif ?>
                <?php if ($is_variable && empty($variations_using_parent_stock)) : ?>
                    <span class="badge me-2 text-xs" data-tippy-content="<?php esc_html_e('Since each variation manages its own stock, you can disable stock management at the product level.', 'anbarak') ?>">
                        <?php esc_html_e('Useless!', 'anbarak') ?>
                    </span>
                <?php endif ?>
                <?php if ($is_variation || $is_variable): ?>
                    <button data-title="<?php echo esc_attr($_product->get_title()) ?>" data-tippy-content="<?php esc_attr_e('Find Other Variations', 'anbarak') ?>" class="button absolute end-2 !leading-1 shadow-lg !size-8 !p-1 search-by-title transition-opacity delay-500 opacity-0 group-hover:opacity-90 ">
                        <span class="icon icon-search"></span>
                    </button>
                <?php endif ?>
            </div>

        </td>

        <?php if (anbarak_is_inventory_column_active('sku')) : ?>
            <td class="product-item__sku">
                <?php echo wp_kses_post(Input::render([
                    'name' => 'sku',
                    'class' => 'ltr text-center',
                    'value' => get_post_meta($_product->get_id(), '_sku', true),
                    'placeholder' => esc_html__('-', 'anbarak')
                ])); ?>
            </td>
        <?php endif; ?>

        <?php if (anbarak_is_inventory_column_active('weight')) : ?>
            <td class="product-item__weight">
                <?php echo wp_kses_post(Input::render([
                    'name' => 'weight',
                    'class' => 'ltr text-center',
                    'value' => $_product->get_weight(),
                    'placeholder' => esc_html__('-', 'anbarak')
                ])); ?>
            </td>
        <?php endif; ?>

        <?php if (anbarak_user_is_admin_or_manager() && anbarak_is_inventory_column_active('online_sell')) : ?>
            <td class="product-item__online-sell text-center">
                <?php $online_sell = get_post_meta($_product->get_id(), '_anbarak_no_online_sell', true); ?>
                <select name="online-sell" id="">
                    <option value="0" <?php selected($online_sell, 'yes') ?>><?php esc_html_e('Inactive', 'anbarak'); ?></option>
                    <option value="1" <?php selected($online_sell, null) ?>><?php esc_html_e('Active', 'anbarak'); ?></option>
                </select>
            </td>
        <?php endif; ?>

        <?php if (anbarak_user_is_admin_or_manager() && anbarak_is_inventory_column_active('backorders')) : ?>
            <td class="product-item__backorders">
                <select name="backorders" id="">
                    <option value="no" <?php selected($_product->get_backorders(), 'no'); ?>><?php esc_html_e('Disallow', 'anbarak'); ?></option>
                    <option value="notify" <?php selected($_product->get_backorders(), 'notify'); ?>><?php esc_html_e('Notify', 'anbarak'); ?></option>
                    <option value="yes" <?php selected($_product->get_backorders(), 'yes'); ?>><?php esc_html_e('yes', 'anbarak'); ?></option>
                </select>
            </td>
        <?php endif; ?>

        <?php if (anbarak_user_is_admin_or_manager() && anbarak_is_inventory_column_active('last_buy_price')) : ?>
            <td class="product-item__last-buy-price text-center">
                <?php if (!$is_variable): ?>
                    <?php echo wp_kses_post(Input::render([
                        'name' => 'buy_price',
                        'class' => 'thousand-separator ltr text-center',
                        'value' => $last_buy_price ?: '',
                        'placeholder' => esc_html__('Buy Price', 'anbarak')
                    ])); ?>
                <?php else: ?>
                    <div class="ltr justify-center flex items-center gap-1 text-gray-400" data-tippy-content="<?php esc_html_e('Parent product doesn\'t have this feature', 'anbarak') ?>">
                        <span class="icon icon-alert-circle"></span>
                        <span>N/A</span>
                    </div>
                <?php endif ?>
            </td>
        <?php endif; ?>

        <td class="product-item__price">
            <div class="flex items-center justify-center text-nowrap relative ltr <?php echo $profitPercent ? 'with-badge' : '' ?> <?php echo (int)$profitPercent < 0 ? 'badge--error' : '' ?>" data-badge="<?php echo $profitPercent ? esc_attr(round($profitPercent, 1) . '%') : '' ?>">
                <?php if (!$is_variable): ?>
                    <?php echo wp_kses_post(Input::render([
                        'name' => 'price',
                        'class' => 'thousand-separator ltr text-center',
                        'value' => !empty($_product->get_regular_price()) ? $_product->get_regular_price() : $_product->get_price(),
                        'placeholder' => esc_html__('Price', 'anbarak')
                    ])); ?>
                <?php else: ?>
                    <div class="flex items-center gap-1 text-gray-400" data-tippy-content="<?php esc_html_e('Parent product doesn\'t have this feature', 'anbarak') ?>">
                        <span class="icon icon-alert-circle"></span>
                        <span>N/A</span>
                    </div>
                <?php endif ?>
            </div>
        </td>

        <td class="product-item__price_sale">
            <div class="flex items-center justify-center text-nowrap relative ltr <?php echo $profitPercentBySalePrice ? 'with-badge' : '' ?> <?php echo (int)$profitPercent < 0 ? 'badge--error' : '' ?>" data-badge="<?php echo $profitPercentBySalePrice ? esc_attr(round($profitPercentBySalePrice, 1) . '%') : '' ?>">
                <?php if (!$is_variable): ?>
                    <?php echo wp_kses_post(Input::render([
                        'name' => 'sale_price',
                        'class' => 'thousand-separator ltr text-center',
                        'value' => $_product->get_sale_price(),
                        'placeholder' => esc_html__('Sale Price', 'anbarak')
                    ])); ?>
                <?php else: ?>
                    <div class="flex items-center gap-1 text-gray-400" data-tippy-content="<?php esc_html_e('Parent product doesn\'t have this feature', 'anbarak') ?>">
                        <span class="icon icon-alert-circle"></span>
                        <span>N/A</span>
                    </div>
                <?php endif ?>
            </div>
        </td>

        <td class="product-item__stock">
            <div class="flex items-center relative justify-center">
                <?php echo wp_kses_post(Input::render([
                    'name' => 'stock',
                    'class' => '!w-[55px] thousand-separator ltr text-center',
                    'value' => $_product->get_stock_quantity(),
                ])); ?>

                <input type="hidden" name="stock-initial" value="<?php echo esc_attr($_product->get_stock_quantity()) ?>">
            </div>
        </td>
        <td class="product-item__actions">
            <input type="hidden" name="product_id" value="<?php echo esc_attr(get_the_ID()) ?>">
            <div class="actions-wrap icons-only flex gap-2 justify-center">
                <?php if (anbarak_user_is_admin_or_manager()): ?>
                    <button type="button" name="action_save" data-tippy-content="<?php esc_html_e('Save', 'anbarak') ?>" value="" class="button btn-submit-save flex items-center justify-center">
                        <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 256 256">
                            <g fill-rule="evenodd">
                                <path style="stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none" d="M174.66 4.7c-24.3.51-48.67.12-73 .42-24.18.2-48.37-.16-72.53.51C17.06 7.23 7.37 19.6 8.82 31.6c-.1 64.9-1.14 129.9-.39 194.72C9.76 239.14 22.7 249 35.35 247.36c64.55.02 129.12.64 193.65.3 12.6-2.54 23.09-15.06 21.8-28.12.22-45.51.11-91.02.06-136.53-.15-7.25.9-16.71-5.9-21.47L192.36 7.22c-5.52-2.43-11.7-2.69-17.69-2.53zm19.97 2.5c-.65 2.06 1.82-.46 0 0zM33.8 27.17c7.67.54 15.67-.71 23.2.88 4.07 2.96 1.34 8.62 2.15 12.7.22 15.8-.44 31.66.37 47.41 2.17 7.58 10.68 11.84 18.2 10.4 29.92-.24 59.93.52 89.79-.4a16.4 16.4 0 0 0 10.18-18.12c.21-16.6-.45-33.34.34-49.86 1.75-2.9 5.1.25 6.36 2.02 14.56 14.47 29.92 28.23 43.98 43.14 2.88 6.19.43 13.13 1.26 19.61-.06 41.79.42 83.6-.02 125.36-1.22 5.4-7.79 6.34-12.37 5.52-60.59-.42-121.2-.42-181.76-1.13-5.52-1.14-6.63-7.75-5.8-12.45.02-60.66-.37-121.35-.06-181.98.5-1.8 2.3-3.15 4.18-3.1zm93.6.6c8.92.15 17.95-.22 26.8.4 4.4 2.22 2.14 7.89 2.66 11.67-.27 12.27.57 24.68-.4 36.86-2.3 4.27-7.84 2-11.63 2.54-20.8-.15-41.63.31-62.4-.23-4.76-1.98-2.48-7.98-2.97-11.8.33-12.32-.63-24.8.46-37.01 2.46-4.28 8.36-1.69 12.22-2.38 11.75.01 23.5-.05 35.26-.04zm120.74 34.7c-1.27 1.65 2.14.24 0 0z" fill="#333" />
                                <path style="stroke-width:1" d="M128.1 115.23c-27.44.61-51.79 29.12-45.41 56.46 6.18 25.56 35.14 43.92 60.67 36.42 24.86-7.08 40.68-37.06 30.67-61.16-7.12-18.39-26.13-31.97-45.93-31.72zm1.75 20.65c14.63.04 26.98 14.47 25.14 28.92-.86 13.93-14.13 26.19-28.28 24.31-14.26-1.44-25.24-15.92-23.35-30.04 1.28-13.03 13.3-23.83 26.49-23.2z" fill="#333" />
                            </g>
                        </svg>
                        <label><?php esc_html_e('Save', 'anbarak') ?></label>
                    </button>

                <?php endif; ?>
                <?php if (anbarak_is_inventory_column_active('submit_sell')) : ?>
                    <button type="button" name="action_sell" value="" data-tippy-content="<?php esc_attr_e('Create Order (CTRL+O)', 'anbarak') ?>" class="button btn-submit-sell flex items-center justify-center">
                        <svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 1024 1024">
                            <path d="M704 288h131.07a32 32 0 0 1 31.81 28.8L886.4 512h-64.38l-16-160H704v96a32 32 0 1 1-64 0v-96H384v96a32 32 0 1 1-64 0v-96H217.92l-51.2 512H512v64H131.33a32 32 0 0 1-31.81-35.2l57.6-576a32 32 0 0 1 31.8-28.8H320v-22.34C320 154.7 405.5 64 512 64s192 90.69 192 201.66v22.4zm-64 0v-22.34C640 189.25 582.27 128 512 128c-70.27 0-128 61.25-128 137.66v22.4h256z" style="fill:#333" />
                            <path style="fill:#0040ff;stroke-width:1" d="m829.48 732.79-73.4-73.34v229.5a32 32 0 1 1-64 0v-229.5l-73.35 73.34a32 32 0 1 1-45.25-45.25l128-128a32 32 0 0 1 45.25 0l128 128a32 32 0 1 1-45.25 45.25z" />
                        </svg>
                        <label><?php esc_html_e('Submit Sell', 'anbarak') ?></label>
                    </button>
                <?php endif; ?>
            </div>
        </td>
    </tr>
<?php
}


function anbarak_normalize_number($string)
{
    $string = (string) $string;

    $number_map = [
        '۰' => '0',
        '۱' => '1',
        '۲' => '2',
        '۳' => '3',
        '۴' => '4',
        '۵' => '5',
        '۶' => '6',
        '۷' => '7',
        '۸' => '8',
        '۹' => '9',
        '٠' => '0',
        '١' => '1',
        '٢' => '2',
        '٣' => '3',
        '٤' => '4',
        '٥' => '5',
        '٦' => '6',
        '٧' => '7',
        '٨' => '8',
        '٩' => '9',
    ];

    return strtr($string, $number_map);
}

/**
 * Backward-compatible wrapper for older code paths.
 *
 * @deprecated 1.0.0 Use anbarak_normalize_number() instead.
 */
function anbarak_convert_persian_to_english($string)
{
    return anbarak_normalize_number($string);
}


/**
 * check anbarak allowed purchase
 */
function anbarak_check_product_active($active, $product)
{

    $no_sell = get_post_meta($product->get_id(), '_anbarak_no_online_sell', true);

    if ($no_sell) {
        return  false;
    }

    return $active;
}

function anbarak_get_orders_by_meta(string $meta_key, string $meta_value, string $compare = 'LIKE'): array
{
    global $wpdb;

    $allowed_compares = ['LIKE', '=', '!=', '>', '<', '>=', '<='];
    if (!in_array($compare, $allowed_compares, true)) {
        $compare = 'LIKE';
    }

    if (anbarak_is_wc_hpos_enabled()) {
        $table_meta = $wpdb->prefix . 'wc_orders_meta';
        $table_orders = $wpdb->prefix . 'wc_orders';

        $meta_value_sql = 'LIKE' === $compare ? '%' . $wpdb->esc_like($meta_value) . '%' : $meta_value;

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- WooCommerce HPOS table names are fixed from $wpdb->prefix and the operator is allowlisted above. WordPress 6.0 does not support %i placeholders.
        return $wpdb->get_col($wpdb->prepare("SELECT o.id FROM {$table_meta} AS o_meta INNER JOIN {$table_orders} AS o ON o.id = o_meta.order_id WHERE o_meta.meta_key = %s AND o_meta.meta_value {$compare} %s GROUP BY o.id", $meta_key, $meta_value_sql));
    }

    $meta_value_sql = $compare === 'LIKE'
        ? '%' . $wpdb->esc_like($meta_value) . '%'
        : $meta_value;

    $table_meta = $wpdb->postmeta;
    $table_posts = $wpdb->posts;

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Core table names are fixed from $wpdb and the operator is allowlisted above. WordPress 6.0 does not support %i placeholders.
    return $wpdb->get_col($wpdb->prepare("SELECT pm.post_id FROM {$table_meta} pm INNER JOIN {$table_posts} p ON pm.post_id = p.ID WHERE pm.meta_key = %s AND pm.meta_value {$compare} %s AND p.post_type IN ('shop_order', 'shop_order_refund') GROUP BY pm.post_id", $meta_key, $meta_value_sql));
}

/**
 * Admin orders list with pagination
 * Returns ['orders' => [], 'total' => int]
 */
function anbarak_get_admin_orders(
    int $limit = 2000,
    int $paged = 1,
    array $status = [],
    ?int $date_from = null,
    ?int $date_to = null
) {
    $args = [
        'limit'    => $limit,
        'page'     => max(1, $paged),
        'return'   => 'objects',
        'orderby'    => 'date',
        'order'      => 'DESC',
        'paginate' => true,
    ];

    if (!empty($status)) {
        $args['status'] = $status;
    }

    if (!empty($date_from) || !empty($date_to)) {
        $date_filter = '';

        if (!empty($date_from)) {
            $date_filter .= '>' . gmdate('Y-m-d H:i:s', (int) $date_from);
        }
        if (!empty($date_to)) {
            $date_filter .= ' <' . gmdate('Y-m-d H:i:s', (int) $date_to);
        }

        $args['date_created_gmt'] = trim($date_filter);
    }

    try {
        $result = wc_get_orders($args);
    } catch (Exception $e) {
        return ['orders' => [], 'total' => 0];
    }

    return [
        'orders' => $result->orders,
        'total'  => (int) $result->total,
    ];
}

function anbarak_get_translated_order_status($status)
{
    $statuses = wc_get_order_statuses();
    return isset($statuses['wc-' . $status]) ? $statuses['wc-' . $status] : ucfirst($status);
}

function anbarak_pagination($base, $current = 1, $per_page = 20, $total_items = 0)
{
    if ($total_items <= 0) return;

    $per_page = max(5, $per_page);

    $total_pages = (int) ceil($total_items / $per_page);

    $page_links = paginate_links(array(
        'base'      => add_query_arg('paged', '%#%', $base),
        'total'     => $total_pages,
        'current'   => max(1, $current),
        'type'      => 'array',
        'prev_next' => false,
        'end_size'  => 1,
        'mid_size'  => 2,
    ));

    echo '<div class="flex flex-wrap text-sm w-full items-center justify-between gap-4">';

    echo '<div class="flex items-center gap-0 ipp">';
    echo '<label for="ipp" class="text-sm text-gray-600 dark:text-gray-300 me-1">' . esc_html__('Items per page', 'anbarak') . '</label>';
    echo '<select name="ipp" id="ipp" class="border border-gray-300 text-sm rounded-lg px-2 py-1 focus:ring-2 focus:ring-blue-500">';
    foreach ([5, 20, 50, 100, 500] as $num) {
        printf('<option value="%d" %s>%d</option>', (int) $num, selected($per_page, $num, false), (int) $num);
    }
    echo '</select>';
    /* translators: %d: total number of items. */
    echo '<div class="mx-2">' . esc_html(sprintf(__('Total: %d items', 'anbarak'), $total_items)) . '</div></div>';

    if (!empty($page_links)) {
            echo '<div class="flex flex-wrap gap-1 pagination">';
        foreach ($page_links as $link) {
            $link = str_replace('page-numbers', 'button inline-block', $link);
            $link = str_replace('current', 'button inline-block button--primary', $link);
            echo wp_kses_post($link);
        }
        echo '</div>';
    }
    echo '</div>';
}


function anbarak_die($message, $title = 'Anbarak Error', $status_code = 500)
{
    while (ob_get_level()) {
        ob_end_clean();
    }

    wp_die(
        esc_html($message),
        esc_html($title),
        [
            'response' => (int) $status_code,
        ]
    );
}


function anbarak_get_default_inventory_cols()
{
    return   [
        'sku'            => true,
        'weight'         => false,
        'online_sell'    => false,
        'backorders'     => false,
        'last_buy_price' => true,
        'sale_price'     => true,
        'submit_buy'     => true,
        'submit_sell'    => true,
    ];
}


/**
 * Check if a specific inventory column is active
 * 
 * @param string $column_key The column key (e.g., 'sku', 'online_sell')
 * @param bool $default Default value if no settings exist
 * @return bool True if column is active, false otherwise
 */
function anbarak_is_inventory_column_active($column_key, $default = true)
{
    // Define all available columns with their defaults
    $default_columns  = anbarak_get_default_inventory_cols();

    // Get cookie value
    $cookie_value = isset($_COOKIE['anbarak_columns']) ? sanitize_text_field(wp_unslash($_COOKIE['anbarak_columns'])) : '';

    // If no cookie exists, return default for this column
    if (empty($cookie_value)) {
        return isset($default_columns[$column_key]) ? $default_columns[$column_key] : $default;
    }

    // Decode JSON from cookie
    $column_states = json_decode(stripslashes($cookie_value), true);

    // If JSON decoding failed or column doesn't exist, return default
    if (!is_array($column_states) || !isset($column_states[$column_key])) {
        return isset($default_columns[$column_key]) ? $default_columns[$column_key] : $default;
    }

    return (bool) $column_states[$column_key];
}


function anbarak_set_transient($key, $value, $expiration = 0)
{
    $prefixed_key = 'anbarak_' . $key;
    return set_transient($prefixed_key, $value, $expiration);
}

function anbarak_get_transient($key)
{
    $prefixed_key = 'anbarak_' . $key;
    return get_transient($prefixed_key);
}

function anbarak_delete_transient($key)
{
    $prefixed_key = 'anbarak_' . $key;
    return delete_transient($prefixed_key);
}

function anbarak_get_transients_stats()
{
    global $wpdb;

    $pattern = 'anbarak_%';

    // Get count and total size in one query
    $results = $wpdb->get_row(
        $wpdb->prepare(
            "SELECT 
                COUNT(*) as count,
                SUM(LENGTH(option_value)) as total_size
            FROM {$wpdb->options} 
            WHERE option_name LIKE %s",
            '_transient_' . $pattern
        )
    );

    return array(
        'count' => (int)$results->count,
        'size_bytes' => (int)$results->total_size,
        'size_kb' => round($results->total_size / 1024, 2),
        'size_mb' => round($results->total_size / (1024 * 1024), 2)
    );
}

function anbarak_clear_transients()
{
    global $wpdb;

    $pattern = 'anbarak_%';

    $wpdb->query(
        $wpdb->prepare(
            "DELETE FROM {$wpdb->options} 
            WHERE option_name LIKE %s 
            OR option_name LIKE %s",
            '_transient_' . $pattern,
            '_transient_timeout_' . $pattern
        )
    );
}
