<?php

if (!defined('ABSPATH')) {
    exit;
}

class AIEO_DMM_Brand_Discounts extends AIEO_DMM_Module_Base {

    public function get_id() { return 'brand_discounts'; }
    public function get_label() { return __('Product Discounts', 'ai-eshop-optimizer'); }
    public function get_priority() { return 20; }
    public function get_group() { return 'special_pricing_offers'; }

    
    const META_MONTHLY_BATCH = '_aieo_monthly_offer_batch';

    public function register_hooks() {
        add_action('wp_ajax_aieo_dmm_brand_discount_save',     array($this, 'ajax_save'));
        add_action('wp_ajax_aieo_dmm_brand_discount_delete',   array($this, 'ajax_delete'));
        add_action('wp_ajax_aieo_dmm_search_brand_terms',      array($this, 'ajax_search_brand_terms'));
        
        add_action('wp_ajax_aieo_dmm_csv_upload',              array($this, 'ajax_csv_upload'));
        add_action('wp_ajax_aieo_dmm_csv_process_batch',       array($this, 'ajax_csv_process_batch'));
        add_action('wp_ajax_aieo_dmm_csv_clear',               array($this, 'ajax_csv_clear'));
        
        add_action('wp_ajax_aieo_dmm_save_badge_settings',     array($this, 'ajax_save_badge_settings'));
        
        add_action('wp_ajax_aieo_dmm_save_lowest_price_message', array($this, 'ajax_save_lowest_price_message'));
        
        add_action('wp_ajax_aieo_dmm_save_price_appearance', array($this, 'ajax_save_price_appearance'));
        add_action('wp_enqueue_scripts', array($this, 'enqueue_price_appearance_css'));
        
        
        
        add_action('woocommerce_before_shop_loop_item_title',
            array($this, 'render_archive_monthly_offer_badge'), 13);
        add_action('woocommerce_before_shop_loop_item_title',
            array($this, 'render_archive_new_badge'), 14);
        
        
        
        
        
        
        add_filter('render_block_woocommerce/product-image-gallery',
            array($this, 'inject_single_badges_into_gallery'), 12, 2);
    }

    public function render_subtab() {
        $this->render_template('brand-discounts.php', array(
            'discounts'              => $this->fetch_all(),
            'monthly_offer_count'    => $this->count_monthly_offers(),
            'monthly_offer_active'   => $this->count_active_monthly_offers(),
            'new_product_days'       => (int) AIEO_DMM_Settings::get('new_product_days', 60),
            'new_product_label'      => (string) AIEO_DMM_Settings::get('new_product_label', 'NEW'),
            'monthly_offer_label'    => (string) AIEO_DMM_Settings::get('monthly_offer_label', 'ΠΡΟΣΦΟΡΑ ΤΟΥ ΜΗΝΑ'),
        ));
    }

    
    public function fetch_all() {
        global $wpdb;
        $table = $wpdb->prefix . 'aieo_dmm_brand_discounts';
        if (!aieo_dmm_table_exists($table)) {
            return array();
        }
        
        $rows = $wpdb->get_results("SELECT * FROM {$table} ORDER BY enabled DESC, id DESC", ARRAY_A);
        if (!is_array($rows)) {
            return array();
        }

        $taxonomy = self::get_brand_taxonomy();

        
        foreach ($rows as &$row) {
            $brand_id = isset($row['brand_term_id']) ? (int) $row['brand_term_id'] : 0;
            if ($brand_id > 0 && $taxonomy) {
                $term = get_term($brand_id, $taxonomy);
                $row['brand_label'] = (is_object($term) && !is_wp_error($term)) ? $term->name : '';
            } else {
                $row['brand_label'] = '';
            }

            
            $cat_ids = isset($row['category_term_ids']) ? json_decode((string) $row['category_term_ids'], true) : array();
            if (!is_array($cat_ids)) { $cat_ids = array(); }
            $row['category_term_ids'] = array_map('intval', $cat_ids);
            $row['category_labels']   = array();
            foreach ($row['category_term_ids'] as $cid) {
                $ct = get_term($cid, 'product_cat');
                if (is_object($ct) && !is_wp_error($ct)) {
                    $row['category_labels'][] = $ct->name;
                }
            }

            
            $need_ids = isset($row['need_term_ids']) ? json_decode((string) $row['need_term_ids'], true) : array();
            if (!is_array($need_ids)) { $need_ids = array(); }
            $row['need_term_ids'] = array_map('intval', $need_ids);
            $row['need_labels']   = array();
            if (taxonomy_exists('pa_need')) {
                foreach ($row['need_term_ids'] as $nid) {
                    $nt = get_term($nid, 'pa_need');
                    if (is_object($nt) && !is_wp_error($nt)) {
                        $row['need_labels'][] = $nt->name;
                    }
                }
            }

            $row['rule_operator'] = (isset($row['rule_operator']) && strtoupper($row['rule_operator']) === 'OR') ? 'OR' : 'AND';
        }
        return $rows;
    }

    
    public static function get_brand_taxonomy() {
        static $memo = null;
        if ($memo !== null) {
            return $memo ?: null;
        }

        $candidates = apply_filters('aieo_dmm_brand_taxonomy_candidates', array(
            'product_brand',         
            'yith_product_brand',    
            'pwb-brand',             
            'product_brands',        
            'berocket_brand',        
        ));

        foreach ($candidates as $slug) {
            if (taxonomy_exists($slug)) {
                $memo = $slug;
                return $memo;
            }
        }

        $memo = false;
        return null;
    }

