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

/**
 * Handles AJAX requests related to Group Management.
 */
class KNSDD_Ajax_Groups
{

    public function __construct()
    {
        add_action('wp_ajax_knsdd_add_group', [$this, 'add_group']);
        add_action('wp_ajax_knsdd_delete_group', [$this, 'delete_group']);
        add_action('wp_ajax_knsdd_edit_group', [$this, 'edit_group']);
        add_action('wp_ajax_knsdd_save_group_dates', [$this, 'save_group_dates']);
        add_action('wp_ajax_knsdd_duplicate_group', [$this, 'duplicate_group']);
        add_action('wp_ajax_knsdd_toggle_group_paused', [$this, 'toggle_group_paused']);
        add_action('wp_ajax_knsdd_export_groups', [$this, 'export_groups']);
        add_action('wp_ajax_knsdd_import_groups', [$this, 'import_groups']);
        add_action('wp_ajax_knsdd_bulk_action', [$this, 'bulk_action']);
    }

    private function check_permissions()
    {
        check_ajax_referer('knsdd_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => __('Yetkiniz yok.', 'kns-dynamic-discounts-for-woocommerce')], 403);
        }
    }

    private function invalidate_cache()
    {
        delete_transient('knsdd_all_rules');
        delete_transient('knsdd_active_rules');
        delete_transient('knsdd_notifications');
        delete_transient('knsdd_groups_batch_data'); // Batch cache
        wp_cache_delete('knsdd_groups', 'kns-dynamic-discounts-for-woocommerce');
        wp_cache_delete('knsdd_group_dates', 'kns-dynamic-discounts-for-woocommerce');
        // Tier tablosu ve diğer frontend cache'lerini hemen temizle
        update_option('knsdd_cache_version', time());
    }

    /**
     * Tarih örtüşen grupları filtreler (performans optimizasyonu).
     * 
     * @param array $all_groups Tüm grup adları
     * @param string $my_group Kontrol edilen grup (kendisi hariç)
     * @param string $start Başlangıç tarihi (Y-m-d)
     * @param string $end Bitiş tarihi (Y-m-d)
     * @return array Tarih örtüşen gruplar
     */
    private function filter_overlapping_groups($all_groups, $my_group, $start, $end)
    {
        $relevant = [];

        foreach ($all_groups as $g) {
            // Kendini atla
            if ($g === $my_group) {
                continue;
            }

            $dates = KNSDD_Data::get_dates_for_group($g);
            $g_start = isset($dates['start']) ? $dates['start'] : '';
            $g_end = isset($dates['end']) ? $dates['end'] : '';

            // Tarihsiz grupları dahil et (güvenli taraf - çakışma olabilir)
            if (empty($g_start) || empty($g_end)) {
                $relevant[] = $g;
                continue;
            }

            // Kendi tarihlerimiz boşsa tüm grupları dahil et
            if (empty($start) || empty($end)) {
                $relevant[] = $g;
                continue;
            }

            // Tarih örtüşmesi kontrolü
            // Örtüşme: Başlangıç <= Diğer Bitiş VE Bitiş >= Diğer Başlangıç
            if ($start <= $g_end && $end >= $g_start) {
                $relevant[] = $g;
            }
        }

        return $relevant;
    }

