<?php

defined('ABSPATH') || exit;

/**
 * Cashback Management Class
 * Класс управления вывода кешбэка кешбэком
 *
 * Class BfwCashback
 *
 * @version 6.4.0
 */
class BfwCashback
{


    /**
     * Cashback write-off output in the cart
     * Вывод суммы начисления кешбэка в корзине и в оформлении заказа
     *
     * @return array|null
     * @version 6.8.0
     */
    public static function bfw_get_cashback_in_cart(): ?array
    {
        global $wpdb;
        $upto = '';
        $percentUp = '';
        $woocommerce = WC();
        $user_id = get_current_user_id();

        $bfwFunctions = new BfwFunctions();
        $Role = new BfwRoles();
        $bfwSingleProduct = new BfwSingleProduct();

        // Calculate total order amount
        $total_order = $woocommerce->cart->total;
        if (BfwSetting::get('exclude-fees-coupons')) {
            $total_order = $woocommerce->cart->get_subtotal();
        }

        $user_role = $Role->getRole($user_id);
        if (is_user_logged_in()) {
            $user_percent = $user_role['percent'] ?? 0;
        } else {
            $user_percent = BfwRoles::maxPercent();
        }

        // Calculate cashback amount from products
        $cashback_this_order = 0;
        $coupon_deduction = 0;
        $cart_items = $woocommerce->cart->get_cart();

        // Считает сумму всех примененных купонов в корзине не считая бонусных баллов
        $filtered_discounts = self::calculate_coupons_total_except_specific();

        foreach ($cart_items as $cart_item) {
            $product_id = $cart_item['product_id'];
            //Если товар имеет variation_id, значит это вариативный товар
            $variation_id = $cart_item['variation_id'] ?? null;

            $product_cashback_info = $bfwSingleProduct->cashbackFromOneProduct($product_id, $user_id, $variation_id);

            $cashback_this_order += $product_cashback_info['amount'] * $cart_item['quantity'];

            $product_percent = $product_cashback_info['percent'] ?? $user_percent;
        }

        $coupon_deduction = self::calculate_coupon_deduction_with_product_percents(
            $filtered_discounts,
            $cart_items,
            $user_id,
            $user_percent
        );

        if ($user_percent != 0) {
            $cashback_this_order -= $coupon_deduction;

            if (!BfwSetting::get('cashback-for-shipping')) {
                $shipping_total = $woocommerce->cart->shipping_total;
                $cashback_this_order += $shipping_total * $user_percent / 100;
            }
        }

        // Calculate user's role and cashback percentage
        if (is_user_logged_in()) {
            //учитываем в кешбэке баллы, которые хочет списать
            $use_points = BfwPoints::getFastPoints($user_id);

            if ($user_percent != 0) {
                // вычитаем использованные баллы из кешбэка
                $cash_fast = $use_points * $user_percent / 100;
                $cashback_this_order = $cashback_this_order - $cash_fast;
            }

            $total_all = BfwPoints::getSumUserOrders($user_id);
            $sumbudet = $total_all + $total_order;
            $all_role = $wpdb->get_results("SELECT summa_start FROM " . $wpdb->prefix . "bfw_computy");
            $all_role = json_decode(wp_json_encode($all_role), true);
            $all_role = $bfwFunctions::arrayMultisortValue($all_role, 'summa_start', SORT_ASC);
            $summa = 0;
            foreach ($all_role as $a) {
                if ($sumbudet >= $a['summa_start']) {
                    $summa = $a['summa_start'];
                }
            }
          /*  $you_next_role = $wpdb->get_results($wpdb->prepare("SELECT id,name,slug,percent,summa_start FROM " . $wpdb->prefix . "bfw_computy WHERE summa_start=%s",
                $summa));*/
            $this_percent = BfwRoles::getRole($user_id);
            $percent = $this_percent['percent'] ?? 0;
            $percent = apply_filters('bfw-filter-percent-in-cart', $percent, $total_order);
            $cashback_this_order = apply_filters('bfw-cashback-this-order', $cashback_this_order, $total_order,
                $percent);
            
            if (BfwSetting::get('cashback_for_first_order') && (new BfwFunctions())->get_customer_order_count($user_id) === 0) {
                $percent = BfwSetting::get('cashback_for_first_order');
            }
            $percentUp = ' ' . $percent . '%';

            //если используются баллы, то не начисляем кешбэк
            if (BfwSetting::get('yous_balls_no_cashback') && $use_points > 0) {
                $cashback_this_order = 0;
            }

            // Не начисляем кешбэк если применился сторонний купон
            if ($woocommerce->cart->applied_coupons && BfwSetting::get('yous_coupon_no_cashback')) {
                $cart_discount = mb_strtolower(BfwSetting::get('bonus-points-on-cart'));
                if (!in_array($cart_discount, $woocommerce->cart->get_applied_coupons()) or in_array($cart_discount,
                        $woocommerce->cart->get_applied_coupons()) && count($woocommerce->cart->get_applied_coupons()) > 1) {
                    $cashback_this_order = 0;
                }
            }

        } else {
            if (!BfwSetting::get('bonus-in-price-upto')) {
                $upto = __('up to', 'bonus-for-woo');
            }
        }

        if (BfwRoles::isPro() && BfwSetting::get('minimal-amount') && $total_order < BfwSetting::get('minimal-amount') && BfwSetting::get('minimal-amount-cashback')) {
            $cashback_this_order = 0;
        }

        // Return cashback data
        $return = array();
        if ($cashback_this_order > 0) {
            $return['cashback_title'] = sprintf(__('Cashback %s', 'bonus-for-woo'), $upto);
            $return['percentUp'] = $percentUp;
            $return['cashback_this_order'] = BfwPoints::roundPoints($cashback_this_order);
            $return['upto'] = $upto;
        }

        return $return;
    }