    public function ajax_save() {
        AIEO_DMM::verify_ajax_request();

        global $wpdb;
        $table = $wpdb->prefix . 'aieo_dmm_brand_discounts';
        if (!aieo_dmm_table_exists($table)) {
            wp_send_json_error(array('message' => __('Table missing; deactivate/reactivate the plugin.', 'ai-eshop-optimizer')));
        }

        $id = isset($_POST['id']) ? absint(wp_unslash($_POST['id'])) : 0;

        
        $brand_ids = array();
        if (isset($_POST['brand_term_ids']) && is_array($_POST['brand_term_ids'])) {
            $brand_ids = array_filter(array_map('absint', wp_unslash($_POST['brand_term_ids'])));
        } elseif (isset($_POST['brand_term_id'])) {
            $bid = absint(wp_unslash($_POST['brand_term_id']));
            if ($bid > 0) { $brand_ids[] = $bid; }
        }
        $brand_ids = array_values(array_unique($brand_ids));

        
        $category_ids = array();
        if (isset($_POST['category_term_ids']) && is_array($_POST['category_term_ids'])) {
            $category_ids = array_filter(array_map('absint', wp_unslash($_POST['category_term_ids'])));
        }
        $category_ids = array_values(array_unique($category_ids));

        
        $need_ids = array();
        if (isset($_POST['need_term_ids']) && is_array($_POST['need_term_ids'])) {
            $need_ids = array_filter(array_map('absint', wp_unslash($_POST['need_term_ids'])));
        }
        $need_ids = array_values(array_unique($need_ids));

        
        $rule_operator = isset($_POST['rule_operator']) && sanitize_key(wp_unslash($_POST['rule_operator'])) === 'or' ? 'OR' : 'AND';

        $percent   = isset($_POST['percent']) ? (float) sanitize_text_field(wp_unslash($_POST['percent'])) : 0.0;
        $date_from = isset($_POST['date_from']) ? sanitize_text_field(wp_unslash($_POST['date_from'])) : '';
        $date_to   = isset($_POST['date_to']) ? sanitize_text_field(wp_unslash($_POST['date_to'])) : '';
        $enabled   = !empty($_POST['enabled']) ? 1 : 0;
        $notes     = isset($_POST['notes']) ? sanitize_text_field(wp_unslash($_POST['notes'])) : '';
        $label     = isset($_POST['label']) ? sanitize_text_field(wp_unslash($_POST['label'])) : '';

        
        
        
        
        $min_subtotal       = isset($_POST['min_subtotal']) ? max(0, (float) wp_unslash($_POST['min_subtotal'])) : 0.0;
        $min_subtotal_scope = isset($_POST['min_subtotal_scope']) && sanitize_key(wp_unslash($_POST['min_subtotal_scope'])) === 'targeted' ? 'targeted' : 'cart_total';
        $application_scope  = isset($_POST['application_scope'])  && sanitize_key(wp_unslash($_POST['application_scope'])) === 'whole_cart' ? 'whole_cart' : 'targeted';

        $excluded_brand_ids = isset($_POST['excluded_brand_ids']) && is_array($_POST['excluded_brand_ids'])
            ? array_values(array_unique(array_filter(array_map('absint', wp_unslash($_POST['excluded_brand_ids']))))) : array();
        $excluded_category_ids = isset($_POST['excluded_category_ids']) && is_array($_POST['excluded_category_ids'])
            ? array_values(array_unique(array_filter(array_map('absint', wp_unslash($_POST['excluded_category_ids']))))) : array();
        $excluded_need_ids = isset($_POST['excluded_need_ids']) && is_array($_POST['excluded_need_ids'])
            ? array_values(array_unique(array_filter(array_map('absint', wp_unslash($_POST['excluded_need_ids']))))) : array();
        sort($excluded_brand_ids);
        sort($excluded_category_ids);
        sort($excluded_need_ids);
        $excluded_brand_json    = wp_json_encode($excluded_brand_ids);
        $excluded_category_json = wp_json_encode($excluded_category_ids);
        $excluded_need_json     = wp_json_encode($excluded_need_ids);

        
        
        
        
        $product_ids_pos = AIEO_DMM_Product_Picker::roll_up_to_parents(
            AIEO_DMM_Product_Picker::collect_ids('product_ids')
        );
        $product_ids_neg = AIEO_DMM_Product_Picker::roll_up_to_parents(
            AIEO_DMM_Product_Picker::collect_ids('excluded_product_ids')
        );
        sort($product_ids_pos);
        sort($product_ids_neg);
        $product_ids_pos_json = wp_json_encode($product_ids_pos);
        $product_ids_neg_json = wp_json_encode($product_ids_neg);

        
        
        if (empty($brand_ids) && empty($category_ids) && empty($need_ids)) {
            wp_send_json_error(array('message' => __('Pick at least one brand, category, or need.', 'ai-eshop-optimizer')));
        }
        if ($percent <= 0 || $percent >= 100) {
            wp_send_json_error(array('message' => __('Percent must be between 0 and 100.', 'ai-eshop-optimizer')));
        }

        
        
        
        
        if (empty($brand_ids)) {
            $brand_ids = array(0);
        }

        $taxonomy = self::get_brand_taxonomy() ?: 'product_brand';

        
        if ($id > 0) {
            if (count($brand_ids) !== 1) {
                wp_send_json_error(array('message' => __('Pick exactly one brand (or none + categories) when editing an existing row.', 'ai-eshop-optimizer')));
            }
            $brand_id = $brand_ids[0];
            if ($brand_id > 0) {
                $term = get_term($brand_id, $taxonomy);
                if (!$term || is_wp_error($term)) {
                    wp_send_json_error(array('message' => __('Brand term not found.', 'ai-eshop-optimizer')));
                }
            }
            $data = array(
                'brand_term_id'         => $brand_id,
                'category_term_ids'     => wp_json_encode($category_ids),
                'need_term_ids'         => wp_json_encode($need_ids),
                'rule_operator'         => $rule_operator,
                'percent'               => $percent,
                'date_from'             => $date_from !== '' ? $date_from : null,
                'date_to'               => $date_to !== '' ? $date_to : null,
                'enabled'               => $enabled,
                'notes'                 => $notes,
                'label'                 => $label !== '' ? $label : null,
                'min_subtotal'          => $min_subtotal,
                'min_subtotal_scope'    => $min_subtotal_scope,
                'application_scope'     => $application_scope,
                'excluded_brand_ids'    => $excluded_brand_json,
                'excluded_category_ids' => $excluded_category_json,
                'excluded_need_ids'     => $excluded_need_json,
                'product_ids'           => $product_ids_pos_json,
                'excluded_product_ids'  => $product_ids_neg_json,
            );
            $formats = array('%d','%s','%s','%s','%f','%s','%s','%d','%s','%s','%f','%s','%s','%s','%s','%s','%s','%s');
            $wpdb->update($table, $data, array('id' => $id), $formats, array('%d'));
            AIEO_DMM_Cache::bump_version('brands');
            wp_send_json_success(array(
                'mode'     => 'updated',
                'inserted' => array($this->hydrate_row_for_response($id)),
                'skipped'  => 0,
                'message'  => __('Brand discount updated.', 'ai-eshop-optimizer'),
            ));
        }

        
        $inserted = array();
        $skipped  = array();
        $date_from_sql = $date_from !== '' ? $date_from : null;
        $date_to_sql   = $date_to !== '' ? $date_to : null;

        
        $category_ids_sorted = $category_ids;
        sort($category_ids_sorted);
        $category_json = wp_json_encode($category_ids_sorted);

        $need_ids_sorted = $need_ids;
        sort($need_ids_sorted);
        $need_json = wp_json_encode($need_ids_sorted);

        foreach ($brand_ids as $brand_id) {
            $brand_label = __('(any brand)', 'ai-eshop-optimizer');
            if ($brand_id > 0) {
                $term = get_term($brand_id, $taxonomy);
                if (!$term || is_wp_error($term)) {
                    $skipped[] = array('brand_term_id' => $brand_id, 'reason' => 'not_found');
                    continue;
                }
                $brand_label = $term->name;
            }

            
            
            
            $existing_id = (int) $wpdb->get_var($wpdb->prepare(
                
                "SELECT id FROM {$table}
                 WHERE brand_term_id = %d
                   AND COALESCE(category_term_ids,'[]') = %s
                   AND COALESCE(need_term_ids,'[]')     = %s
                   AND rule_operator = %s
                   AND percent       = %f
                   AND enabled       = %d
                   AND COALESCE(date_from,'') = %s
                   AND COALESCE(date_to,'')   = %s
                   AND COALESCE(notes,'')     = %s
                   AND COALESCE(min_subtotal,0)             = %f
                   AND COALESCE(min_subtotal_scope,'')      = %s
                   AND COALESCE(application_scope,'')       = %s
                   AND COALESCE(excluded_brand_ids,'[]')    = %s
                   AND COALESCE(excluded_category_ids,'[]') = %s
                   AND COALESCE(excluded_need_ids,'[]')     = %s
                   AND COALESCE(product_ids,'[]')           = %s
                   AND COALESCE(excluded_product_ids,'[]')  = %s
                 LIMIT 1",
                $brand_id,
                $category_json,
                $need_json,
                $rule_operator,
                $percent,
                $enabled,
                $date_from_sql !== null ? $date_from_sql : '',
                $date_to_sql   !== null ? $date_to_sql   : '',
                $notes,
                $min_subtotal,
                $min_subtotal_scope,
                $application_scope,
                $excluded_brand_json,
                $excluded_category_json,
                $excluded_need_json,
                $product_ids_pos_json,
                $product_ids_neg_json
            ));

            if ($existing_id > 0) {
                $skipped[] = array(
                    'brand_term_id' => $brand_id,
                    'brand_label'   => $brand_label,
                    'reason'        => 'duplicate',
                    'existing_id'   => $existing_id,
                );
                continue;
            }

            $ok = $wpdb->insert(
                $table,
                array(
                    'brand_term_id'         => $brand_id,
                    'category_term_ids'     => $category_json,
                    'need_term_ids'         => $need_json,
                    'rule_operator'         => $rule_operator,
                    'percent'               => $percent,
                    'date_from'             => $date_from_sql,
                    'date_to'               => $date_to_sql,
                    'enabled'               => $enabled,
                    'notes'                 => $notes,
                    'label'                 => $label !== '' ? $label : null,
                    'min_subtotal'          => $min_subtotal,
                    'min_subtotal_scope'    => $min_subtotal_scope,
                    'application_scope'     => $application_scope,
                    'excluded_brand_ids'    => $excluded_brand_json,
                    'excluded_category_ids' => $excluded_category_json,
                    'excluded_need_ids'     => $excluded_need_json,
                    'product_ids'           => $product_ids_pos_json,
                    'excluded_product_ids'  => $product_ids_neg_json,
                ),
                array('%d','%s','%s','%s','%f','%s','%s','%d','%s','%s','%f','%s','%s','%s','%s','%s','%s','%s')
            );
            if ($ok) {
                $new_id = (int) $wpdb->insert_id;
                $inserted[] = $this->hydrate_row_for_response($new_id);
            } else {
                $skipped[] = array('brand_term_id' => $brand_id, 'reason' => 'db_error');
            }
        }

        if (!empty($inserted)) {
            AIEO_DMM_Cache::bump_version('brands');
        }

        
        $n_ins = count($inserted);
        $n_dup = 0;
        foreach ($skipped as $s) {
            if (isset($s['reason']) && $s['reason'] === 'duplicate') { $n_dup++; }
        }
        $parts = array();
        if ($n_ins > 0) {
            $parts[] = sprintf(
                
                _n('%d discount saved', '%d discounts saved', $n_ins, 'ai-eshop-optimizer'),
                $n_ins
            );
        }
        if ($n_dup > 0) {
            $parts[] = sprintf(
                
                _n('%d skipped as duplicate', '%d skipped as duplicates', $n_dup, 'ai-eshop-optimizer'),
                $n_dup
            );
        }
        $message = !empty($parts)
            ? implode(', ', $parts) . '.'
            : __('Nothing to save.', 'ai-eshop-optimizer');

        wp_send_json_success(array(
            'mode'     => 'inserted',
            'inserted' => $inserted,
            'skipped'  => $skipped,
            'message'  => $message,
        ));
    }

    
    private function hydrate_row_for_response($id) {
        global $wpdb;
        $table = $wpdb->prefix . 'aieo_dmm_brand_discounts';
        
        $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$table} WHERE id = %d", (int) $id), ARRAY_A);
        if (!is_array($row)) {
            return array();
        }
        $tax = self::get_brand_taxonomy() ?: 'product_brand';
        $term = get_term((int) $row['brand_term_id'], $tax);
        $row['brand_label'] = (is_object($term) && !is_wp_error($term)) ? $term->name : '';
        $row['id']          = (int) $row['id'];
        $row['percent']     = (float) $row['percent'];
        $row['enabled']     = (int) $row['enabled'];

