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

class KNSDD_Data {

    /**
     * Request-level cache to prevent multiple database calls for the same data.
     * @var array
     */
    private static $cache = [];

    private static $tier_groups_by_rule_id = null;

    /**
     * Flushes the static cache.
     * @param string|null $key If provided, only clears a specific key.
     */
    public static function flush_cache( $key = null ) {
        if ( $key !== null ) {
            if ( isset( self::$cache[ $key ] ) ) {
                unset( self::$cache[ $key ] );
            }
        } else {
            self::$cache = [];
        }
    }

    // Grup fonksiyonları
    public static function get_groups() {
        if ( isset( self::$cache['groups'] ) ) {
            return self::$cache['groups'];
        }
        self::$cache['groups'] = get_option( 'knsdd_groups', array() );
        return self::$cache['groups'];
    }

    /**
     * Belirli bir grubun rule_type'ını döndürür.
     * @param string $group Grup adı
     * @return string 'fixed_discount' veya 'special_campaign'
     */
    public static function get_group_rule_type( $group ) {
        // Güvenlik kontrolü: $group string olmalı
        if ( ! is_string( $group ) || empty( $group ) ) {
            return 'fixed_discount';
        }
        
        // knsdd_group_rule_types option'ından oku (ayrı option)
        $rule_types = get_option( 'knsdd_group_rule_types', [] );
        if ( is_array( $rule_types ) && isset( $rule_types[ $group ] ) ) {
            return $rule_types[ $group ];
        }
        // Varsayılan: fixed_discount
        return 'fixed_discount';
    }

    public static function update_groups( $groups ) {
        $result = update_option( 'knsdd_groups', array_values( array_unique( $groups ) ) );
        self::flush_cache('groups');
        return $result;
    }

    // Kural fonksiyonları
    public static function get_rules_for_group( $group ) {
        $key = 'rules_' . sanitize_key( $group );
        if ( isset( self::$cache[ $key ] ) ) {
            return self::$cache[ $key ];
        }
        self::$cache[ $key ] = get_option( 'knsdd_rules_' . sanitize_key( $group ), array() );
        return self::$cache[ $key ];
    }

    public static function save_rules_for_group( $group, $rules ) {
        $result = update_option( 'knsdd_rules_' . sanitize_key( $group ), $rules );
        self::flush_cache('rules_' . sanitize_key( $group ));
        return $result;
    }

    public static function delete_rules_for_group( $group ) {
        $result = delete_option( 'knsdd_rules_' . sanitize_key( $group ) );
        self::flush_cache('rules_' . sanitize_key( $group ));
        return $result;
    }

    /**
     * Verilen ID'lere sahip kuralları tüm gruplar içinde arayıp bulur.
     * @param array $rule_ids Aranacak kural ID'leri.
     * @return array [rule_id => rule_data] formatında bulunan kuralların haritası.
     */
    public static function get_rules_by_ids( array $rule_ids ) {
        if ( empty( $rule_ids ) ) {
            return [];
        }

        $found_rules = [];
        $ids_to_find = array_flip( $rule_ids ); // Daha hızlı arama için ID'leri anahtar yap

        $all_groups = self::get_groups();
        foreach ( (array) $all_groups as $group ) {
            $rules_in_group = self::get_rules_for_group( $group );
            foreach ( (array) $rules_in_group as $rule ) {
                if ( isset( $rule['rule_id'] ) && isset( $ids_to_find[ $rule['rule_id'] ] ) ) {
                    $found_rules[ $rule['rule_id'] ] = $rule;
                    // Bulunan ID'yi listeden çıkararak sonraki gruplarda boşuna aramayı engelle
                    unset( $ids_to_find[ $rule['rule_id'] ] );
                }
            }
            // Eğer tüm ID'ler bulunduysa döngüden erken çık
            if ( empty( $ids_to_find ) ) {
                break;
            }
        }

        return $found_rules;
    }

