<?php
/**
 * Blocked Country Model
 *
 * Manages country-level blocking with database operations
 *
 * @package VMPFence
 * @since 2.2.0
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Blocked Country Management Class
 * 
 * Handles CRUD operations for country blocking
 */
class VMPFence_Blocked_Country {

    /**
     * Table name (without prefix)
     */
    private static $table_name = 'vmpfence_blocked_countries';
    
    /**
     * Logs table name (without prefix)
     */
    private static $logs_table_name = 'vmpfence_country_block_logs';

    /**
     * Add a blocked country
     * 
     * @param string $country_code ISO 3166-1 alpha-2 code
     * @param string $country_name Country display name
     * @param string $reason Reason for blocking
     * @param int $block_login Block login (1) or not (0)
     * @param int $block_site Block entire site (1) or not (0)
     * @param int $blocked_until Unix timestamp (0 = permanent)
     * @return int|false Insert ID on success, false on failure
     */
    public static function add_blocked_country($country_code, $country_name, $reason = '', $block_login = 1, $block_site = 0, $blocked_until = 0) {
        global $wpdb;
        
        // Validate country code
        $country_code = strtoupper(sanitize_text_field($country_code));
        if (!preg_match('/^[A-Z]{2}$/', $country_code)) {
            return false;
        }
        
        $table = $wpdb->prefix . self::$table_name;
        
        // Check if already exists
        $exists = $wpdb->get_var($wpdb->prepare(
            "SELECT id FROM {$table} WHERE country_code = %s",
            $country_code
        ));
        
        if ($exists) {
            // Update existing
            return self::update_blocked_country($country_code, [
                'block_login' => $block_login,
                'block_site' => $block_site,
                'reason' => $reason,
                'is_active' => 1
            ]);
        }
        
        // Insert new
        $result = $wpdb->insert(
            $table,
            [
                'country_code' => $country_code,
                'country_name' => sanitize_text_field($country_name),
                'block_login' => (int)$block_login,
                'block_site' => (int)$block_site,
                'reason' => sanitize_textarea_field($reason),
                'blocked_at' => time(),
                'blocked_until' => (int)$blocked_until,
                'is_active' => 1,
                'source' => 'local',
                'block_count' => 0
            ],
            ['%s', '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%s', '%d']
        );
        
        if ($result) {
            // Clear cache
            self::clear_cache();
            
            // Log
            if (class_exists('VMPFence_Secure_Logger')) {
                VMPFence_Secure_Logger::info("Country blocked: {$country_name} ({$country_code})", [
                    'block_login' => $block_login,
                    'block_site' => $block_site
                ]);
            }
            
            return $wpdb->insert_id;
        }
        
        return false;
    }