        $cat_ids = isset($row['category_term_ids']) ? json_decode((string) $row['category_term_ids'], true) : array();
        if (!is_array($cat_ids)) { $cat_ids = array(); }
        $row['category_term_ids'] = array_map('intval', $cat_ids);
        $row['category_labels']   = array();
        foreach ($row['category_term_ids'] as $cid) {
            $ct = get_term($cid, 'product_cat');
            if (is_object($ct) && !is_wp_error($ct)) {
                $row['category_labels'][] = $ct->name;
            }
        }

        $need_ids = isset($row['need_term_ids']) ? json_decode((string) $row['need_term_ids'], true) : array();
        if (!is_array($need_ids)) { $need_ids = array(); }
        $row['need_term_ids'] = array_map('intval', $need_ids);
        $row['need_labels']   = array();
        if (taxonomy_exists('pa_need')) {
            foreach ($row['need_term_ids'] as $nid) {
                $nt = get_term($nid, 'pa_need');
                if (is_object($nt) && !is_wp_error($nt)) {
                    $row['need_labels'][] = $nt->name;
                }
            }
        }

        return $row;
    }

    public function ajax_delete() {
        AIEO_DMM::verify_ajax_request();

        $id = isset($_POST['id']) ? absint(wp_unslash($_POST['id'])) : 0;
        if ($id <= 0) {
            wp_send_json_error(array('message' => __('Invalid id.', 'ai-eshop-optimizer')));
        }
        global $wpdb;
        $wpdb->delete($wpdb->prefix . 'aieo_dmm_brand_discounts', array('id' => $id), array('%d'));
        AIEO_DMM_Cache::bump_version('brands');
        wp_send_json_success();
    }

    
    public function ajax_search_brand_terms() {
        AIEO_DMM::verify_ajax_request();

        $q = isset($_GET['q']) ? sanitize_text_field(wp_unslash($_GET['q'])) : '';
        $args = array(
            'taxonomy'   => 'product_brand',
            'hide_empty' => false,
            'number'     => 30,
        );
        if ($q !== '') {
            $args['name__like'] = $q;
        }
        $terms = get_terms($args);
        $results = array();
        if (is_array($terms)) {
            foreach ($terms as $term) {
                $results[] = array(
                    'id'   => (int) $term->term_id,
                    'text' => $term->name . ' (' . (int) $term->count . ')',
                );
            }
        }
        wp_send_json(array('results' => $results));
    }

    
    
    
    
    
    
    
    

    public function ajax_csv_upload() {
        AIEO_DMM::verify_ajax_request();
        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(array('message' => __('Insufficient permissions.', 'ai-eshop-optimizer')));
        }
        if (empty($_FILES['csv_file']) || !isset($_FILES['csv_file']['error']) || $_FILES['csv_file']['error'] !== UPLOAD_ERR_OK) {
            wp_send_json_error(array('message' => __('File upload failed.', 'ai-eshop-optimizer')));
        }
        
        $file = $_FILES['csv_file'];
        $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        if ($ext !== 'csv') {
            wp_send_json_error(array('message' => __('Please upload a .csv file.', 'ai-eshop-optimizer')));
        }
        $parsed = $this->parse_csv_for_monthly_offer($file['tmp_name']);
        if (!$parsed['success']) {
            wp_send_json_error(array('message' => $parsed['message']));
        }
        wp_send_json_success(array(
            'batch_id' => $parsed['batch_id'],
            'total'    => $parsed['total'],
        ));
    }

    
    private function parse_csv_for_monthly_offer($file_path) {
        if (!file_exists($file_path)) {
            return array('success' => false, 'message' => __('Temp file missing.', 'ai-eshop-optimizer'));
        }
        $content = (string) file_get_contents($file_path);
        if ($content === '') {
            return array('success' => false, 'message' => __('Empty file.', 'ai-eshop-optimizer'));
        }
        
        $content = str_replace("\xEF\xBB\xBF", '', $content);
        $content = str_replace(array("\r\n", "\r"), "\n", $content);
        $lines = array_values(array_filter(array_map('trim', explode("\n", $content)), function ($l) { return $l !== ''; }));
        if (empty($lines)) {
            return array('success' => false, 'message' => __('Empty CSV.', 'ai-eshop-optimizer'));
        }
        $headers = str_getcsv($lines[0]);
        $headers = array_map(static function ($h) { return trim((string) $h); }, (array) $headers);
        $required = array('Date_From', 'Date_to', 'SKU', 'Percentage_Discount');
        $missing  = array_diff($required, $headers);
        if (!empty($missing)) {
            return array(
                'success' => false,
                
                'message' => sprintf(__('Missing required columns: %s', 'ai-eshop-optimizer'), implode(', ', $missing)),
            );
        }
        $rows = array();
        $col_count = count($headers);
        for ($i = 1, $n = count($lines); $i < $n; $i++) {
            $data = str_getcsv($lines[$i]);
            if (!is_array($data) || count($data) !== $col_count) { continue; }
            $row = array_combine($headers, $data);
            if (!is_array($row)) { continue; }
            $row = array_map(static function ($v) { return trim((string) $v); }, $row);
            $rows[] = $row;
        }
        if (empty($rows)) {
            return array('success' => false, 'message' => __('No valid data rows.', 'ai-eshop-optimizer'));
        }
        $batch_id = 'aieo_monthly_' . time() . '_' . wp_generate_password(8, false);
        set_transient($batch_id, array(
            'rows'      => $rows,
            'total'     => count($rows),
            'processed' => 0,
            'success'   => 0,
            'errors'    => array(),
        ), HOUR_IN_SECONDS);
        return array('success' => true, 'batch_id' => $batch_id, 'total' => count($rows));
    }

    public function ajax_csv_process_batch() {
        AIEO_DMM::verify_ajax_request();
        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(array('message' => __('Insufficient permissions.', 'ai-eshop-optimizer')));
        }
        $batch_id   = isset($_POST['batch_id']) ? sanitize_text_field(wp_unslash($_POST['batch_id'])) : '';
        $batch_size = isset($_POST['batch_size']) ? max(1, min(50, (int) $_POST['batch_size'])) : 10;
        if ($batch_id === '') {
            wp_send_json_error(array('message' => __('Batch id missing.', 'ai-eshop-optimizer')));
        }
        $batch = get_transient($batch_id);
        if (!is_array($batch) || empty($batch['rows'])) {
            wp_send_json_error(array('message' => __('Batch expired or not found.', 'ai-eshop-optimizer')));
        }

        $rows      = $batch['rows'];
        $processed = (int) $batch['processed'];
        $total     = (int) $batch['total'];
        $success   = (int) $batch['success'];
        $errors    = (array) $batch['errors'];

        $end = min($processed + $batch_size, $total);
        for ($i = $processed; $i < $end; $i++) {
            $result = $this->apply_monthly_offer_row($rows[$i], $batch_id);
            if ($result === true) {
                $success++;
            } else {
                $errors[] = '[Row ' . ($i + 2) . '] ' . $result;
            }
        }

        $batch['processed'] = $end;
        $batch['success']   = $success;
        $batch['errors']    = $errors;
        set_transient($batch_id, $batch, HOUR_IN_SECONDS);

        $is_done = ($end >= $total);
        if ($is_done && class_exists('AIEO_DMM_Cache')) {
            AIEO_DMM_Cache::bump_version('brands');
        }

        wp_send_json_success(array(
            'processed'  => $end,
            'total'      => $total,
            'success'    => $success,
            'errors'     => array_slice($errors, -20), 
            'is_done'    => $is_done,
            'percentage' => $total > 0 ? round(($end / $total) * 100, 1) : 100.0,
        ));
    }

    
    private function apply_monthly_offer_row(array $row, $batch_id) {
        $sku        = isset($row['SKU']) ? trim((string) $row['SKU']) : '';
        $date_from  = isset($row['Date_From']) ? trim((string) $row['Date_From']) : '';
        $date_to    = isset($row['Date_to']) ? trim((string) $row['Date_to']) : '';
        $pct_raw    = isset($row['Percentage_Discount']) ? trim((string) $row['Percentage_Discount']) : '';

        if ($sku === '') { return __('SKU is empty', 'ai-eshop-optimizer'); }
        $pct = (float) str_replace(',', '.', $pct_raw);
        if ($pct <= 0 || $pct > 100) {
            
            return sprintf(__('Invalid percentage: %s', 'ai-eshop-optimizer'), $pct_raw);
        }

        $product_id = function_exists('wc_get_product_id_by_sku') ? wc_get_product_id_by_sku($sku) : 0;
        if (!$product_id) {
            
            return sprintf(__('Product not found for SKU: %s', 'ai-eshop-optimizer'), $sku);
        }
        $product = function_exists('wc_get_product') ? wc_get_product($product_id) : null;
        if (!$product) {
            
            return sprintf(__('Unable to load product (SKU: %s)', 'ai-eshop-optimizer'), $sku);
        }

        $regular = (float) $product->get_regular_price();
        if ($regular <= 0) {
            
            return sprintf(__("Product '%s' has no valid regular price", 'ai-eshop-optimizer'), $sku);
        }
        $sale = round($regular - ($regular * $pct / 100), 2);

        
        
        $from_ts = null;
        if ($date_from !== '') {
            $parsed = $this->parse_flex_date($date_from);
            if ($parsed === false) {
                
                return sprintf(__('Invalid Date_From: %s', 'ai-eshop-optimizer'), $date_from);
            }
            if ($parsed >= strtotime('today')) {
                $from_ts = $parsed;
            }
        }
        
        $to_ts = null;
        if ($date_to !== '') {
            $parsed = $this->parse_flex_date($date_to);
            if ($parsed === false) {
                
                return sprintf(__('Invalid Date_to: %s', 'ai-eshop-optimizer'), $date_to);
            }
            $to_ts = strtotime('23:59:59', $parsed);
        }

        try {
            $product->set_sale_price($sale);
            $product->set_date_on_sale_from($from_ts);
            $product->set_date_on_sale_to($to_ts);
            $product->save();
            update_post_meta($product_id, self::META_MONTHLY_BATCH, $batch_id);
            return true;
        } catch (\Exception $e) {
            return 'Save failed: ' . $e->getMessage();
        }
    }

    
    private function parse_flex_date($value) {
        $value = trim((string) $value);
        if ($value === '') { return false; }
        
        if (preg_match('#^(\d{4})-(\d{1,2})-(\d{1,2})$#', $value, $m)) {
            return mktime(0, 0, 0, (int) $m[2], (int) $m[3], (int) $m[1]);
        }
        
        if (preg_match('#^(\d{1,2})[/\-](\d{1,2})[/\-](\d{4})$#', $value, $m)) {
            return mktime(0, 0, 0, (int) $m[2], (int) $m[1], (int) $m[3]);
        }
        return false;
    }

    public function ajax_csv_clear() {
        AIEO_DMM::verify_ajax_request();
        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(array('message' => __('Insufficient permissions.', 'ai-eshop-optimizer')));
        }
        global $wpdb;
        
        $product_ids = $wpdb->get_col($wpdb->prepare(
            "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s",
            self::META_MONTHLY_BATCH
        ));
        $cleared = 0;
        foreach ((array) $product_ids as $pid) {
            $product = function_exists('wc_get_product') ? wc_get_product((int) $pid) : null;
            if (!$product) {
                delete_post_meta((int) $pid, self::META_MONTHLY_BATCH);
                continue;
            }
            $product->set_sale_price('');
            $product->set_date_on_sale_from(null);
            $product->set_date_on_sale_to(null);
            $product->save();
            delete_post_meta((int) $pid, self::META_MONTHLY_BATCH);
            $cleared++;
        }
        if (class_exists('AIEO_DMM_Cache')) {
            AIEO_DMM_Cache::bump_version('brands');
        }
        wp_send_json_success(array(
            'cleared' => $cleared,
            
            'message' => sprintf(__('%d monthly-offer entries cleared.', 'ai-eshop-optimizer'), $cleared),
        ));
    }

    
    public function count_monthly_offers() {
        global $wpdb;
        return (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT post_id) FROM {$wpdb->postmeta} WHERE meta_key = %s",
            self::META_MONTHLY_BATCH
        ));
    }

    
    public function count_active_monthly_offers() {
        global $wpdb;
        $now = current_time('timestamp', true);
        
        return (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT pm.post_id)
             FROM {$wpdb->postmeta} pm
             LEFT JOIN {$wpdb->postmeta} pmf ON pmf.post_id = pm.post_id AND pmf.meta_key = '_sale_price_dates_from'
             LEFT JOIN {$wpdb->postmeta} pmt ON pmt.post_id = pm.post_id AND pmt.meta_key = '_sale_price_dates_to'
             WHERE pm.meta_key = %s
               AND ( pmf.meta_value IS NULL OR pmf.meta_value = '' OR CAST(pmf.meta_value AS UNSIGNED) <= %d )
               AND ( pmt.meta_value IS NULL OR pmt.meta_value = '' OR CAST(pmt.meta_value AS UNSIGNED) >= %d )",
            self::META_MONTHLY_BATCH,
            $now,
            $now
        ));
    }

    public function ajax_save_badge_settings() {
        AIEO_DMM::verify_ajax_request();
        $patch = array();
        if (isset($_POST['new_product_days'])) {
            $patch['new_product_days'] = max(0, min(3650, (int) $_POST['new_product_days']));
        }
        if (isset($_POST['new_product_label'])) {
            $patch['new_product_label'] = sanitize_text_field(wp_unslash((string) $_POST['new_product_label']));
        }
        if (isset($_POST['monthly_offer_label'])) {
            $patch['monthly_offer_label'] = sanitize_text_field(wp_unslash((string) $_POST['monthly_offer_label']));
        }
        if (!empty($patch)) {
            AIEO_DMM_Settings::update($patch);
        }
        wp_send_json_success(array('saved' => array_keys($patch)));
    }

    
    public function ajax_save_lowest_price_message() {
        AIEO_DMM::verify_ajax_request();
        
        $patch = array('lowest_price_message_enabled' => !empty($_POST['lowest_price_message_enabled']));
        if (isset($_POST['lowest_price_message_text'])) {
            $patch['lowest_price_message_text'] = wp_kses_post(wp_unslash((string) $_POST['lowest_price_message_text']));
        }
        if (isset($_POST['lowest_price_tooltip_text'])) {
            $patch['lowest_price_tooltip_text'] = wp_kses_post(wp_unslash((string) $_POST['lowest_price_tooltip_text']));
        }
        if (isset($_POST['lowest_price_message_font_size'])) {
            
            $patch['lowest_price_message_font_size'] = sanitize_text_field(wp_unslash((string) $_POST['lowest_price_message_font_size']));
        }
        if (!empty($patch)) {
            AIEO_DMM_Settings::update($patch);
        }
        wp_send_json_success(array('saved' => array_keys($patch)));
    }

    
    public function ajax_save_price_appearance() {
        AIEO_DMM::verify_ajax_request();
        $patch = array();
        if (isset($_POST['price_layout'])) {
            $patch['price_layout'] = sanitize_key(wp_unslash((string) $_POST['price_layout']));
        }
        foreach (array(
            'price_regular_font_size', 'price_sale_font_size', 'price_regular_color', 'price_sale_color',
            'price_regular_font_size_mobile', 'price_sale_font_size_mobile',
            'price_archive_regular_font_size', 'price_archive_regular_font_size_mobile',
            'price_archive_sale_font_size', 'price_archive_sale_font_size_mobile',
            'price_separator_spacing', 'price_separator_thickness', 'price_separator_color',
        ) as $k) {
            if (isset($_POST[$k])) {
                $patch[$k] = sanitize_text_field(wp_unslash((string) $_POST[$k]));
            }
        }
        $patch['price_sale_bold'] = !empty($_POST['price_sale_bold']);
        $patch['price_separator_enabled'] = !empty($_POST['price_separator_enabled']);
        
        AIEO_DMM_Settings::update($patch);
        wp_send_json_success(array('saved' => array_keys($patch)));
    }

    
    public function enqueue_price_appearance_css() {
        $is_single  = function_exists('is_product') && is_product();
        
        
        $is_listing = (function_exists('is_shop') && is_shop())
            || (function_exists('is_product_taxonomy') && is_product_taxonomy())
            || $is_single;
        if (!$is_single && !$is_listing) { return; }

        $css = '';
        if ($is_single)  { $css .= $this->build_price_appearance_css(); }
        if ($is_listing) { $css .= $this->build_archive_price_css(); }
        if ($css === '') { return; }

        wp_register_style('aieo-dmm-price-appearance', false, array(), defined('AIEO_VERSION') ? AIEO_VERSION : '1.0');
        wp_enqueue_style('aieo-dmm-price-appearance');
        wp_add_inline_style('aieo-dmm-price-appearance', $css);
    }

    
    private function build_price_appearance_css() {
        if (!class_exists('AIEO_DMM_Settings')) { return ''; }
        $layout  = (string) AIEO_DMM_Settings::get('price_layout', 'inline');
        $reg_fs  = (string) AIEO_DMM_Settings::get('price_regular_font_size', '');
        $reg_c   = (string) AIEO_DMM_Settings::get('price_regular_color', '');
        $sale_fs = (string) AIEO_DMM_Settings::get('price_sale_font_size', '');
        $sale_c  = (string) AIEO_DMM_Settings::get('price_sale_color', '');
        $bold    = (bool) AIEO_DMM_Settings::get('price_sale_bold', false);

        $in  = '.ff-order--price .wc-block-components-product-price';
        $css = '';
        
        
        
        $css .= $in . ':not(:has(del)){display:flex;flex-flow:row wrap;align-items:baseline;column-gap:4px;}';
        if ($layout === 'stacked_sale_first' || $layout === 'stacked_regular_first') {
            $css .= $in . ':has(del){display:flex;flex-direction:column;align-items:flex-start;gap:2px;}';
            
            
            
            if ($layout === 'stacked_sale_first') {
                $css .= $in . ' ins{order:1;}' . $in . ' del{order:2;}';
            } else { 
                $css .= $in . ' del{order:1;}' . $in . ' ins{order:2;}';
            }
        }
        if ($reg_fs !== '')  { $css .= $in . ' del,' . $in . ' del .woocommerce-Price-amount{font-size:' . $reg_fs . ';}'; }
        if ($reg_c !== '')   { $css .= $in . ' del,' . $in . ' del .woocommerce-Price-amount{color:' . $reg_c . ';}'; }
        if ($sale_fs !== '') { $css .= $in . ' ins,' . $in . ' ins .woocommerce-Price-amount,' . $in . '>.woocommerce-Price-amount{font-size:' . $sale_fs . ';}'; }
        if ($sale_c !== '')  { $css .= $in . ' ins,' . $in . ' ins .woocommerce-Price-amount,' . $in . '>.woocommerce-Price-amount{color:' . $sale_c . ';}'; }
        if ($bold)           { $css .= $in . ' ins,' . $in . ' ins .woocommerce-Price-amount{font-weight:700;}'; }

        
        $reg_fs_m  = (string) AIEO_DMM_Settings::get('price_regular_font_size_mobile', '');
        $sale_fs_m = (string) AIEO_DMM_Settings::get('price_sale_font_size_mobile', '');
        $mob = '';
        if ($reg_fs_m !== '')  { $mob .= $in . ' del,' . $in . ' del .woocommerce-Price-amount{font-size:' . $reg_fs_m . ';}'; }
        if ($sale_fs_m !== '') { $mob .= $in . ' ins,' . $in . ' ins .woocommerce-Price-amount,' . $in . '>.woocommerce-Price-amount{font-size:' . $sale_fs_m . ';}'; }
        if ($mob !== '') { $css .= '@media (max-width:768px){' . $mob . '}'; }

        
        if (AIEO_DMM_Settings::get('price_separator_enabled', false)) {
            $sp  = (string) AIEO_DMM_Settings::get('price_separator_spacing', '16px');   $sp  = ($sp  !== '') ? $sp  : '16px';
            $th  = (string) AIEO_DMM_Settings::get('price_separator_thickness', '1px');  $th  = ($th  !== '') ? $th  : '1px';
            $col = (string) AIEO_DMM_Settings::get('price_separator_color', '#e0e0e0');  $col = ($col !== '') ? $col : '#e0e0e0';
            $css .= '.ff-order--price{display:block;padding-bottom:' . $sp . ';margin-bottom:' . $sp . ';border-bottom:' . $th . ' solid ' . $col . ';}';
        }
        return $css;
    }

    
    private function build_archive_price_css() {
        if (!class_exists('AIEO_DMM_Settings')) { return ''; }
        $reg_d  = (string) AIEO_DMM_Settings::get('price_archive_regular_font_size', '');
        $reg_m  = (string) AIEO_DMM_Settings::get('price_archive_regular_font_size_mobile', '');
        $sale_d = (string) AIEO_DMM_Settings::get('price_archive_sale_font_size', '');
        $sale_m = (string) AIEO_DMM_Settings::get('price_archive_sale_font_size_mobile', '');
        if ($reg_d === '' && $reg_m === '' && $sale_d === '' && $sale_m === '') { return ''; }

        
        $bases = array(
            'ul.products li.product .price',
            'ul.products li.product .wc-block-components-product-price',
            '.wc-block-product-template li .wc-block-components-product-price',
            '.wp-block-woocommerce-product-template li .wc-block-components-product-price',
        );
        $reg = array(); $sale = array();
        foreach ($bases as $b) {
            $reg[]  = $b . ' del';
            $reg[]  = $b . ' del .woocommerce-Price-amount';
            $sale[] = $b . ' ins';
            $sale[] = $b . ' ins .woocommerce-Price-amount';
            $sale[] = $b . '>.woocommerce-Price-amount';
        }
        $reg_s  = implode(',', $reg);
        $sale_s = implode(',', $sale);

        $css = '';
        if ($reg_d  !== '') { $css .= $reg_s  . '{font-size:' . $reg_d  . ';}'; }
        if ($sale_d !== '') { $css .= $sale_s . '{font-size:' . $sale_d . ';}'; }
        $mob = '';
        if ($reg_m  !== '') { $mob .= $reg_s  . '{font-size:' . $reg_m  . ';}'; }
        if ($sale_m !== '') { $mob .= $sale_s . '{font-size:' . $sale_m . ';}'; }
        if ($mob !== '') { $css .= '@media (max-width:768px){' . $mob . '}'; }
        return $css;
    }

    
    
    

    
    public static function is_monthly_offer_active($product_id) {
        $batch = get_post_meta((int) $product_id, self::META_MONTHLY_BATCH, true);
        if (empty($batch)) { return false; }
        $product = function_exists('wc_get_product') ? wc_get_product((int) $product_id) : null;
        return $product && $product->is_on_sale();
    }

    
    public static function is_new_product($product_id) {
        $days = (int) AIEO_DMM_Settings::get('new_product_days', 60);
        if ($days <= 0) { return false; }
        $post = get_post((int) $product_id);
        if (!$post || $post->post_status !== 'publish') { return false; }
        $age = time() - (int) get_post_time('U', true, $post);
        return $age >= 0 && $age < ($days * DAY_IN_SECONDS);
    }

    public function render_archive_monthly_offer_badge() {
        if (class_exists('AIEO_DMM_Badge_Renderer') && AIEO_DMM_Badge_Renderer::is_enabled()) { return; }
        global $product;
        if (!$product) { return; }
        if (!self::is_monthly_offer_active($product->get_id())) { return; }
        $label = (string) AIEO_DMM_Settings::get('monthly_offer_label', 'ΠΡΟΣΦΟΡΑ ΤΟΥ ΜΗΝΑ');
        echo '<span class="aieo-monthly-offer-badge" aria-label="' . esc_attr($label) . '">'
           . '<span class="aieo-monthly-offer-badge-text">' . esc_html($label) . '</span>'
           . '</span>';
    }

    public function render_archive_new_badge() {
        if (class_exists('AIEO_DMM_Badge_Renderer') && AIEO_DMM_Badge_Renderer::is_enabled()) { return; }
        global $product;
        if (!$product) { return; }
        if (!self::is_new_product($product->get_id())) { return; }
        $label = (string) AIEO_DMM_Settings::get('new_product_label', 'NEW');
        echo '<span class="aieo-new-badge" aria-label="' . esc_attr($label) . '">'
           . '<span class="aieo-new-badge-text">' . esc_html($label) . '</span>'
           . '</span>';
    }

    
    public function inject_single_badges_into_gallery($block_content, $block) {
        if (class_exists('AIEO_DMM_Badge_Renderer') && AIEO_DMM_Badge_Renderer::is_enabled()) { return $block_content; }
        if (!is_singular('product')) { return $block_content; }
        global $product;
        if (!$product) { return $block_content; }
        $pid = $product->get_id();

        $badges = '';
        if (self::is_monthly_offer_active($pid)) {
            $label = (string) AIEO_DMM_Settings::get('monthly_offer_label', 'ΠΡΟΣΦΟΡΑ ΤΟΥ ΜΗΝΑ');
            $badges .= '<span class="aieo-monthly-offer-badge aieo-monthly-offer-badge--single" aria-label="' . esc_attr($label) . '">'
                    . '<span class="aieo-monthly-offer-badge-text">' . esc_html($label) . '</span>'
                    . '</span>';
        }
        if (self::is_new_product($pid)) {
            $label = (string) AIEO_DMM_Settings::get('new_product_label', 'NEW');
            $badges .= '<span class="aieo-new-badge aieo-new-badge--single" aria-label="' . esc_attr($label) . '">'
                    . '<span class="aieo-new-badge-text">' . esc_html($label) . '</span>'
                    . '</span>';
        }
        if ($badges === '') { return $block_content; }

        
        if (preg_match('/^(\s*<[a-zA-Z][^>]*>)(.*)$/s', (string) $block_content, $m)) {
            return $m[1] . $badges . $m[2];
        }
        return $badges . $block_content;
    }
}