    public static function get_tier_group_rule_ids( $rule_id ) {
        if ( null === self::$tier_groups_by_rule_id ) {
            self::$tier_groups_by_rule_id = [];
            $all_groups = self::get_groups();
            foreach ( (array) $all_groups as $group ) {
                $rules = self::get_rules_for_group( $group );
                $tier_groups = [];
                foreach ( (array) $rules as $rule ) {
                    if ( empty( $rule['rule_id'] ) ) {
                        continue;
                    }
                    $rid = $rule['rule_id'];

                    if ( isset( $rule['rule_type'] ) && 'special_campaign' === $rule['rule_type'] ) {
                        if ( ! isset( self::$tier_groups_by_rule_id[ $rid ] ) ) {
                            self::$tier_groups_by_rule_id[ $rid ] = [ $rid ];
                        }
                        continue;
                    }

                    $cat = 0;
                    if ( isset( $rule['category'] ) ) {
                        if ( is_array( $rule['category'] ) ) {
                            $first_cat = reset( $rule['category'] );
                            $cat = absint( $first_cat );
                        } else {
                            $cat = absint( $rule['category'] );
                        }
                    }

                    $products = [];
                    if ( ! empty( $rule['product'] ) && is_array( $rule['product'] ) ) {
                        $products = $rule['product'];
                        sort( $products );
                    }

                    if ( ! $cat && empty( $products ) ) {
                        if ( ! isset( self::$tier_groups_by_rule_id[ $rid ] ) ) {
                            self::$tier_groups_by_rule_id[ $rid ] = [ $rid ];
                        }
                        continue;
                    }

                    $key = $group . '|' . $cat . '|' . implode( ',', $products );
                    if ( ! isset( $tier_groups[ $key ] ) ) {
                        $tier_groups[ $key ] = [];
                    }
                    $tier_groups[ $key ][] = $rid;
                }

                foreach ( $tier_groups as $ids ) {
                    if ( empty( $ids ) ) {
                        continue;
                    }
                    foreach ( $ids as $rid ) {
                        self::$tier_groups_by_rule_id[ $rid ] = $ids;
                    }
                }
            }
        }

        if ( isset( self::$tier_groups_by_rule_id[ $rule_id ] ) ) {
            return self::$tier_groups_by_rule_id[ $rule_id ];
        }

        return [ $rule_id ];
    }

    // Tarih fonksiyonları
    public static function get_all_group_dates() {
        if ( isset( self::$cache['group_dates'] ) ) {
            return self::$cache['group_dates'];
        }
        self::$cache['group_dates'] = get_option( 'knsdd_group_dates', array() );
        return self::$cache['group_dates'];
    }

    public static function get_dates_for_group( $group ) {
        $all_dates = self::get_all_group_dates();
        return isset( $all_dates[ $group ] ) ? $all_dates[ $group ] : array( 'start' => '', 'end' => '' );
    }

    public static function set_dates_for_group( $group, $start_date, $end_date ) {
        $all_dates = self::get_all_group_dates();
        $all_dates[ $group ] = array( 'start' => KNSDD_Utils::ensure_iso_date( $start_date ), 'end'   => KNSDD_Utils::ensure_iso_date( $end_date ), );
        $result = update_option( 'knsdd_group_dates', $all_dates );
        self::flush_cache('group_dates');
        return $result;
    }

    public static function delete_dates_for_group($group) {
        $all_dates = self::get_all_group_dates();
        if ( ! is_array( $all_dates ) ) {
            $all_dates = array();
        }
        unset($all_dates[$group]);
        $result = update_option('knsdd_group_dates', $all_dates);
        self::flush_cache('group_dates');
        return $result;
    }

    // Grup bayrakları (paused vb.)
    public static function get_all_group_flags() {
        if ( isset( self::$cache['group_flags'] ) ) {
            return self::$cache['group_flags'];
        }
        $flags = get_option( 'knsdd_group_flags', array() );
        self::$cache['group_flags'] = is_array( $flags ) ? $flags : array();
        return self::$cache['group_flags'];
    }

    public static function is_group_paused( $group ) {
        $flags = self::get_all_group_flags();
        return ! empty( $flags[ $group ]['paused'] );
    }