    /**
     * When is cashback output displayed in [woocommerce-cart]
     * Когда вывод кешбэка выводится в [woocommerce-cart]
     *
     * @return void
     * @version 6.4.0
     */
    public static function getCashbackInCart(): void
    {
        $return = self::bfw_get_cashback_in_cart();

        // Отладочная информация - временно
        if (defined('WP_DEBUG') && WP_DEBUG) {
            echo '<!-- DEBUG: Cashback data: ' . print_r($return, true) . ' -->';
        }

        if ($return) {
            $cashback_title = esc_html($return['cashback_title']);
            $percent_up = esc_html($return['percentUp']);
            $upto_label = BfwPoints::howLabel(
                $return['upto'],
                $return['cashback_this_order']
            );

            echo '<tr class="order-cashback">'
                . '<th><span class="order-cashback-title">' . $cashback_title . ' ' . $percent_up . '</span></th>'
                . '<td data-title="' . $cashback_title . ' ' . $percent_up . '">'
                . '<span class="order-cashback-value">' . $return['cashback_this_order'] . ' ' . $upto_label . '</span>'
                . '</td>'
                . '</tr>';
        }
    }




    /** Метод для получения HTML кешбэка
     *
     * @return WP_REST_Response
     */
    public static function rest_get_cashback_html(): WP_REST_Response
    {
        // 1. Принудительная инициализация сессии
        if (null === WC()->session) {
            $session_class = apply_filters('woocommerce_session_handler', 'WC_Session_Handler');
            WC()->session = new $session_class();
            WC()->session->init();
        }

        // 2. Принудительная загрузка корзины
        if (null === WC()->cart) {
            WC()->cart = new WC_Cart();
            // Загружаем данные корзины из сессии, чтобы get_cart() не был пустым
            WC()->cart->get_cart();
        }

        $html = '';

        // 3. Вызов расчета кешбэка
        $return = self::bfw_get_cashback_in_cart();

        if (!empty($return) && is_array($return)) {
            $cashback_title = esc_html($return['cashback_title']);
            $percent_up = esc_html($return['percentUp']);

            // Передаем параметры в howLabel (склонение)
            $upto_label = BfwPoints::howLabel(
                $return['upto'] ?? '',
                (float)$return['cashback_this_order']
            );

            $html = '<div class="bfw-order-cashback-title-blocks">' . $cashback_title . $percent_up . '</div>'
                . '<div class="bfw-order-cashback-value-blocks">' . $return['cashback_this_order'] . ' ' . $upto_label . '</div>';
        }

        return new WP_REST_Response(['html' => $html], 200);
    }

    /**
     * Cashback withdrawal when the cart is implemented using blocks.
     * Вывод кешбэка когда корзина реализована с помощью blocks.
     *
     * @return void
     */
    public static function getCashbackInCartBlocks(): void
    {
        $return = self::bfw_get_cashback_in_cart();

        if ($return) {
            $cashback_title = esc_html($return['cashback_title']);
            $percent_up = esc_html($return['percentUp']);
            $upto_label = BfwPoints::howLabel(
                $return['upto'],
                $return['cashback_this_order']
            );

            echo '<div class="bfw-order-cashback-title-blocks">' . $cashback_title . $percent_up . '</div>'
                . '<div class="bfw-order-cashback-value-blocks">' . $return['cashback_this_order'] . ' ' . $upto_label . '</div>';
            exit();
        }
        exit();
    }