    /**
     * Check if a country is blocked
     * 
     * @param string $country_code ISO alpha-2 code
     * @return array|false Country data if blocked, false if not
     */
    public static function is_country_blocked($country_code) {
        global $wpdb;
        
        $country_code = strtoupper(sanitize_text_field($country_code));
        $table = $wpdb->prefix . self::$table_name;
        
        // Try cache first
        $cache_key = 'vmpfence_blocked_country_' . $country_code;
        $cached = wp_cache_get($cache_key);
        
        if ($cached !== false) {
            return $cached;
        }
        
        // Query database
        $country = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$table} WHERE country_code = %s",
            $country_code
        ), ARRAY_A);
        
        if (!$country) {
            wp_cache_set($cache_key, false, '', 300); // Cache miss for 5 minutes
            return false;
        }
        
        // Check if active
        if ($country['is_active'] != 1) {
            wp_cache_set($cache_key, false, '', 300);
            return false;
        }
        
        // Check if expired (temporary block)
        if ($country['blocked_until'] > 0 && $country['blocked_until'] < time()) {
            self::unblock_country($country_code);
            wp_cache_set($cache_key, false, '', 300);
            return false;
        }
        
        // Cache and return
        wp_cache_set($cache_key, $country, '', 300);
        return $country;
    }

    /**
     * Unblock a country
     * 
     * @param string|int $identifier Country code or database ID
     * @return bool True on success
     */
    public static function unblock_country($identifier) {
        global $wpdb;
        
        $table = $wpdb->prefix . self::$table_name;
        
        // Determine if it's a code or ID
        if (is_numeric($identifier)) {
            $result = $wpdb->delete($table, ['id' => (int)$identifier], ['%d']);
        } else {
            $country_code = strtoupper(sanitize_text_field($identifier));
            $result = $wpdb->delete($table, ['country_code' => $country_code], ['%s']);
            
            // Clear cache
            wp_cache_delete('vmpfence_blocked_country_' . $country_code);
        }
        
        if ($result) {
            self::clear_cache();
            
            if (class_exists('VMPFence_Secure_Logger')) {
                VMPFence_Secure_Logger::info("Country unblocked", ['identifier' => $identifier]);
            }
            
            return true;
        }
        
        return false;
    }

    /**
     * Update a blocked country
     * 
     * @param string $country_code ISO alpha-2 code
     * @param array $data Data to update
     * @return bool True on success
     */
    public static function update_blocked_country($country_code, $data) {
        global $wpdb;
        
        $country_code = strtoupper(sanitize_text_field($country_code));
        $table = $wpdb->prefix . self::$table_name;
        
        $allowed_fields = ['country_name', 'block_login', 'block_site', 'reason', 'blocked_until', 'is_active'];
        $update_data = [];
        $formats = [];
        
        foreach ($data as $key => $value) {
            if (in_array($key, $allowed_fields)) {
                $update_data[$key] = $value;
                
                if (in_array($key, ['block_login', 'block_site', 'is_active', 'blocked_until'])) {
                    $formats[] = '%d';
                } else {
                    $formats[] = '%s';
                }
            }
        }
        
        if (empty($update_data)) {
            return false;
        }
        
        $result = $wpdb->update(
            $table,
            $update_data,
            ['country_code' => $country_code],
            $formats,
            ['%s']
        );
        
        if ($result !== false) {
            self::clear_cache();
            wp_cache_delete('vmpfence_blocked_country_' . $country_code);
            return true;
        }
        
        return false;
    }

    /**
     * Get all blocked countries
     * 
     * @param array $args Query arguments
     * @return array List of blocked countries
     */
    public static function get_blocked_countries($args = []) {
        global $wpdb;
        
        $defaults = [
            'active_only' => true,
            'limit' => 100,
            'offset' => 0,
            'orderby' => 'blocked_at',
            'order' => 'DESC'
        ];
        
        $args = wp_parse_args($args, $defaults);
        
        // Whitelist validation for ORDER BY (prevent SQL injection)
        $allowed_orderby = ['id', 'country_code', 'country_name', 'blocked_at', 'block_count', 'last_attempt'];
        if (!in_array($args['orderby'], $allowed_orderby)) {
            $args['orderby'] = 'blocked_at';
        }
        
        $allowed_order = ['ASC', 'DESC'];
        $args['order'] = strtoupper($args['order']);
        if (!in_array($args['order'], $allowed_order)) {
            $args['order'] = 'DESC';
        }
        
        $table = $wpdb->prefix . self::$table_name;
        
        // Build WHERE clause
        $where_clauses = [];
        $where_values = [];
        
        if ($args['active_only']) {
            $where_clauses[] = 'is_active = %d';
            $where_values[] = 1;
        }
        
        $where_sql = !empty($where_clauses) ? 'WHERE ' . implode(' AND ', $where_clauses) : '';
        
        // Build query
        $sql = "SELECT * FROM {$table} {$where_sql} ORDER BY {$args['orderby']} {$args['order']}";
        
        if ($args['limit'] > 0) {
            $sql .= $wpdb->prepare(" LIMIT %d OFFSET %d", $args['limit'], $args['offset']);
        }
        
        if (!empty($where_values)) {
            $sql = $wpdb->prepare($sql, $where_values);
        }
        
        return $wpdb->get_results($sql, ARRAY_A);
    }

    /**
     * Get count of blocked countries
     * 
     * @param bool $active_only Count only active blocks
     * @return int Count
     */
    public static function get_blocked_count($active_only = true) {
        global $wpdb;
        
        $table = $wpdb->prefix . self::$table_name;
        $where = $active_only ? 'WHERE is_active = 1' : '';
        
        return (int)$wpdb->get_var("SELECT COUNT(*) FROM {$table} {$where}");
    }

    /**
     * Increment block counter for a country
     * 
     * @param string $country_code ISO alpha-2 code
     * @return bool True on success
     */
    public static function increment_block_count($country_code) {
        global $wpdb;
        
        $country_code = strtoupper(sanitize_text_field($country_code));
        $table = $wpdb->prefix . self::$table_name;
        
        $result = $wpdb->query($wpdb->prepare(
            "UPDATE {$table} 
            SET block_count = block_count + 1,
                last_attempt = %s
            WHERE country_code = %s",
            current_time('mysql'),
            $country_code
        ));
        
        if ($result !== false) {
            wp_cache_delete('vmpfence_blocked_country_' . $country_code);
            return true;
        }
        
        return false;
    }

    /**
     * Get statistics
     * 
     * @return array Statistics data
     */
    public static function get_stats() {
        global $wpdb;
        
        $table = $wpdb->prefix . self::$table_name;
        
        $stats = [
            'total_blocked' => self::get_blocked_count(false),
            'active_blocks' => self::get_blocked_count(true),
            'total_attempts' => 0,
            'top_countries' => []
        ];
        
        // Get total block attempts
        $stats['total_attempts'] = (int)$wpdb->get_var(
            "SELECT SUM(block_count) FROM {$table} WHERE is_active = 1"
        );
        
        // Get top 5 blocked countries by attempt count
        $stats['top_countries'] = $wpdb->get_results(
            "SELECT 
                country_code,
                country_name,
                block_count,
                blocked_at
            FROM {$table}
            WHERE is_active = 1
            ORDER BY block_count DESC
            LIMIT 5",
            ARRAY_A
        );
        
        return $stats;
    }

    /**
     * Get top attacking countries from block logs
     * @since 2.2.0
     * @param string $period Time period ('24h', '7d', '30d')
     * @param int $limit Number of countries to return
     * @return array Top countries with attack counts
     */
    public static function get_top_attacking_countries($period = '7d', $limit = 10) {
        global $wpdb;
        
        $logs_table = $wpdb->prefix . self::$logs_table_name;
        
        // Check if table exists - if not, return empty array to prevent errors
        $table_exists = $wpdb->get_var("SHOW TABLES LIKE '{$logs_table}'") === $logs_table;
        if (!$table_exists) {
            // Table doesn't exist yet - might be a fresh install or migration not run
            // Create the table if needed
            if (method_exists('VMPFence_Database', 'create_tables')) {
                require_once VMPFENCE_PLUGIN_DIR . 'lib/class-database.php';
                VMPFence_Database::create_tables();
            }
            return [];
        }
        
        // Validate and sanitize limit
        $limit = absint($limit);
        if ($limit < 1 || $limit > 100) {
            $limit = 10; // Default to 10 if invalid
        }
        
        // Convert period to hours
        $hours_map = [
            '24h' => 24,
            '7d' => 168,  // 7 days
            '30d' => 720  // 30 days
        ];
        
        $hours = isset($hours_map[$period]) ? $hours_map[$period] : 168;
        
        // Query to get top countries by attack count
        $results = $wpdb->get_results($wpdb->prepare(
            "SELECT 
                country_code,
                country_name,
                COUNT(*) as attack_count
            FROM {$logs_table}
            WHERE blocked_at >= DATE_SUB(NOW(), INTERVAL %d HOUR)
            GROUP BY country_code, country_name
            ORDER BY attack_count DESC
            LIMIT %d",
            $hours,
            $limit
        ), ARRAY_A);
        
        return $results ? $results : [];
    }

    /**
     * Get country by code
     * 
     * @param string $country_code ISO alpha-2 code
     * @return array|false Country data or false
     */
    public static function get_country($country_code) {
        global $wpdb;
        
        $country_code = strtoupper(sanitize_text_field($country_code));
        $table = $wpdb->prefix . self::$table_name;
        
        return $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$table} WHERE country_code = %s",
            $country_code
        ), ARRAY_A);
    }

    /**
     * Check if country blocking feature is enabled
     * 
     * @return bool True if enabled
     */
    public static function is_feature_enabled() {
        // Check if premium license using the same pattern as country blocker
        if (!class_exists('VMPFence_License')) {
            return false;
        }
        
        $license_type = VMPFence_License::get_license_type();
        if ($license_type !== VMPFence_Constants::LICENSE_PREMIUM) {
            return false;
        }
        
        // Check if feature is enabled in settings
        $enabled = get_option('vmpfence_country_blocking_enabled', 0);
        
        return (bool)$enabled;
    }
    
    /**
     * Clear all country blocking caches
     * 
     * @return void
     */
    public static function clear_cache() {
        global $wpdb;
        
        // Clear list cache
        wp_cache_delete('vmpfence_blocked_countries_list');
        wp_cache_delete('vmpfence_blocked_countries_count');
        
        // Clear individual country caches
        $table = $wpdb->prefix . self::$table_name;
        $codes = $wpdb->get_col("SELECT country_code FROM {$table}");
        
        if ($codes) {
            foreach ($codes as $code) {
                wp_cache_delete('vmpfence_blocked_country_' . $code);
            }
        }
        
        // Clear GeoIP transient caches (important for immediate blocking/unblocking)
        // This ensures newly blocked/unblocked countries take effect immediately
        $wpdb->query(
            $wpdb->prepare(
                "DELETE FROM {$wpdb->options} 
                 WHERE option_name LIKE %s 
                 OR option_name LIKE %s",
                $wpdb->esc_like('_transient_vmpfence_geoip_') . '%',
                $wpdb->esc_like('_transient_timeout_vmpfence_geoip_') . '%'
            )
        );
    }
    
    /**
     * Log a country block event
     * 
     * @param array $data Block event data (ip, country_code, country_name, block_type, request_uri, user_agent)
     * @return int|false Insert ID on success, false on failure
     */
    public static function log_block_event($data) {
        global $wpdb;
        
        $table = $wpdb->prefix . self::$logs_table_name;
        
        // Check if table exists before trying to insert
        $table_exists = $wpdb->get_var("SHOW TABLES LIKE '{$table}'") === $table;
        if (!$table_exists) {
            // Table doesn't exist - silently fail or create table
            if (method_exists('VMPFence_Database', 'create_tables')) {
                require_once VMPFENCE_PLUGIN_DIR . 'lib/class-database.php';
                VMPFence_Database::create_tables();
            }
            return false;
        }
        
        $insert_data = [
            'ip' => isset($data['ip']) ? $data['ip'] : '',
            'country_code' => isset($data['country_code']) ? $data['country_code'] : '',
            'country_name' => isset($data['country_name']) ? $data['country_name'] : '',
            'block_type' => isset($data['block_type']) ? $data['block_type'] : 'site',
            'request_uri' => isset($data['request_uri']) ? substr($data['request_uri'], 0, 500) : '',
            'user_agent' => isset($data['user_agent']) ? substr($data['user_agent'], 0, 500) : '',
            'blocked_at' => current_time('mysql')
        ];
        
        $result = $wpdb->insert($table, $insert_data, [
            '%s', // ip
            '%s', // country_code
            '%s', // country_name
            '%s', // block_type
            '%s', // request_uri
            '%s', // user_agent
            '%s'  // blocked_at
        ]);
        
        if ($result === false) {
            if (class_exists('VMPFence_Secure_Logger')) {
                VMPFence_Secure_Logger::error('Failed to log country block event', [
                    'error' => $wpdb->last_error,
                    'data' => $data
                ]);
            }
            return false;
        }
        
        return $wpdb->insert_id;
    }
}