    public static function set_group_paused( $group, $paused ) {
        $flags = self::get_all_group_flags();
        if ( ! isset( $flags[ $group ] ) || ! is_array( $flags[ $group ] ) ) {
            $flags[ $group ] = array();
        }
        $flags[ $group ]['paused'] = (bool) $paused;
        $result = update_option( 'knsdd_group_flags', $flags );
        self::flush_cache('group_flags');
        return $result;
    }

    public static function delete_group_flags( $group ) {
        $flags = self::get_all_group_flags();
        if ( isset( $flags[ $group ] ) ) {
            unset( $flags[ $group ] );
            $result = update_option( 'knsdd_group_flags', $flags );
            self::flush_cache('group_flags');
            return $result;
        }
        return false;
    }

    public static function rename_group_flags( $old, $new ) {
        if ( $old === $new ) { return; }
        $flags = self::get_all_group_flags();
        if ( isset( $flags[ $old ] ) ) {
            $flags[ $new ] = $flags[ $old ];
            unset( $flags[ $old ] );
            $result = update_option( 'knsdd_group_flags', $flags );
            self::flush_cache('group_flags');
            return $result;
        }
    }

    /**
     * Kural kullanımlarını toplu olarak veritabanından sorgular.
     * @param array $rule_ids
     * @return array
     */
    public static function get_usage_for_multiple_rules( array $rule_ids ) {
        if ( empty( $rule_ids ) ) {
            return [];
        }

        global $wpdb;
        $table = $wpdb->prefix . 'knsdd_usage_log';
        $results = [];

        // Sanitize rule IDs
        $sanitized_ids = array_map( 'sanitize_text_field', $rule_ids );
        $placeholders = implode( ', ', array_fill( 0, count( $sanitized_ids ), '%s' ) );

        // Get total usage for all requested rules - Sum all discount amounts (positive and negative)
        $sql_total = $wpdb->prepare(
            "SELECT rule_id, 
                    SUM(CASE WHEN discount_amount > 0 THEN 1 WHEN discount_amount < 0 THEN -1 ELSE 0 END) as total,
                    SUM(CASE WHEN discount_amount > 0 AND customer_id > 0 THEN 1 WHEN discount_amount < 0 AND customer_id > 0 THEN -1 ELSE 0 END) as members_only_total
             FROM {$table} WHERE rule_id IN ({$placeholders}) GROUP BY rule_id",
            $sanitized_ids
        );
        $total_usages = $wpdb->get_results( $sql_total, OBJECT_K );
        
        // MySQL senkronizasyon sorunu önleme: Sonuçları zorla array'e çevir
        if ( $total_usages && is_array( $total_usages ) ) {
            $total_usages = array_values( $total_usages );
            $total_usages = array_combine( array_column( (array) $total_usages, 'rule_id' ), $total_usages );
        }

        // Get per-user usage for all requested rules - Sum positive and negative amounts per user
        $sql_users = $wpdb->prepare(
            "SELECT rule_id, customer_id, SUM(CASE WHEN discount_amount > 0 THEN 1 WHEN discount_amount < 0 THEN -1 ELSE 0 END) as count FROM {$table} WHERE rule_id IN ({$placeholders}) AND customer_id > 0 GROUP BY rule_id, customer_id",
            $sanitized_ids
        );
        $user_usages = $wpdb->get_results( $sql_users, ARRAY_A );

        // Initialize results array
        foreach ( $sanitized_ids as $id ) {
            $results[ $id ] = [
                'total' => 0,
                'members_only_total' => 0,
                'users' => [],
            ];
        }

        // Populate with total usages
        if ( $total_usages ) {
            foreach ( $total_usages as $rule_id => $row ) {
                $results[ $rule_id ]['total'] = max(0, (int) $row->total); // Negatif olamaz
                $results[ $rule_id ]['members_only_total'] = max(0, (int) $row->members_only_total); // Negatif olamaz
            }
        }

        // Populate with per-user usages
        if ( $user_usages ) {
            foreach ( $user_usages as $row ) {
                $rule_id = $row['rule_id'];
                $customer_id = $row['customer_id'];
                if ( isset( $results[ $rule_id ] ) ) {
                    $results[ $rule_id ]['users'][ $customer_id ] = max(0, (int) $row['count']); // Negatif olamaz
                }
            }
        }

        return $results;
    }