    /**
     * When the cashback output is displayed by shortcode.
     * Когда вывод кешбэка выводится шорткодом.
     *
     * @return string
     * @version 6.4.0
     */
    public static function bfwGetCashbackInCartForShortcode(): string
    {
        $return = self::bfw_get_cashback_in_cart();
        if ($return) {
            return '<div class="bfw-how-match-cashback-block">
                 <span class="order-cashback-title">' . $return['cashback_title']
                . $return['percentUp'] . '</span>
            <span class="order-cashback-value">' .
                $return['cashback_this_order'] . ' ' . BfwPoints::howLabel(
                    $return['upto'],
                    $return['cashback_this_order']
                ) . '
            </span>
            </div>';
        }

        return '';
    }


    /**
     * Считает сумму всех примененных купонов в корзине
     *
     * @return float
     */
    public static function calculate_coupons_total_except_specific(): float
    {
        $woo = WC();
        $coupons_total = 0;
        $excluded_coupon = BfwSetting::get('bonus-points-on-cart'); // Купон, который нужно исключить

        // Получаем все примененные купоны
        if (isset($woo->cart) && $woo->cart->get_applied_coupons()) {
            foreach ($woo->cart->get_applied_coupons() as $code) {
                if (mb_strtolower($code) !== mb_strtolower($excluded_coupon)) {
                    $discount = $woo->cart->get_coupon_discount_amount($code);
                    $coupons_total += $discount;
                }
            }
        }
        return $coupons_total;
    }

    private static function calculate_coupon_deduction_with_product_percents(
        $total_discounts,
        $cart_items,
        $user_id,
        $user_percent
    ) {
        $bfwSingleProduct = new BfwSingleProduct();
        $deduction = 0;

        // Получаем общую стоимость товаров (без скидок)
        $cart_subtotal = WC()->cart->get_subtotal();
        if ($cart_subtotal <= 0) {
            return 0;
        }

        foreach ($cart_items as $cart_item) {
            $product_id = $cart_item['product_id'];
            $variation_id = $cart_item['variation_id'] ?? null;
            $line_total = $cart_item['line_total']; // стоимость товара после скидок

            // Получаем процент кешбэка для этого товара
            $product_cashback_info = $bfwSingleProduct->cashbackFromOneProduct($product_id, $user_id, $variation_id);

            // Если метод возвращает массив с percent, используем его, иначе берем сумму и вычисляем процент

            $product_percent = $product_cashback_info['percent'];


            // Распределяем скидки пропорционально стоимости товара
            $product_ratio = $line_total / $cart_subtotal;
            $product_discount_share = $total_discounts * $product_ratio;

            // Вычисляем вычет для этого товара
            $deduction += $product_discount_share * $product_percent / 100;
        }

        return $deduction;
    }


    /** Находим все заказы на которые не начислен кешбэк
     *
     * @return void
     */
    public static function cashbackPrepare()
    {
        check_ajax_referer('bfw_cashback_recount_nonce', 'nonce');

        if (!current_user_can('manage_woocommerce') && !current_user_can('manage_options')) {
            wp_send_json_error(__('Access denied.', 'bonus-for-woo'));
            return;
        }
        $order_status = BfwSetting::get('add_points_order_status', 'completed');
        $cart_discount = mb_strtolower(BfwSetting::get('bonus-points-on-cart'));
        
        // Сначала ищем все заказы нужного статуса без дополнительных условий
        $args_all = [
            'type' => 'shop_order',
            'status' => ['wc-' . $order_status],
            'limit' => -1,
            'return' => 'ids',
        ];
        
        $all_ids = wc_get_orders($args_all);
        
        // Теперь ищем заказы с уже начисленным кешбэком
        $args_with_cashback = [
            'type' => 'shop_order',
            'status' => ['wc-' . $order_status],
            'limit' => -1,
            'return' => 'ids',
            'meta_query' => [
                [
                    'key' => 'cashback_receipt',
                    'compare' => 'EXISTS',
                ],
            ],
        ];
        
        $with_cashback_ids = wc_get_orders($args_with_cashback);
        
        // Получаем заказы без кешбэка
        $ids = array_diff($all_ids, $with_cashback_ids);
        
        // Дополнительно фильтруем заказы с бонусными купонами и исключаем гостевые
        $filtered_ids = [];
        foreach ($ids as $order_id) {
            $order = wc_get_order($order_id);
            if ($order) {
                $user_id = $order->get_customer_id();
                
                // Исключаем гостевые заказы (user_id = 0)
                if ($user_id === 0) {
                    continue;
                }
                
                // Проверяем купоны если нужно
                if (!empty($cart_discount)) {
                    $used_coupons = $order->get_coupon_codes();
                    if (in_array($cart_discount, $used_coupons)) {
                        continue;
                    }
                }
                
                $filtered_ids[] = $order_id;
            }
        }
        $ids = $filtered_ids;
        update_option('cashback_orders_to_recount', $ids);

        wp_send_json([
            'total' => count($ids),
        ]);
    }

