<?php

/**
 * Sentinel Migration Class
 *
 * Handles database table creation and updates.
 */

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

class Sentinel_Migration
{
    /**
     * Create or update the Sentinel log table
     * This is called on plugin activation and version checks
     */
    public static function create_tables()
    {
        global $wpdb;
        $charset_collate = $wpdb->get_charset_collate();

        // SQL for the main log table
        $table_name = $wpdb->prefix . 'sentinel_logs';
        $sql = "CREATE TABLE $table_name (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            event_key varchar(100) NOT NULL,
            category varchar(50) DEFAULT 'general',
            priority varchar(20) DEFAULT 'info',
            user_id bigint(20) DEFAULT 0,
            ip_address varchar(45) DEFAULT NULL,
            user_agent text DEFAULT NULL,
            url text DEFAULT NULL,
            data longtext DEFAULT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            KEY event_key (event_key),
            KEY user_id (user_id),
            KEY created_at (created_at),
            KEY priority (priority)
        ) $charset_collate;";

        // SQL for the archive table (identical structure)
        $archive_table_name = $wpdb->prefix . 'sentinel_logs_archive';
        $archive_sql = "CREATE TABLE $archive_table_name (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            event_key varchar(100) NOT NULL,
            category varchar(50) DEFAULT 'general',
            priority varchar(20) DEFAULT 'info',
            user_id bigint(20) DEFAULT 0,
            ip_address varchar(45) DEFAULT NULL,
            user_agent text DEFAULT NULL,
            url text DEFAULT NULL,
            data longtext DEFAULT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            archived_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            KEY event_key (event_key),
            KEY user_id (user_id),
            KEY created_at (created_at),
            KEY archived_at (archived_at),
            KEY priority (priority)
        ) $charset_collate;";

        // SQL for the incidents table (Sentinel+ feature)
        $incidents_table_name = $wpdb->prefix . 'sentinel_incidents';
        $incidents_sql = "CREATE TABLE $incidents_table_name (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            type varchar(64) NOT NULL,
            status enum('open','resolved') NOT NULL DEFAULT 'open',
            confidence enum('low','medium','high') NOT NULL,
            ip varbinary(16) DEFAULT NULL,
            username varchar(191) DEFAULT NULL,
            source varchar(32) DEFAULT NULL,
            first_seen datetime NOT NULL,
            last_seen datetime NOT NULL,
            count int unsigned NOT NULL DEFAULT 0,
            meta longtext DEFAULT NULL,
            created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
            updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            KEY idx_type_status (type, status),
            KEY idx_ip_status (ip, status),
            KEY idx_last_seen (last_seen)
        ) $charset_collate;";

        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');

        // Create main table and check if it worked
        $main_result = dbDelta($sql);
        $main_exists = self::table_exists($table_name);

        // Create archive table and check if it worked
        $archive_result = dbDelta($archive_sql);
        $archive_exists = self::table_exists($archive_table_name);

        // Create incidents table and check if it worked
        $incidents_result = dbDelta($incidents_sql);
        $incidents_exists = self::table_exists($incidents_table_name);

        // Log creation results for debugging
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log('Sentinel Migration: Main table ' . ($main_exists ? 'created/exists' : 'FAILED'));
            error_log('Sentinel Migration: Archive table ' . ($archive_exists ? 'created/exists' : 'FAILED'));
            error_log('Sentinel Migration: Incidents table ' . ($incidents_exists ? 'created/exists' : 'FAILED'));
        }

        // Only save version if all tables exist
        if ($main_exists && $archive_exists && $incidents_exists) {
            update_option('sentinel_db_version', SENTINEL_VERSION);
            return true;
        }

        return false;
    }

    /**
     * Check if a table exists
     */
    private static function table_exists($table_name)
    {
        global $wpdb;
        return $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name;
    }

    /**
     * Check if the database needs to be updated
     * This is called on plugin load to ensure the table is up to date
     */
    public static function check_version()
    {
        $current_version = get_option('sentinel_db_version');

        // Always check if tables actually exist, regardless of version
        global $wpdb;
        $main_table = $wpdb->prefix . 'sentinel_logs';
        $archive_table = $wpdb->prefix . 'sentinel_logs_archive';
        $incidents_table = $wpdb->prefix . 'sentinel_incidents';

        $main_exists = $wpdb->get_var("SHOW TABLES LIKE '$main_table'") == $main_table;
        $archive_exists = $wpdb->get_var("SHOW TABLES LIKE '$archive_table'") == $archive_table;
        $incidents_exists = $wpdb->get_var("SHOW TABLES LIKE '$incidents_table'") == $incidents_table;

        // Create tables if version doesn't match OR if any table doesn't exist
        if ($current_version !== SENTINEL_VERSION || !$main_exists || !$archive_exists || !$incidents_exists) {
            self::create_tables();
        }
    }

    /**
     * Ensure tables exist (can be called at any time)
     */
    public static function ensure_tables_exist()
    {
        global $wpdb;
        $main_table = $wpdb->prefix . 'sentinel_logs';
        $archive_table = $wpdb->prefix . 'sentinel_logs_archive';
        $incidents_table = $wpdb->prefix . 'sentinel_incidents';

        $main_exists = $wpdb->get_var("SHOW TABLES LIKE '$main_table'") == $main_table;
        $archive_exists = $wpdb->get_var("SHOW TABLES LIKE '$archive_table'") == $archive_table;
        $incidents_exists = $wpdb->get_var("SHOW TABLES LIKE '$incidents_table'") == $incidents_table;

        if (!$main_exists || !$archive_exists || !$incidents_exists) {
            self::create_tables();
        }
    }

    /**
     * Set default plugin options (placeholder for future settings)
     */
    public static function set_default_options()
    {
        if (get_option('sentinel_settings') === false) {
            add_option('sentinel_settings', array());
        }

        // Add default security settings for Sentinel+ brute force detection
        if (get_option('sentinel_security_settings') === false) {
            $default_security_settings = array(
                // Detection thresholds
                'bruteforce_threshold' => 5,
                'bruteforce_window' => 300, // 5 minutes in seconds
                'enumeration_threshold' => 10,
                'enumeration_window' => 600, // 10 minutes in seconds
                'xmlrpc_threshold' => 20,
                'xmlrpc_window' => 300, // 5 minutes in seconds

                // Resolution and cool-down
                'incident_auto_resolve' => 21600, // 6 hours in seconds
                'notification_cooldown' => 1800, // 30 minutes in seconds

                // Whitelist and trust
                'ip_allowlist' => '',
                'trust_admin_ips' => 1,
                'admin_trust_duration' => 86400, // 24 hours in seconds

                // Action mode (Phase 2)
                'action_mode' => 'observe', // observe|throttle|block
                'throttle_delay' => 3, // seconds
                'temp_block_duration' => 3600, // 1 hour in seconds
            );
            add_option('sentinel_security_settings', $default_security_settings);
        }

        // Seed onboarding state on activation. Idempotent: respects existing
        // state and never overwrites it.
        if (class_exists('Sentinel_Onboarding')) {
            Sentinel_Onboarding::seed_on_activation();
        }
    }

    /**
     * Update existing tables (for future upgrades)
     */
    public static function update_tables()
    {
        // For future schema changes
        self::create_tables();
    }
}