    public function add_group()
    {
        $this->check_permissions();

        // ========================================
        // Ücretsiz sürüm limit kontrolü
        // ========================================
        $limit_check = KNSDD_License::check_group_limit();
        if (!$limit_check['allowed']) {
            wp_send_json_error(array(
                'message' => $limit_check['message'],
                'upgrade_url' => KNSDD_License::get_upgrade_url('groups'),
                'is_limit' => true, // Frontend için flag
            ));
        }

        $new_group = isset($_POST['group']) ? sanitize_text_field(wp_unslash($_POST['group'])) : '';
        $rule_type = isset($_POST['rule_type']) ? sanitize_text_field(wp_unslash($_POST['rule_type'])) : '';

        if (empty($new_group)) {
            wp_send_json_error(['message' => __('Grup adı boş olamaz.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        // Kural tipi kontrolü
        if (empty($rule_type) || !in_array($rule_type, ['fixed_discount', 'special_campaign'], true)) {
            wp_send_json_error(['message' => __('Geçerli bir kural tipi seçmelisiniz.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        $groups = KNSDD_Data::get_groups();
        if (in_array($new_group, $groups, true)) {
            wp_send_json_error(['message' => __('Bu grup adı zaten mevcut.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        $groups[] = $new_group;
        KNSDD_Data::update_groups($groups);
        KNSDD_Data::set_dates_for_group($new_group, '', '');

        // Kural tipini kaydet (ayrı option)
        $rule_types = get_option('knsdd_group_rule_types', []);
        $rule_types[$new_group] = $rule_type;
        update_option('knsdd_group_rule_types', $rule_types);

        $this->invalidate_cache();
        wp_send_json_success(['groups' => $groups]);
    }

    public function delete_group()
    {
        $this->check_permissions();
        $group_to_delete = isset($_POST['group']) ? sanitize_text_field(wp_unslash($_POST['group'])) : '';
        $groups = KNSDD_Data::get_groups();
        $groups = array_diff($groups, [$group_to_delete]);
        KNSDD_Data::update_groups($groups);
        KNSDD_Data::delete_rules_for_group($group_to_delete);
        KNSDD_Data::delete_dates_for_group($group_to_delete);
        KNSDD_Data::delete_group_flags($group_to_delete);

        // Rule type'ı da sil
        $rule_types = get_option('knsdd_group_rule_types', []);
        if (isset($rule_types[$group_to_delete])) {
            unset($rule_types[$group_to_delete]);
            update_option('knsdd_group_rule_types', $rule_types);
        }

        // NOT: usage_log kayıtları silinmez - uzun dönem kullanım analizi için korunur
        // Bu gruba ait bildirimleri temizle
        if (class_exists('KNSDD_Notifications')) {
            KNSDD_Notifications::clear_notifications_for_group($group_to_delete);
        }
        // İstatistik cache'lerini de temizlet (mevcut yöneticide hook bağlı)
        do_action('knsdd_group_updated', $group_to_delete);
        $this->invalidate_cache();
        wp_send_json_success(['groups' => array_values($groups)]);
    }

    public function edit_group()
    {
        $this->check_permissions();
        $old_name = isset($_POST['old_group']) ? sanitize_text_field(wp_unslash($_POST['old_group'])) : '';
        $new_name = isset($_POST['new_group']) ? sanitize_text_field(wp_unslash($_POST['new_group'])) : '';
        if (empty($old_name) || empty($new_name)) {
            wp_send_json_error(['message' => __('Grup adları boş olamaz.', 'kns-dynamic-discounts-for-woocommerce')]);
        }
        $groups = KNSDD_Data::get_groups();
        if ($new_name !== $old_name && in_array($new_name, $groups, true)) {
            wp_send_json_error(['message' => __('Bu grup adı zaten mevcut.', 'kns-dynamic-discounts-for-woocommerce')]);
        }
        $key = array_search($old_name, $groups, true);
        if (false !== $key) {
            $groups[$key] = $new_name;
            KNSDD_Data::update_groups($groups);
            $rules = KNSDD_Data::get_rules_for_group($old_name);
            KNSDD_Data::save_rules_for_group($new_name, $rules);
            KNSDD_Data::delete_rules_for_group($old_name);
            $dates = KNSDD_Data::get_dates_for_group($old_name);
            KNSDD_Data::set_dates_for_group($new_name, $dates['start'], $dates['end']);
            KNSDD_Data::delete_dates_for_group($old_name);
            KNSDD_Data::rename_group_flags($old_name, $new_name);

            // Rule type'ı da taşı
            $rule_types = get_option('knsdd_group_rule_types', []);
            if (isset($rule_types[$old_name])) {
                $rule_types[$new_name] = $rule_types[$old_name];
                unset($rule_types[$old_name]);
                update_option('knsdd_group_rule_types', $rule_types);
            }

            // Yeni: usage_log içinde group_name değerlerini de yeniden adlandır
            if (class_exists('KNSDD_Database') && is_callable(['KNSDD_Database', 'rename_group'])) {
                KNSDD_Database::rename_group($old_name, $new_name);
            }
            // Cache invalidation için olay yayınla
            do_action('knsdd_group_updated', $new_name);
            $this->invalidate_cache();
            wp_send_json_success(['groups' => $groups, 'new_group' => $new_name]);
        } else {
            wp_send_json_error(['message' => __('Grup bulunamadı.', 'kns-dynamic-discounts-for-woocommerce')]);
        }
    }

    public function save_group_dates()
    {
        $this->check_permissions();
        $group = isset($_POST['group']) ? sanitize_text_field(wp_unslash($_POST['group'])) : '';
        $start = isset($_POST['start']) ? sanitize_text_field(wp_unslash($_POST['start'])) : '';
        $end = isset($_POST['end']) ? sanitize_text_field(wp_unslash($_POST['end'])) : '';
        if (empty($group)) {
            wp_send_json_error(['message' => __('Grup belirtilmedi.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        // --- VALIDATION: Mevcut kampanya durumunu kontrol et ---
        $existing_dates = KNSDD_Data::get_dates_for_group($group);
        $existing_start = isset($existing_dates['start']) ? $existing_dates['start'] : '';
        $existing_end = isset($existing_dates['end']) ? $existing_dates['end'] : '';
        $today = current_time('Y-m-d');

        // KURAL 1: Başlamış kampanyaların başlangıç tarihi değiştirilemez (Ayar ile kontrol edilir)
        // NOT: Sadece başlangıç ve bitiş HER İKİSİ de varsa kampanya "başlamış" sayılır
        // Bitiş yoksa düzenleme aşamasında, serbest bırak
        $global_settings = get_option('knsdd_global_settings', array());
        $lock_started_campaigns = isset($global_settings['lock_started_campaigns']) ? (int) $global_settings['lock_started_campaigns'] : 1;

        if (!empty($existing_start) && !empty($existing_end) && $existing_start <= $today) {
            // Kampanya başlamış (başlangıç tarihi bugün veya geçmiş VE bitiş tarihi var)

            // Başlangıç kilidi ayarı aktifse kontrol et
            if ($lock_started_campaigns === 1 && $start !== $existing_start) {
                // Başlangıç tarihini değiştirmeye çalışıyor
                wp_send_json_error([
                    'code' => 'started_campaign_start_locked',
                    'message' => __('Başlamış kampanyaların başlangıç tarihi değiştirilemez.', 'kns-dynamic-discounts-for-woocommerce')
                ]);
            }

            // KURAL 2: Başlamış kampanyaların bitiş tarihi bugünden öncesine alınamaz (Her zaman kontrol edilir)
            if (!empty($end) && $end < $today) {
                wp_send_json_error([
                    'code' => 'end_date_cannot_be_past',
                    'message' => __('Başlamış kampanyanın bitiş tarihi bugünden önce olamaz.', 'kns-dynamic-discounts-for-woocommerce')
                ]);
            }
        }

        // KURAL 3: Tamamlanmış kampanyaların tarihleri tamamen kilitli
        if (!empty($existing_end) && $existing_end < $today) {
            wp_send_json_error([
                'code' => 'expired_campaign_locked',
                'message' => __('Tamamlanmış kampanyaların tarihleri değiştirilemez.', 'kns-dynamic-discounts-for-woocommerce')
            ]);
        }

        // --- VALIDATION: Geçmiş tarih kontrolü ---
        // NOT: Sadece tarih DEĞİŞTİĞİNDE kontrol et
        // Mevcut tarih zaten geçmişse (değişmiyorsa) izin ver

        // Başlangıç: Yeni tarih mi ve geçmiş mi?
        if (!empty($start) && $start !== $existing_start && $start < $today) {
            wp_send_json_error([
                'code' => 'past_date_not_allowed',
                'message' => __('Başlangıç tarihi bugünden önce olamaz.', 'kns-dynamic-discounts-for-woocommerce')
            ]);
        }

        // Bitiş: Yeni tarih mi ve geçmiş mi?
        if (!empty($end) && $end !== $existing_end && $end < $today) {
            wp_send_json_error([
                'code' => 'past_date_not_allowed',
                'message' => __('Bitiş tarihi bugünden önce olamaz.', 'kns-dynamic-discounts-for-woocommerce')
            ]);
        }

        // --- VALIDATION: Başlangıç tarihi bitiş tarihinden sonra olamaz ---
        if (!empty($start) && !empty($end) && $start > $end) {
            wp_send_json_error([
                'code' => 'invalid_date_range',
                'message' => __('Başlangıç tarihi, bitiş tarihinden sonra olamaz.', 'kns-dynamic-discounts-for-woocommerce')
            ]);
        }

        // --- VALIDATION: Prevent setting dates that create cross-group scope conflicts (shared) ---
        // PERFORMANCE OPTIMIZATION: Sadece tarih örtüşen grupları kontrol et
        $all_groups = KNSDD_Data::get_groups();

        // Tarih örtüşen grupları filtrele
        $relevant_groups = $this->filter_overlapping_groups($all_groups, $group, $start, $end);

        $preloaded_data = ['dates' => [], 'rules' => []];

        foreach ($relevant_groups as $g) {
            $preloaded_data['dates'][$g] = KNSDD_Data::get_dates_for_group($g);
            $preloaded_data['rules'][$g] = KNSDD_Data::get_rules_for_group($g);
        }

        // Güvenlik: Grup verileri yoksa boş array kullan
        $my_rules = isset($preloaded_data['rules'][$group]) ? $preloaded_data['rules'][$group] : [];
        list($my_category_only, $my_product_ids, $my_category_only_ranges) = KNSDD_Conflicts::build_sets_from_rules($my_rules);

        $result = KNSDD_Conflicts::check_cross_group_conflict(
            $group,
            $start,
            $end,
            [$my_category_only, $my_product_ids, $my_category_only_ranges],
            $preloaded_data
        );

        if (isset($result['conflict']) && $result['conflict']) {
            $conflict_with = isset($result['with']) ? $result['with'] : '';

            // Eğer karşı grubun adı boş gelirse daha genel bir mesaj göster.
            if (!empty($conflict_with)) {
                $msg = sprintf(__("Seçilen tarih aralığı, '%s' grubunun tarih aralığı ile çakışıyor ve kural kapsamı çakışması tespit edildi. Lütfen tarihleri veya kapsamı değiştirin.", 'kns-dynamic-discounts-for-woocommerce'), $conflict_with);
            } else {
                $msg = __('Seçilen tarih aralığı, diğer bir grubun tarih aralığı ile çakışıyor ve kural kapsamı çakışması tespit edildi. Lütfen tarihleri veya kapsamı değiştirin.', 'kns-dynamic-discounts-for-woocommerce');
            }
            wp_send_json_error([
                'code' => 'cross_group_scope_conflict',
                'with' => $conflict_with,
                'message' => $msg,
            ]);
        }

        // No conflicts, proceed to save
        KNSDD_Data::set_dates_for_group($group, $start, $end);
        $dates = KNSDD_Data::get_dates_for_group($group);
        $paused = KNSDD_Data::is_group_paused($group);
        $status_info = KNSDD_Utils::get_group_status_info($dates, $paused);

        // Trigger notification cache invalidation
        do_action('knsdd_group_updated', $group);

        $this->invalidate_cache();
        wp_send_json_success(['message' => __('Tarihler kaydedildi.', 'kns-dynamic-discounts-for-woocommerce'), 'status_info' => $status_info]);
    }

    public function duplicate_group()
    {
        $this->check_permissions();

        $groups = KNSDD_Data::get_groups();
        $limit = KNSDD_License::get_max_groups();

        if (count($groups) >= $limit) {
            wp_send_json_error([
                'message' => sprintf(
                    __('Grup kopyalanamadı. Ücretsiz versiyonda maksimum %d gruba izin verilir. Pro sürüme yükseltin.', 'kns-dynamic-discounts-for-woocommerce'),
                    $limit
                ),
                'upgrade_url' => KNSDD_License::get_upgrade_url('groups'),
                'is_limit' => true,
            ]);
        }

        $original_group = isset($_POST['group']) ? sanitize_text_field(wp_unslash($_POST['group'])) : '';
        if (empty($original_group)) {
            wp_send_json_error(['message' => __('Kopyalanacak grup adı belirtilmedi.', 'kns-dynamic-discounts-for-woocommerce')]);
        }
        $groups = KNSDD_Data::get_groups();
        $new_group_name = $original_group . __('-kopya', 'kns-dynamic-discounts-for-woocommerce');
        $counter = 2;
        while (in_array($new_group_name, $groups, true)) {
            $new_group_name = $original_group . __('-kopya-', 'kns-dynamic-discounts-for-woocommerce') . $counter++;
        }
        $original_key = array_search($original_group, $groups, true);
        if (false !== $original_key) {
            array_splice($groups, $original_key + 1, 0, $new_group_name);
        } else {
            $groups[] = $new_group_name;
        }
        KNSDD_Data::update_groups($groups);
        $rules = KNSDD_Data::get_rules_for_group($original_group);
        KNSDD_Data::save_rules_for_group($new_group_name, $rules);
        // Kopyalanan grup tarihsiz olmalı - kullanıcı manuel tarih seçecek
        KNSDD_Data::set_dates_for_group($new_group_name, '', '');
        // paused bayrağını kopyala
        $orig_paused = KNSDD_Data::is_group_paused($original_group);
        KNSDD_Data::set_group_paused($new_group_name, $orig_paused);

        // Rule type'ı da kopyala
        $rule_types = get_option('knsdd_group_rule_types', []);
        $orig_rule_type = isset($rule_types[$original_group]) ? $rule_types[$original_group] : 'fixed_discount';
        $rule_types[$new_group_name] = $orig_rule_type;
        update_option('knsdd_group_rule_types', $rule_types);
        $all_groups = $groups;
        $data_for_js = ['dates' => [], 'statuses' => [], 'rules' => [], 'paused' => []];
        foreach ($all_groups as $group) {
            $group_dates = KNSDD_Data::get_dates_for_group($group);
            $data_for_js['dates'][$group] = $group_dates;
            $is_paused = KNSDD_Data::is_group_paused($group);
            $data_for_js['paused'][$group] = $is_paused;
            $data_for_js['statuses'][$group] = KNSDD_Utils::get_group_status_info($group_dates, $is_paused);
            $data_for_js['rules'][$group] = KNSDD_Data::get_rules_for_group($group);
        }
        $this->invalidate_cache();
        wp_send_json_success([
            'message' => __('Grup başarıyla kopyalandı.', 'kns-dynamic-discounts-for-woocommerce'),
            'new_group_name' => $new_group_name,
            'groups' => $all_groups,
            'data' => $data_for_js
        ]);
    }

    public function toggle_group_paused()
    {
        $this->check_permissions();
        $group = isset($_POST['group']) ? sanitize_text_field(wp_unslash($_POST['group'])) : '';
        $paused = isset($_POST['paused']) ? (bool) intval($_POST['paused']) : false;
        if (empty($group)) {
            wp_send_json_error(['message' => __('Grup belirtilmedi.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        // --- VALIDATION: Pasif → Aktif yapılıyorsa çakışma kontrolü ---
        if (!$paused) { // Aktif yapılıyor
            $dates = KNSDD_Data::get_dates_for_group($group);
            $start = isset($dates['start']) ? $dates['start'] : '';
            $end = isset($dates['end']) ? $dates['end'] : '';

            // Tarihler varsa çakışma kontrolü yap
            if (!empty($start) && !empty($end)) {
                // PERFORMANCE OPTIMIZATION: Sadece tarih örtüşen grupları kontrol et
                $all_groups = KNSDD_Data::get_groups();
                $relevant_groups = $this->filter_overlapping_groups($all_groups, $group, $start, $end);

                $preloaded_data = ['dates' => [], 'rules' => []];

                foreach ($relevant_groups as $g) {
                    $preloaded_data['dates'][$g] = KNSDD_Data::get_dates_for_group($g);
                    $preloaded_data['rules'][$g] = KNSDD_Data::get_rules_for_group($g);
                }

                // Güvenlik: Grup verileri yoksa boş array kullan
                $my_rules = isset($preloaded_data['rules'][$group]) ? $preloaded_data['rules'][$group] : [];
                list($my_category_only, $my_product_ids, $my_category_only_ranges) = KNSDD_Conflicts::build_sets_from_rules($my_rules);

                // Pass preloaded data to avoid redundant DB queries
                $result = KNSDD_Conflicts::check_cross_group_conflict(
                    $group,
                    $start,
                    $end,
                    [$my_category_only, $my_product_ids, $my_category_only_ranges],
                    $preloaded_data
                );

                if (isset($result['conflict']) && $result['conflict']) {
                    $conflict_with = isset($result['with']) ? $result['with'] : '';

                    // General scope conflict
                    $msg = $conflict_with
                        ? sprintf(__('Bu grubu aktif yapamazsınız. "%s" grubu ile kapsam çakışması var. Önce tarihleri veya kuralları düzenleyin.', 'kns-dynamic-discounts-for-woocommerce'), $conflict_with)
                        : __('Bu grubu aktif yapamazsınız. Başka bir grupla kapsam çakışması var. Önce tarihleri veya kuralları düzenleyin.', 'kns-dynamic-discounts-for-woocommerce');
                    wp_send_json_error([
                        'code' => 'cross_group_conflict_on_activate',
                        'with' => $conflict_with,
                        'message' => $msg,
                    ]);
                }

                // BOGO çakışma kontrolü (preloaded data ile)
                $bogo_result = KNSDD_Conflicts::check_bogo_cross_group_conflict($group, $start, $end, $my_rules, $preloaded_data);
                if (isset($bogo_result['conflict']) && $bogo_result['conflict']) {
                    $conflict_with = isset($bogo_result['with']) ? $bogo_result['with'] : '';
                    $msg = $conflict_with
                        ? sprintf(__('Bu grubu aktif yapamazsınız. "%s" grubu ile BOGO çakışması var. Lütfen düzenleyin.', 'kns-dynamic-discounts-for-woocommerce'), $conflict_with)
                        : __('Bu grubu aktif yapamazsınız. Başka bir grupla BOGO çakışması var. Lütfen düzenleyin.', 'kns-dynamic-discounts-for-woocommerce');
                    wp_send_json_error([
                        'code' => 'bogo_conflict_on_activate',
                        'with' => $conflict_with,
                        'message' => $msg,
                    ]);
                }
            }
        }

        KNSDD_Data::set_group_paused($group, $paused);
        $dates = KNSDD_Data::get_dates_for_group($group);
        $status_info = KNSDD_Utils::get_group_status_info($dates, $paused);
        $this->invalidate_cache();
        wp_send_json_success(['message' => __('Durum güncellendi', 'kns-dynamic-discounts-for-woocommerce'), 'status_info' => $status_info]);
    }

    /**
     * Export groups as JSON stream
     * Supports: all, active, filtered (client sends group list)
     */
    public function export_groups()
    {
        $this->check_permissions();

        $export_type = isset($_POST['export_type']) ? sanitize_text_field(wp_unslash($_POST['export_type'])) : 'all';
        $group_list = isset($_POST['group_list']) && is_array($_POST['group_list']) ? array_map('sanitize_text_field', array_map('wp_unslash', $_POST['group_list'])) : [];
        $status_list = isset($_POST['status_list']) && is_array($_POST['status_list']) ? array_map('sanitize_text_field', array_map('wp_unslash', $_POST['status_list'])) : [];

        $all_groups = KNSDD_Data::get_groups();
        $groups_to_export = [];

        switch ($export_type) {
            case 'active':
                foreach ($all_groups as $group) {
                    $dates = KNSDD_Data::get_dates_for_group($group);
                    $paused = KNSDD_Data::is_group_paused($group);
                    $status_info = KNSDD_Utils::get_group_status_info($dates, $paused);
                    if (isset($status_info['status']) && $status_info['status'] === 'open') {
                        $groups_to_export[] = $group;
                    }
                }
                break;
            case 'by_status':
                // Allow only known statuses for safety
                $allowed = array('open', 'closed-pending', 'closed-expired', 'paused', 'closed-incomplete');
                $wanted = array_values(array_intersect($status_list, $allowed));
                if (empty($wanted)) {
                    // Fallback to all if nothing valid provided
                    $groups_to_export = $all_groups;
                    break;
                }
                // Preload cached maps to minimize option lookups
                foreach ($all_groups as $group) {
                    $dates = KNSDD_Data::get_dates_for_group($group);
                    $paused = KNSDD_Data::is_group_paused($group);
                    $status_info = KNSDD_Utils::get_group_status_info($dates, $paused);
                    $bucket = '';
                    if ($paused) {
                        $bucket = 'paused';
                    } elseif (isset($status_info['status']) && $status_info['status'] === 'open') {
                        $bucket = 'open';
                    } elseif (isset($status_info['className']) && $status_info['className'] === 'status-pending') {
                        $bucket = 'closed-pending';
                    } elseif (isset($status_info['className']) && $status_info['className'] === 'status-expired') {
                        $bucket = 'closed-expired';
                    } elseif (isset($status_info['className']) && $status_info['className'] === 'status-incomplete') {
                        $bucket = 'closed-incomplete';
                    }
                    if (in_array($bucket, $wanted, true)) {
                        $groups_to_export[] = $group;
                    }
                }
                break;
            case 'filtered':
                $groups_to_export = array_intersect($all_groups, $group_list);
                break;
            case 'all':
            default:
                $groups_to_export = $all_groups;
                break;
        }

        if (empty($groups_to_export)) {
            wp_send_json_error(['message' => __('Dışa aktarılacak grup bulunamadı.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        // Stream JSON response
        header('Content-Type: application/json; charset=utf-8');
        header('Content-Disposition: attachment; filename="knsdd-groups-export-' . current_time('Y-m-d') . '.json"');
        header('Cache-Control: no-cache, must-revalidate');

        $export_data = [
            'version' => '1.0',
            'exported_at' => current_time('c'),
            'groups' => []
        ];

        foreach ($groups_to_export as $group) {
            $dates = KNSDD_Data::get_dates_for_group($group);
            $rules = KNSDD_Data::get_rules_for_group($group);
            $paused = KNSDD_Data::is_group_paused($group);

            // Grup rule_type'ını al
            $rule_types = get_option('knsdd_group_rule_types', []);
            $rule_type = isset($rule_types[$group]) ? $rule_types[$group] : 'fixed_discount';

            $export_data['groups'][] = [
                'name' => $group,
                'dates' => $dates,
                'paused' => $paused,
                'rules' => $rules,
                'rule_type' => $rule_type
            ];
        }

        echo wp_json_encode($export_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
        exit;
    }

    /**
     * Import groups with dry-run and apply modes
     * Supports conflict detection using existing validation logic
     */
    public function import_groups()
    {
        $this->check_permissions();

        $mode = isset($_POST['mode']) ? sanitize_text_field(wp_unslash($_POST['mode'])) : 'dry_run';
        $import_data = isset($_POST['import_data']) ? wp_unslash($_POST['import_data']) : '';

        if (empty($import_data)) {
            wp_send_json_error(['message' => __('İçe aktarılacak veri bulunamadı.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        // Sanitize import data before json_decode (WordPress.org requirement)
        // Using wp_kses_post to preserve HTML in message fields while removing dangerous content
        $import_data = wp_kses_post($import_data);

        // Parse JSON
        $data = json_decode($import_data, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            wp_send_json_error(['message' => __('Geçersiz JSON formatı: ', 'kns-dynamic-discounts-for-woocommerce') . json_last_error_msg()]);
        }

        if (!isset($data['groups']) || !is_array($data['groups'])) {
            wp_send_json_error(['message' => __('Geçersiz veri formatı: groups anahtarı bulunamadı.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        $groups_to_import = $data['groups'];
        if (empty($groups_to_import)) {
            wp_send_json_error(['message' => __('İçe aktarılacak grup bulunamadı.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        // File size guard (10MB limit)
        if (strlen($import_data) > 10 * 1024 * 1024) {
            wp_send_json_error(['message' => __('Dosya çok büyük (10MB sınırı aşıldı).', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        $validation_report = $this->validate_import_dataset($groups_to_import, isset($data['version']) ? (string) $data['version'] : '');

        if ($mode === 'dry_run') {
            wp_send_json_success([
                'mode' => 'dry_run',
                'report' => $validation_report
            ]);
        } elseif ($mode === 'apply') {
            if (!$validation_report['ok']) {
                wp_send_json_error(['message' => __('Doğrulama hataları nedeniyle içe aktarma durduruldu.', 'kns-dynamic-discounts-for-woocommerce')]);
            }

            $apply_result = $this->apply_import_dataset($groups_to_import);
            wp_send_json_success([
                'mode' => 'apply',
                'report' => $validation_report,
                'apply_result' => $apply_result
            ]);
        } else {
            wp_send_json_error(['message' => __('Geçersiz mod.', 'kns-dynamic-discounts-for-woocommerce')]);
        }
    }

    /**
     * Validate import dataset using existing conflict detection logic
     */
    private function validate_import_dataset($groups_to_import, $data_version = '')
    {
        $errors = [];
        $warnings = [];
        $sanitized_groups = [];

        // Version tolerance: accept major=1, warn on newer minor, reject other majors
        $ver_check = $this->check_import_version($data_version);
        if (isset($ver_check['warnings']) && is_array($ver_check['warnings'])) {
            $warnings = array_merge($warnings, $ver_check['warnings']);
        }
        if (isset($ver_check['ok']) && !$ver_check['ok']) {
            $errors[] = ['code' => 'unsupported_version', 'message' => __('İçe aktarılan dosya sürümü desteklenmiyor. Lütfen aynı ana sürümden (1.x) dışa aktarılmış bir dosya kullanın.', 'kns-dynamic-discounts-for-woocommerce')];
            return [
                'ok' => false,
                'errors' => $errors,
                'warnings' => $warnings,
                'groups_count' => 0,
                'sanitized_groups' => []
            ];
        }

        // Get current database state for cross-group conflict checks
        $existing_groups = KNSDD_Data::get_groups();
        $existing_dataset = [];
        foreach ($existing_groups as $group) {
            $existing_dataset[$group] = [
                'dates' => KNSDD_Data::get_dates_for_group($group),
                'rules' => KNSDD_Data::get_rules_for_group($group)
            ];
        }

        foreach ($groups_to_import as $group_data) {
            $group_name = isset($group_data['name']) ? trim($group_data['name']) : '';
            if (empty($group_name)) {
                $errors[] = ['code' => 'empty_group_name', 'message' => __('Grup adı boş olamaz.', 'kns-dynamic-discounts-for-woocommerce')];
                continue;
            }

            $dates = isset($group_data['dates']) ? (array) $group_data['dates'] : [];
            $start = isset($dates['start']) ? sanitize_text_field($dates['start']) : '';
            $end = isset($dates['end']) ? sanitize_text_field($dates['end']) : '';
            $paused = isset($group_data['paused']) ? (bool) $group_data['paused'] : false;
            $rules = isset($group_data['rules']) ? (array) $group_data['rules'] : [];

            // Grup rule_type'ını al ve validate et
            $rule_type = isset($group_data['rule_type']) ? sanitize_text_field($group_data['rule_type']) : 'fixed_discount';
            if (!in_array($rule_type, ['fixed_discount', 'special_campaign'], true)) {
                $rule_type = 'fixed_discount';
            }

            // Sanitize rules using existing logic from KNSDD_Ajax_Rules (with ext support)
            $sanitized_rules = $this->sanitize_rules_for_import($rules);

            // --- TARİH VALİDASYONU (save_group_dates ile aynı mantık) ---
            $today = current_time('Y-m-d');
            $existing_start = '';
            $existing_end = '';

            // Mevcut grup mu?
            if (in_array($group_name, $existing_groups, true)) {
                $existing_dates = KNSDD_Data::get_dates_for_group($group_name);
                $existing_start = isset($existing_dates['start']) ? $existing_dates['start'] : '';
                $existing_end = isset($existing_dates['end']) ? $existing_dates['end'] : '';
            }

            // KURAL 1: Başlamış kampanyaların başlangıç tarihi değiştirilemez (Ayar ile kontrol edilir)
            $global_settings = get_option('knsdd_global_settings', array());
            $lock_started_campaigns = isset($global_settings['lock_started_campaigns']) ? (int) $global_settings['lock_started_campaigns'] : 1;

            if (!empty($existing_start) && !empty($existing_end) && $existing_start <= $today) {
                // Başlangıç kilidi ayarı aktifse kontrol et
                if ($lock_started_campaigns === 1 && $start !== $existing_start) {
                    $errors[] = [
                        'code' => 'started_campaign_start_locked',
                        'group' => $group_name,
                        'message' => sprintf(__('Grup "%s": Başlamış kampanyaların başlangıç tarihi değiştirilemez.', 'kns-dynamic-discounts-for-woocommerce'), $group_name)
                    ];
                    continue;
                }

                // KURAL 2: Başlamış kampanyaların bitiş tarihi bugünden öncesine alınamaz (Her zaman kontrol edilir)
                if (!empty($end) && $end < $today) {
                    $errors[] = [
                        'code' => 'end_date_cannot_be_past',
                        'group' => $group_name,
                        'message' => sprintf(__('Grup "%s": Başlamış kampanyanın bitiş tarihi bugünden önce olamaz.', 'kns-dynamic-discounts-for-woocommerce'), $group_name)
                    ];
                    continue;
                }
            }

            // KURAL 3: Tamamlanmış kampanyaların tarihleri tamamen kilitli
            if (!empty($existing_end) && $existing_end < $today) {
                $errors[] = [
                    'code' => 'expired_campaign_locked',
                    'group' => $group_name,
                    'message' => sprintf(__('Grup "%s": Tamamlanmış kampanyaların tarihleri değiştirilemez.', 'kns-dynamic-discounts-for-woocommerce'), $group_name)
                ];
                continue;
            }

            // KURAL 4: Geçmiş tarih kontrolü (sadece değiştiğinde)
            if (!empty($start) && $start !== $existing_start && $start < $today) {
                $errors[] = [
                    'code' => 'past_date_not_allowed',
                    'group' => $group_name,
                    'message' => sprintf(__('Grup "%s": Başlangıç tarihi bugünden önce olamaz.', 'kns-dynamic-discounts-for-woocommerce'), $group_name)
                ];
                continue;
            }

            if (!empty($end) && $end !== $existing_end && $end < $today) {
                $errors[] = [
                    'code' => 'past_date_not_allowed',
                    'group' => $group_name,
                    'message' => sprintf(__('Grup "%s": Bitiş tarihi bugünden önce olamaz.', 'kns-dynamic-discounts-for-woocommerce'), $group_name)
                ];
                continue;
            }

            // KURAL 5: Başlangıç tarihi bitiş tarihinden sonra olamaz
            if (!empty($start) && !empty($end) && $start > $end) {
                $errors[] = [
                    'code' => 'invalid_date_range',
                    'group' => $group_name,
                    'message' => sprintf(__('Grup "%s": Başlangıç tarihi, bitiş tarihinden sonra olamaz.', 'kns-dynamic-discounts-for-woocommerce'), $group_name)
                ];
                continue;
            }
            // --- TARİH VALİDASYONU SONU ---

            // Intra-group validation using registry
            $intra_validation = KNSDD_Validator_Registry::validate_intra_group(
                $sanitized_rules,
                'import',
                ['group_name' => $group_name, 'dates' => ['start' => $start, 'end' => $end]]
            );
            if (!$intra_validation['ok']) {
                foreach ($intra_validation['errors'] as $error) {
                    $errors[] = [
                        'code' => $error['code'],
                        'group' => $group_name,
                        'message' => sprintf(__('Grup "%s": %s', 'kns-dynamic-discounts-for-woocommerce'), $group_name, $error['message'])
                    ];
                }
                continue;
            }

            $my_sets = $intra_validation['sets'];

            // Cross-group validation using registry
            $combined_dataset = array_merge($existing_dataset, $sanitized_groups);
            $cross_result = KNSDD_Validator_Registry::validate_cross_group(
                $group_name,
                $start,
                $end,
                $my_sets,
                $sanitized_rules,
                $combined_dataset,
                'import',
                ['existing_dataset' => $existing_dataset, 'import_dataset' => $sanitized_groups]
            );

            if (isset($cross_result['conflict']) && $cross_result['conflict']) {
                $conflict_with = isset($cross_result['with']) ? $cross_result['with'] : '';
                $errors[] = [
                    'code' => 'cross_group_conflict',
                    'group' => $group_name,
                    'with' => $conflict_with,
                    'message' => sprintf(
                        __('Grup "%s": Gruplar arası kapsam çakışması tespit edildi ("%s" grubu ile).', 'kns-dynamic-discounts-for-woocommerce'),
                        $group_name,
                        $conflict_with
                    )
                ];
                continue;
            }

            // BOGO cross-group validation
            $bogo_result = KNSDD_Conflicts::check_bogo_cross_group_conflict_dataset(
                $group_name,
                $start,
                $end,
                $sanitized_rules,
                $combined_dataset
            );

            if (isset($bogo_result['conflict']) && $bogo_result['conflict']) {
                $conflict_with = isset($bogo_result['with']) ? $bogo_result['with'] : '';
                $errors[] = [
                    'code' => 'bogo_cross_group_conflict',
                    'group' => $group_name,
                    'with' => $conflict_with,
                    'message' => sprintf(
                        __('Grup "%s": BOGO çakışması - "%s" grubuyla aynı tetikleyici ürün/kategori kullanılıyor.', 'kns-dynamic-discounts-for-woocommerce'),
                        $group_name,
                        $conflict_with
                    )
                ];
                continue;
            }

            // Group name conflict handling
            if (in_array($group_name, $existing_groups, true)) {
                $warnings[] = [
                    'code' => 'group_name_exists',
                    'group' => $group_name,
                    'message' => sprintf(__('Grup "%s" zaten mevcut - güncellenecek.', 'kns-dynamic-discounts-for-woocommerce'), $group_name)
                ];
            }

            $sanitized_groups[$group_name] = [
                'dates' => ['start' => $start, 'end' => $end],
                'paused' => $paused,
                'rules' => $sanitized_rules,
                'rule_type' => $rule_type
            ];
        }

        return [
            'ok' => empty($errors),
            'errors' => $errors,
            'warnings' => $warnings,
            'groups_count' => count($sanitized_groups),
            'sanitized_groups' => $sanitized_groups
        ];
    }

    /**
     * Apply validated import dataset to database
     */
    private function apply_import_dataset($groups_to_import)
    {
        $validation_result = $this->validate_import_dataset($groups_to_import);
        if (!$validation_result['ok']) {
            return ['success' => false, 'message' => __('Doğrulama başarısız.', 'kns-dynamic-discounts-for-woocommerce')];
        }

        $sanitized_groups = $validation_result['sanitized_groups'];
        $existing_groups = KNSDD_Data::get_groups();
        $updated_groups = $existing_groups;
        $imported_count = 0;
        $updated_count = 0;

        foreach ($sanitized_groups as $group_name => $group_data) {
            $is_new = !in_array($group_name, $existing_groups, true);

            if ($is_new) {
                $updated_groups[] = $group_name;
                $imported_count++;
            } else {
                $updated_count++;
            }

            // Save group data
            KNSDD_Data::save_rules_for_group($group_name, $group_data['rules']);
            KNSDD_Data::set_dates_for_group($group_name, $group_data['dates']['start'], $group_data['dates']['end']);

            // Tamamlanmış kampanyaları otomatik pasif yap
            $dates = array('start' => $group_data['dates']['start'], 'end' => $group_data['dates']['end']);
            $status_info = KNSDD_Utils::get_group_status_info($dates, false);

            if ($status_info['className'] === 'status-expired') {
                // Tamamlanmış, otomatik pasif yap
                KNSDD_Data::set_group_paused($group_name, true);
            } else {
                // Normal durum, import dosyasındaki paused değerini kullan
                KNSDD_Data::set_group_paused($group_name, $group_data['paused']);
            }

            // Grup rule_type'ını kaydet
            $rule_types = get_option('knsdd_group_rule_types', []);
            $rule_types[$group_name] = $group_data['rule_type'];
            update_option('knsdd_group_rule_types', $rule_types);
        }

        // Update groups list once
        KNSDD_Data::update_groups($updated_groups);

        // Single cache invalidation
        $this->invalidate_cache();

        return [
            'success' => true,
            'imported_count' => $imported_count,
            'updated_count' => $updated_count,
            'total_groups' => count($updated_groups),
            'message' => sprintf(
                __('İçe aktarma tamamlandı: %d yeni, %d güncellenen grup.', 'kns-dynamic-discounts-for-woocommerce'),
                $imported_count,
                $updated_count
            )
        ];
    }

    /**
     * Simplified rule sanitization for import (based on KNSDD_Ajax_Rules logic)
     */
    private function sanitize_rules_for_import($rules)
    {
        $sanitized_rules = [];

        foreach ((array) $rules as $rule) {
            if (!is_array($rule))
                continue;

            $rule_id = isset($rule['rule_id']) ? sanitize_text_field($rule['rule_id']) : uniqid('knsdd_');
            $category = isset($rule['category']) ? absint($rule['category']) : null;
            $product = isset($rule['product']) && is_array($rule['product']) ? array_map('absint', $rule['product']) : [];
            $min = isset($rule['min']) ? absint($rule['min']) : 0;
            $max = isset($rule['max']) ? absint($rule['max']) : 0;
            $login_required = isset($rule['login_required']) ? (bool) $rule['login_required'] : false;
            $allowed_customers = isset($rule['allowed_customers']) && is_array($rule['allowed_customers']) ? array_map('absint', $rule['allowed_customers']) : [];
            $total_limit = isset($rule['total_limit']) ? absint($rule['total_limit']) : 0;
            $per_customer_limit = isset($rule['per_customer_limit']) ? absint($rule['per_customer_limit']) : 0;
            // Normalize: If both > 0 and per_customer exceeds total, clamp to total
            if ($total_limit > 0 && $per_customer_limit > 0 && $per_customer_limit > $total_limit) {
                $per_customer_limit = $total_limit;
            }
            $rule_type = isset($rule['rule_type']) ? sanitize_text_field($rule['rule_type']) : 'standard_discount';

            // Sanitize messages structure (including BOGO messages)
            $messages = $this->sanitize_messages_for_import(isset($rule['messages']) ? (array) $rule['messages'] : []);

            $sanitized_rule = [
                'rule_id' => $rule_id,
                'category' => $category,
                'product' => $product,
                'min' => $min,
                'max' => $max,
                'messages' => $messages,
                'login_required' => $login_required,
                'allowed_customers' => $allowed_customers,
                'total_limit' => $total_limit,
                'per_customer_limit' => $per_customer_limit,
                'rule_type' => $rule_type
            ];

            // Handle special campaign fields
            if ($rule_type === 'special_campaign') {
                $sanitized_rule['campaign_type'] = isset($rule['campaign_type']) ? sanitize_text_field($rule['campaign_type']) : '';
                if (isset($rule['buy_x']))
                    $sanitized_rule['buy_x'] = absint($rule['buy_x']);
                if (isset($rule['pay_y']))
                    $sanitized_rule['pay_y'] = absint($rule['pay_y']);
                if (isset($rule['nth']))
                    $sanitized_rule['nth'] = absint($rule['nth']);
                if (isset($rule['min_cart_total']))
                    $sanitized_rule['min_cart_total'] = floatval($rule['min_cart_total']);
                if (isset($rule['discount_value']))
                    $sanitized_rule['discount_value'] = floatval($rule['discount_value']);
                if (isset($rule['discount_type']))
                    $sanitized_rule['discount_type'] = sanitize_text_field($rule['discount_type']);

                // BOGO specific fields (trigger/target)
                if ($sanitized_rule['campaign_type'] === 'buy_x_get_y_discount') {
                    // Trigger
                    if (isset($rule['trigger_type']))
                        $sanitized_rule['trigger_type'] = sanitize_text_field($rule['trigger_type']);
                    if (isset($rule['trigger_quantity']))
                        $sanitized_rule['trigger_quantity'] = absint($rule['trigger_quantity']);
                    if (isset($rule['trigger_products']) && is_array($rule['trigger_products'])) {
                        $sanitized_rule['trigger_products'] = array_filter(array_map('absint', $rule['trigger_products']));
                    }
                    if (isset($rule['trigger_category']))
                        $sanitized_rule['trigger_category'] = absint($rule['trigger_category']);

                    // Target
                    if (isset($rule['target_type']))
                        $sanitized_rule['target_type'] = sanitize_text_field($rule['target_type']);
                    if (isset($rule['target_quantity']))
                        $sanitized_rule['target_quantity'] = absint($rule['target_quantity']);
                    if (isset($rule['target_products']) && is_array($rule['target_products'])) {
                        $sanitized_rule['target_products'] = array_filter(array_map('absint', $rule['target_products']));
                    }
                    if (isset($rule['target_category']))
                        $sanitized_rule['target_category'] = absint($rule['target_category']);
                }
            } else {
                $sanitized_rule['discount_type'] = isset($rule['discount_type']) && 'fixed' === $rule['discount_type'] ? 'fixed' : 'percent';
                $sanitized_rule['discount_value'] = isset($rule['discount_value']) ? floatval($rule['discount_value']) : 0;
            }

            // ext support: collect unknown fields and/or explicit ext
            $known_keys = [
                'rule_id',
                'category',
                'product',
                'min',
                'max',
                'messages',
                'login_required',
                'allowed_customers',
                'total_limit',
                'per_customer_limit',
                'rule_type',
                'campaign_type',
                'buy_x',
                'pay_y',
                'nth',
                'min_cart_total',
                'discount_value',
                'discount_type',
                'trigger_type',
                'trigger_quantity',
                'trigger_products',
                'trigger_category',
                'target_type',
                'target_quantity',
                'target_products',
                'target_category',
                'ext'
            ];
            $extra = array_diff_key((array) $rule, array_flip($known_keys));
            $input_ext = isset($rule['ext']) && is_array($rule['ext']) ? $rule['ext'] : [];
            $merged_ext = array_merge($input_ext, $extra);
            $safe_ext = $this->sanitize_ext_value($merged_ext, 0);
            if (is_array($safe_ext) && !empty($safe_ext)) {
                $sanitized_rule['ext'] = $safe_ext;
            }

            $sanitized_rules[] = $sanitized_rule;
        }

        return $sanitized_rules;
    }

    /**
     * Check import version tolerance. Accepts major=1, warns on newer minor, rejects other majors.
     * @return array { ok: bool, warnings: array[] }
     */
    private function check_import_version($ver)
    {
        $warnings = [];
        $CURRENT = '1.0';
        $cm = 1;
        $cn = 0; // current major/minor
        $ver = (string) $ver;
        if ($ver === '') {
            $warnings[] = ['code' => 'missing_version', 'message' => __('Dışa aktarma sürümü belirtilmemiş (1.0 varsayıldı).', 'kns-dynamic-discounts-for-woocommerce')];
            return ['ok' => true, 'warnings' => $warnings];
        }
        if (!preg_match('/^(\d+)(?:\.(\d+))?/', $ver, $m)) {
            $warnings[] = ['code' => 'invalid_version', 'message' => __('Geçersiz sürüm formatı (1.0 varsayıldı).', 'kns-dynamic-discounts-for-woocommerce')];
            return ['ok' => true, 'warnings' => $warnings];
        }
        $maj = isset($m[1]) ? intval($m[1]) : 1;
        $min = isset($m[2]) ? intval($m[2]) : 0;
        if ($maj !== $cm) {
            return ['ok' => false, 'warnings' => $warnings];
        }
        if ($min > $cn) {
            $warnings[] = ['code' => 'newer_minor', 'message' => sprintf(__('Yeni minör sürüm (%s) içe aktarılıyor. Uyum modunda devam ediliyor.', 'kns-dynamic-discounts-for-woocommerce'), $ver)];
        }
        return ['ok' => true, 'warnings' => $warnings];
    }

    /**
     * Sanitize messages structure for import (supports BOGO messages)
     */
    private function sanitize_messages_for_import($messages)
    {
        $sanitized = [];

        // Helper to sanitize icon data
        $sanitize_icon = function ($icon) {
            if (!is_array($icon))
                return [];
            return [
                'enabled' => isset($icon['enabled']) && filter_var($icon['enabled'], FILTER_VALIDATE_BOOLEAN),
                'pack' => isset($icon['pack']) ? sanitize_text_field($icon['pack']) : 'iconify',
                'value' => isset($icon['value']) ? sanitize_text_field($icon['value']) : 'tabler:star',
                'color' => isset($icon['color']) ? sanitize_hex_color($icon['color']) : '#000000',
                'position' => isset($icon['position']) && in_array($icon['position'], ['before', 'after'], true) ? $icon['position'] : 'before',
                'size' => isset($icon['size']) && in_array($icon['size'], ['sm', 'md', 'lg'], true) ? $icon['size'] : 'md',
            ];
        };

        // Helper to sanitize a single message block
        $sanitize_message_block = function ($msg) use ($sanitize_icon) {
            if (!is_array($msg))
                return null;
            return [
                'text' => isset($msg['text']) ? sanitize_text_field($msg['text']) : '',
                'color' => isset($msg['color']) ? sanitize_hex_color($msg['color']) : '#000000',
                'show' => isset($msg['show']) && filter_var($msg['show'], FILTER_VALIDATE_BOOLEAN),
                'highlight' => isset($msg['highlight']) && filter_var($msg['highlight'], FILTER_VALIDATE_BOOLEAN),
                'icon' => $sanitize_icon(isset($msg['icon']) ? $msg['icon'] : []),
            ];
        };

        // Sanitize product message
        if (isset($messages['product'])) {
            $sanitized['product'] = $sanitize_message_block($messages['product']);
        }

        // Sanitize BOGO trigger message
        if (isset($messages['product_trigger'])) {
            $sanitized['product_trigger'] = $sanitize_message_block($messages['product_trigger']);
        }

        // Sanitize BOGO target message
        if (isset($messages['product_target'])) {
            $sanitized['product_target'] = $sanitize_message_block($messages['product_target']);
        }

        // Sanitize cart message (has additional show_* fields)
        if (isset($messages['cart']) && is_array($messages['cart'])) {
            $cart = $messages['cart'];
            $sanitized['cart'] = [
                'text' => isset($cart['text']) ? sanitize_text_field($cart['text']) : '',
                'color' => isset($cart['color']) ? sanitize_hex_color($cart['color']) : '#000000',
                'show_mini' => isset($cart['show_mini']) && filter_var($cart['show_mini'], FILTER_VALIDATE_BOOLEAN),
                'show_cart' => isset($cart['show_cart']) && filter_var($cart['show_cart'], FILTER_VALIDATE_BOOLEAN),
                'show_checkout' => isset($cart['show_checkout']) && filter_var($cart['show_checkout'], FILTER_VALIDATE_BOOLEAN),
                'highlight' => isset($cart['highlight']) && filter_var($cart['highlight'], FILTER_VALIDATE_BOOLEAN),
                'icon' => $sanitize_icon(isset($cart['icon']) ? $cart['icon'] : []),
            ];
        }

        return $sanitized;
    }

    /**
     * Sanitize unknown extension payload recursively with depth/size constraints.
     * - Depth limit: 2
     * - Max items per level: 50
     * - Key whitelist: [A-Za-z0-9_-]{1,48}
     * - Strings trimmed and sanitized (max len 1024)
     */
    private function sanitize_ext_value($value, $depth = 0)
    {
        if ($depth > 2) {
            return [];
        }
        if (is_array($value)) {
            $out = [];
            $count = 0;
            foreach ($value as $k => $v) {
                if ($count >= 50) {
                    break;
                }
                $key_ok = is_int($k) || (is_string($k) && preg_match('/^[A-Za-z0-9_\-]{1,48}$/', $k));
                if (!$key_ok) {
                    continue;
                }
                $san = $this->sanitize_ext_value($v, $depth + 1);
                if ($san === null) {
                    continue;
                }
                $out[$k] = $san;
                $count++;
            }
            return $out;
        }
        if (is_string($value)) {
            $s = sanitize_text_field($value);
            if (function_exists('mb_substr')) {
                $s = mb_substr($s, 0, 1024);
            } else {
                $s = substr($s, 0, 1024);
            }
            return $s;
        }
        if (is_bool($value)) {
            return (bool) $value;
        }
        if (is_int($value)) {
            return intval($value);
        }
        if (is_float($value)) {
            return floatval($value);
        }
        if (is_numeric($value)) {
            return floatval($value);
        }
        return null;
    }

    /**
     * Toplu işlem AJAX handler
     * İşlemler: delete, export, pause, unpause
     */
    public function bulk_action()
    {
        $this->check_permissions();

        $action = isset($_POST['bulk_action']) ? sanitize_text_field(wp_unslash($_POST['bulk_action'])) : '';
        $groups = isset($_POST['groups']) && is_array($_POST['groups'])
            ? array_map('sanitize_text_field', array_map('wp_unslash', $_POST['groups']))
            : [];

        if (empty($action) || empty($groups)) {
            wp_send_json_error(['message' => __('Geçersiz istek.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        // İzin verilen işlemler
        $allowed_actions = ['delete', 'export', 'pause', 'unpause'];
        if (!in_array($action, $allowed_actions, true)) {
            wp_send_json_error(['message' => __('Geçersiz işlem.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        // Rate limiting: Max 100 grup
        if (count($groups) > 100) {
            wp_send_json_error(['message' => __('Tek seferde en fazla 100 grup işlenebilir.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        // Mevcut gruplarla kesişimi al (güvenlik)
        $all_groups = KNSDD_Data::get_groups();
        $groups = array_values(array_intersect($groups, $all_groups));

        if (empty($groups)) {
            wp_send_json_error(['message' => __('İşlenecek geçerli grup bulunamadı.', 'kns-dynamic-discounts-for-woocommerce')]);
        }

        // Diğer işlemler için batch processing
        $results = [];
        $success_count = 0;
        $error_count = 0;

        foreach ($groups as $group) {
            $result = $this->execute_bulk_action($action, $group);

            if ($result['success']) {
                $success_count++;
            } else {
                $error_count++;
                $results[] = $result;
            }
        }

        // Başarı mesajı
        $message = $this->get_bulk_action_message($action, $success_count, $error_count);

        // Cache temizle
        $this->invalidate_cache();

        wp_send_json_success([
            'message' => $message,
            'success_count' => $success_count,
            'error_count' => $error_count,
            'results' => $results
        ]);
    }

    /**
     * Tek grup için toplu işlem uygula
     */
    private function execute_bulk_action($action, $group)
    {
        switch ($action) {
            case 'delete':
                return $this->bulk_delete_group($group);

            case 'pause':
                return $this->bulk_pause_group($group);

            case 'unpause':
                return $this->bulk_unpause_group($group);

            default:
                return ['success' => false, 'message' => 'Invalid action'];
        }
    }

    /**
     * Grubu sil
     */
    private function bulk_delete_group($group)
    {
        $all_groups = KNSDD_Data::get_groups();

        if (!in_array($group, $all_groups, true)) {
            return [
                'success' => false,
                'group' => $group,
                'message' => sprintf(__('"%s" grubu bulunamadı.', 'kns-dynamic-discounts-for-woocommerce'), $group)
            ];
        }

        // Kuralları sil
        KNSDD_Data::delete_rules_for_group($group);

        // Tarihleri sil
        KNSDD_Data::delete_dates_for_group($group);

        // Bayrakları sil
        KNSDD_Data::delete_group_flags($group);

        // Bildirimleri temizle
        if (class_exists('KNSDD_Notifications')) {
            KNSDD_Notifications::clear_notifications_for_group($group);
        }

        // Gruptan çıkar
        $all_groups = array_values(array_diff($all_groups, [$group]));
        KNSDD_Data::update_groups($all_groups);

        // Hook tetikle
        do_action('knsdd_group_updated', $group);

        return [
            'success' => true,
            'group' => $group,
            'message' => sprintf(__('"%s" grubu silindi.', 'kns-dynamic-discounts-for-woocommerce'), $group)
        ];
    }

    /**
     * Grubu manuel pasif yap
     */
    private function bulk_pause_group($group)
    {
        // Zaten manuel pasif mi?
        if (KNSDD_Data::is_group_paused($group)) {
            return [
                'success' => false,
                'group' => $group,
                'message' => sprintf(__('"%s" zaten manuel pasif.', 'kns-dynamic-discounts-for-woocommerce'), $group)
            ];
        }

        // Tamamlanmış kampanyaları pasif yapma
        $dates = KNSDD_Data::get_dates_for_group($group);
        $status_info = KNSDD_Utils::get_group_status_info($dates);

        if ($status_info['status'] === 'closed-expired') {
            return [
                'success' => false,
                'group' => $group,
                'message' => sprintf(__('"%s" zaten sona ermiş, pasif yapılamaz.', 'kns-dynamic-discounts-for-woocommerce'), $group)
            ];
        }

        // Manuel pasif yap
        KNSDD_Data::set_group_paused($group, true);

        return [
            'success' => true,
            'group' => $group,
            'message' => sprintf(__('"%s" manuel pasif yapıldı.', 'kns-dynamic-discounts-for-woocommerce'), $group)
        ];
    }

    /**
     * Grubu manuel aktif yap
     */
    private function bulk_unpause_group($group)
    {
        // Zaten aktif mi?
        if (!KNSDD_Data::is_group_paused($group)) {
            return [
                'success' => false,
                'group' => $group,
                'message' => sprintf(__('"%s" zaten aktif.', 'kns-dynamic-discounts-for-woocommerce'), $group)
            ];
        }

        // Manuel pasif durumunu kaldır
        KNSDD_Data::set_group_paused($group, false);

        return [
            'success' => true,
            'group' => $group,
            'message' => sprintf(__('"%s" manuel aktif yapıldı.', 'kns-dynamic-discounts-for-woocommerce'), $group)
        ];
    }

    /**
     * Toplu işlem sonuç mesajı
     */
    private function get_bulk_action_message($action, $success_count, $error_count)
    {
        $messages = [
            'delete' => sprintf(
                __('%d grup silindi.', 'kns-dynamic-discounts-for-woocommerce'),
                $success_count
            ),
            'pause' => sprintf(
                __('%d grup manuel pasif yapıldı.', 'kns-dynamic-discounts-for-woocommerce'),
                $success_count
            ),
            'unpause' => sprintf(
                __('%d grup manuel aktif yapıldı.', 'kns-dynamic-discounts-for-woocommerce'),
                $success_count
            )
        ];

        if ($error_count > 0) {
            $messages['delete'] = sprintf(
                __('%1$d grup silindi, %2$d grup silinemedi.', 'kns-dynamic-discounts-for-woocommerce'),
                $success_count,
                $error_count
            );
            $messages['pause'] = sprintf(
                __('%1$d grup manuel pasif yapıldı, %2$d grup işlenemedi.', 'kns-dynamic-discounts-for-woocommerce'),
                $success_count,
                $error_count
            );
            $messages['unpause'] = sprintf(
                __('%1$d grup manuel aktif yapıldı, %2$d grup işlenemedi.', 'kns-dynamic-discounts-for-woocommerce'),
                $success_count,
                $error_count
            );
        }

        return isset($messages[$action]) ? $messages[$action] : __('İşlem tamamlandı.', 'kns-dynamic-discounts-for-woocommerce');
    }
}