    /**
     * Yeni: E-posta bazlı kural kullanımını toplu olarak döndürür (net kullanım: pozitif - negatif).
     * @param array $rule_ids
     * @param string $email
     * @return array [rule_id => count]
     */
    public static function get_usage_for_multiple_rules_by_email( array $rule_ids, $email ) {
        if ( empty( $rule_ids ) || empty( $email ) ) {
            return [];
        }

        $email = sanitize_email( $email );
        if ( $email === '' ) { return []; }

        global $wpdb;
        $table = $wpdb->prefix . 'knsdd_usage_log';

        // Sanitize rule IDs
        $sanitized_ids = array_map( 'sanitize_text_field', $rule_ids );
        $placeholders = implode( ', ', array_fill( 0, count( $sanitized_ids ), '%s' ) );

        // Net kullanım hesapla (pozitif - negatif)
        $sql = $wpdb->prepare(
            "SELECT rule_id, SUM(CASE WHEN discount_amount > 0 THEN 1 WHEN discount_amount < 0 THEN -1 ELSE 0 END) as cnt FROM {$table} WHERE rule_id IN ({$placeholders}) AND customer_email = %s GROUP BY rule_id",
            array_merge( $sanitized_ids, [ $email ] )
        );
        $rows = $wpdb->get_results( $sql, ARRAY_A );
        
        // MySQL senkronizasyon sorunu önleme: Sonuçları zorla işle
        if ( $rows && is_array( $rows ) ) {
            $rows = array_values( $rows );
        }

        // Safety Net: If the complex query fails, fall back to the simple one.
        if ( $wpdb->last_error ) {
            $sql_fallback = $wpdb->prepare(
                "SELECT rule_id, COUNT(DISTINCT order_id) as cnt FROM {$table} WHERE rule_id IN ({$placeholders}) AND discount_amount > 0 AND customer_email = %s GROUP BY rule_id",
                array_merge( $sanitized_ids, [ $email ] )
            );
            $rows = $wpdb->get_results( $sql_fallback, ARRAY_A );
        }

        $map = [];
        foreach ( (array) $rows as $row ) {
            $map[ $row['rule_id'] ] = max(0, (int) $row['cnt']); // Negatif olamaz
        }

        // Geri uyumluluk: eski kayıtlar customer_email sütununda olmayabilir → meta'da ara (yavaş ama dar kapsamlı)
        $missing = array_diff( $sanitized_ids, array_keys( $map ) );
        if ( ! empty( $missing ) ) {
            $ph = implode( ', ', array_fill( 0, count( $missing ), '%s' ) );
            // meta JSON içinde '"email":"..."' araması
            $like = '%"email":"' . $wpdb->esc_like( $email ) . '"%';
            $fallback_sql = $wpdb->prepare(
                "SELECT rule_id, COUNT(DISTINCT order_id) as cnt FROM {$table} WHERE rule_id IN ({$ph}) AND discount_amount > 0 AND meta LIKE %s GROUP BY rule_id",
                array_merge( $missing, [ $like ] )
            );
            $fallback_rows = $wpdb->get_results( $fallback_sql, ARRAY_A );
            
            // MySQL senkronizasyon sorunu önleme
            if ( $fallback_rows && is_array( $fallback_rows ) ) {
                $fallback_rows = array_values( $fallback_rows );
            }
            
            foreach ( (array) $fallback_rows as $row ) {
                $map[ $row['rule_id'] ] = (int) $row['cnt'];
            }
        }

        return $map;
    }