    /** Начисление кешбэка за прошлые заказы
     *
     * @return void
     */
    public static function cashbackRecount()
    {
        check_ajax_referer('bfw_cashback_recount_nonce', 'nonce');

        if (!current_user_can('manage_woocommerce') && !current_user_can('manage_options')) {
            wp_send_json_error(__('Access denied.', 'bonus-for-woo'));
            return;
        }
        $batch = 20; // количество заказов за шаг

        $order_ids = get_option('cashback_orders_to_recount', []);
        $offset = intval($_POST['offset'] ?? 0);

        $ids = array_slice($order_ids, $offset, $batch);

        foreach ($ids as $order_id) {
            $order = wc_get_order($order_id);
            // Пропускаем, если кешбэк уже начислен
            if ($order->get_meta('cashback_receipt')) {
                continue;
            }

            BfwPoints::addPointsForOrder($order_id, false);
        }
        $processedTotal = $offset + count($ids);
        wp_send_json([
            'nextOffset' => $offset + $batch,
            'total' => count($order_ids),
            'processedTotal' => $processedTotal,
        ]);
    }



    public static function computyMassAddPoints(): void
    {
        ob_start();
        global $wpdb;
        $wpdb->hide_errors();
        $wpdb->suppress_errors(true);

        if (!current_user_can('manage_options')) {
            wp_send_json_error('Access denied');
        }

        if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'bfw_mass_add')) {
            wp_send_json_error('Security check failed');
        }

        $points = isset($_POST['points']) ? (int) $_POST['points'] : 0;
        $text   = isset($_POST['text']) ? sanitize_text_field($_POST['text']) : '';

        if ($points <= 0 || $points > 10000) {
            wp_send_json_error('Invalid points amount');
        }

        /*
         * 1. Создаем meta computy_point если её нет
         */

        $wpdb->query("
        INSERT INTO {$wpdb->usermeta} (user_id, meta_key, meta_value)
        SELECT ID, 'computy_point', 0
        FROM {$wpdb->users}
        WHERE ID NOT IN (
            SELECT user_id
            FROM {$wpdb->usermeta}
            WHERE meta_key = 'computy_point'
        )
    ");

        /*
         * 2. Начисляем баллы всем пользователям,
         * которым ещё не начисляли (нет f14)
         */

        $wpdb->query(
            $wpdb->prepare("
            UPDATE {$wpdb->usermeta} p
            LEFT JOIN {$wpdb->usermeta} f
                ON f.user_id = p.user_id
                AND f.meta_key = 'f14'
            SET p.meta_value = p.meta_value + %d
            WHERE p.meta_key = 'computy_point'
            AND f.umeta_id IS NULL
        ", $points)
        );

        /*
         * 3. Помечаем что начислили
         */

        $wpdb->query("
        INSERT INTO {$wpdb->usermeta} (user_id, meta_key, meta_value)
        SELECT user_id, 'f14', 'yes'
        FROM {$wpdb->usermeta}
        WHERE meta_key = 'computy_point'
        AND user_id NOT IN (
            SELECT user_id
            FROM {$wpdb->usermeta}
            WHERE meta_key = 'f14'
        )
    ");

        /*
         * 4. История (опционально)
         */

        if (class_exists('BfwHistory')) {

            $user_ids = $wpdb->get_col("
            SELECT user_id
            FROM {$wpdb->usermeta}
            WHERE meta_key = 'f14'
        ");

            foreach ($user_ids as $user_id) {
                BfwHistory::add_history(
                    $user_id,
                    '+',
                    $points,
                    '0',
                    $text
                );
            }
        }

        // удаляем временную метку
        $wpdb->query("
    DELETE FROM {$wpdb->usermeta}
    WHERE meta_key = 'f14'
");

        while (ob_get_level()) {
            ob_end_clean();
        }

        wp_send_json_success([
            'done' => true
        ]);
    }


    /**
     * @return void
     */
    public static function recount_user_orders()
    {
        check_ajax_referer( 'bfw_recount_nonce', 'nonce' );

        wp_send_json_success( array( 'message' => 'Сумма пересчитана' ) );
    }

}