    /**
     * Belirtilen gruplar için, verilen müşteri (user_id veya email) bazında
     * daha önce kullanım olup olmadığını döndürür.
     * Kullanım, aynı group_name için discount_amount > 0 kaydı olan herhangi bir sipariş anlamına gelir.
     *
     * @param array $groups
     * @param int $user_id
     * @param string $email
     * @return array [group_name => bool used]
     */
    public static function get_group_usage_for_customer( array $groups, $user_id, $email ) {
        
        if ( empty( $groups ) ) {
            return array();
        }

        global $wpdb;
        $table = $wpdb->prefix . 'knsdd_usage_log';

        // Çıktıyı false ile başlat
        foreach ( $groups as $g ) { $results[ $g ] = false; }

        $placeholders = implode( ', ', array_fill( 0, count( $groups ), '%s' ) );
        $user_id  = (int) $user_id;
        $email    = sanitize_email( $email );

        // 1) user_id > 0 ise, bu kullanıcı için grup bazlı kullanım kontrol et
        if ( $user_id > 0 ) {
            // Önce tüm gruplar için net kullanım hesapla
            $sql_u = $wpdb->prepare(
                "SELECT group_name, SUM(CASE WHEN discount_amount > 0 THEN 1 WHEN discount_amount < 0 THEN -1 ELSE 0 END) as net_usage FROM {$table} WHERE group_name IN ({$placeholders}) AND customer_id = %d GROUP BY group_name",
                array_merge( $groups, [ $user_id ] )
            );
            $rows_u = $wpdb->get_results( $sql_u, ARRAY_A );
            
            // MySQL senkronizasyon sorunu önleme
            if ( $rows_u && is_array( $rows_u ) ) {
                $rows_u = array_values( $rows_u );
            }
            
            // Sonuçları işle - sadece net kullanımı > 0 olanları "kullanılmış" say
            foreach ( (array) $rows_u as $row ) {
                $net_usage = (int) $row['net_usage'];
                if ( isset( $row['group_name'] ) && $net_usage > 0 ) {
                    $results[ $row['group_name'] ] = true;
                }
            }
        }

        // 2) email mevcutsa, email bazında grup net kullanımını da kontrol et (pozitif - negatif)
        if ( $email !== '' ) {
            $sql_e = $wpdb->prepare(
                "SELECT group_name, SUM(CASE WHEN discount_amount > 0 THEN 1 WHEN discount_amount < 0 THEN -1 ELSE 0 END) as net_usage FROM {$table} WHERE group_name IN ({$placeholders}) AND customer_email = %s GROUP BY group_name",
                array_merge( $groups, [ $email ] )
            );
            $rows_e = $wpdb->get_results( $sql_e, ARRAY_A );
            
            // MySQL senkronizasyon sorunu önleme
            if ( $rows_e && is_array( $rows_e ) ) {
                $rows_e = array_values( $rows_e );
            }
            
            foreach ( (array) $rows_e as $row ) {
                $net_usage = (int) $row['net_usage'];
                if ( isset( $row['group_name'] ) && $net_usage > 0 ) {
                    $results[ $row['group_name'] ] = true;
                }
            }
        }

        return $results;
    }

    /**
     * Bu fonksiyon artık doğrudan KNSDD_Tracker tarafından yönetilmektedir.
     * Veritabanına log kaydı atıldığında kullanım otomatik olarak artar.
     * Geriye dönük uyumluluk için boş bırakıldı.
     */
    public static function increment_rule_usage( $rule_id, $customer_id = 0 ) {
        // Bu fonksiyonun içeriği artık KNSDD_Tracker sınıfında.
        // Veritabanına log kaydı atıldığında bu sayımlar dolaylı olarak artmış olur.
        return;
    }

    // YENİ: Genel Ayarlar Fonksiyonu
    /**
     * Eklentinin genel olarak aktif olup olmadığını kontrol eder.
     * @return bool
     */
    public static function is_globally_enabled() {
        if ( isset( self::$cache['global_status'] ) ) {
            return self::$cache['global_status'];
        }
        // Varsayılan olarak eklenti aktiftir.
        $options = get_option( 'knsdd_global_settings', ['global_status' => 1] );
        self::$cache['global_status'] = isset( $options['global_status'] ) ? (bool) $options['global_status'] : true;
        return self::$cache['global_status'];
    }
}
