<?php
/**
 * Plugin activation class
 *
 * Handles creation of tables, roles and capabilities during activation
 *
 * @package SlideMind
 * @since 2.0.0
 */

namespace SlideMind;

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

class Activator {

    /**
     * Database version
     * @var string
     */
    private static $db_version = '1.6';

    /**
     * Main activation method
     */
    public static function activate() {
        self::create_tables();
        self::create_capabilities();
        self::create_encryption_key();
        self::migrate_provider_settings();
        self::seed_default_templates();
        self::migrate_formation_to_course();

        // Store the version for future migrations
        update_option('slidemind_db_version', self::$db_version);
        update_option('slidemind_plugin_version', SLIDEMIND_VERSION);

        // Schedule the log purge cron
        if (!wp_next_scheduled('slidemind_purge_logs_cron')) {
            wp_schedule_event(time(), 'daily', 'slidemind_purge_logs_cron');
        }

        // Schedule the learner memory purge cron (GDPR)
        if (!wp_next_scheduled('slidemind_purge_memory_cron')) {
            wp_schedule_event(time(), 'daily', 'slidemind_purge_memory_cron');
        }

        // Flush rewrite rules
        flush_rewrite_rules();
    }

    /**
     * Create the logs table
     */
    private static function create_tables() {
        global $wpdb;

        $table_name = $wpdb->prefix . 'slidemind_logs';
        $charset_collate = $wpdb->get_charset_collate();

        $sql = "CREATE TABLE $table_name (
            id BIGINT UNSIGNED AUTO_INCREMENT,
            config_id BIGINT UNSIGNED NOT NULL,
            request_tokens INT UNSIGNED DEFAULT 0,
            response_tokens INT UNSIGNED DEFAULT 0,
            total_tokens INT UNSIGNED DEFAULT 0,
            estimated_cost DECIMAL(10,6) DEFAULT 0,
            response_time_ms INT UNSIGNED DEFAULT 0,
            model_id VARCHAR(100) DEFAULT '',
            status ENUM('success', 'error') DEFAULT 'success',
            error_message TEXT,
            user_ip VARCHAR(45) DEFAULT '',
            user_id BIGINT UNSIGNED DEFAULT 0,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            KEY idx_config_date (config_id, created_at),
            KEY idx_status (status),
            KEY idx_created_at (created_at),
            KEY idx_user_id (user_id)
        ) $charset_collate;";

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

        // Learner memory table
        $memory_table = $wpdb->prefix . 'slidemind_learner_memory';

        $memory_sql = "CREATE TABLE $memory_table (
            id BIGINT UNSIGNED AUTO_INCREMENT,
            wp_user_id BIGINT UNSIGNED NOT NULL,
            session_id VARCHAR(36) NOT NULL DEFAULT '',
            scope VARCHAR(20) NOT NULL DEFAULT 'global',
            scope_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
            variable_name VARCHAR(255) NOT NULL,
            variable_value LONGTEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            UNIQUE KEY unique_memory (wp_user_id,session_id,scope,scope_id,variable_name),
            KEY idx_wp_user_id (wp_user_id),
            KEY idx_anon_expiry (wp_user_id, session_id, updated_at)
        ) $charset_collate;";

        dbDelta($memory_sql);
    }

    /**
     * Create custom capabilities
     */
    private static function create_capabilities() {
        // Add capabilities to the administrator role
        $admin_role = get_role('administrator');

        if ($admin_role) {
            // Capabilities for configurations
            $admin_role->add_cap('manage_slidemind_configs');
            $admin_role->add_cap('edit_slidemind_config');
            $admin_role->add_cap('edit_slidemind_configs');
            $admin_role->add_cap('edit_others_slidemind_configs');
            $admin_role->add_cap('publish_slidemind_configs');
            $admin_role->add_cap('read_slidemind_config');
            $admin_role->add_cap('read_private_slidemind_configs');
            $admin_role->add_cap('delete_slidemind_config');
            $admin_role->add_cap('delete_slidemind_configs');

            // Capabilities for settings
            $admin_role->add_cap('manage_slidemind_settings');
        }

        // Add limited capabilities to the editor role
        $editor_role = get_role('editor');

        if ($editor_role) {
            $editor_role->add_cap('manage_slidemind_configs');
            $editor_role->add_cap('edit_slidemind_config');
            $editor_role->add_cap('edit_slidemind_configs');
            $editor_role->add_cap('publish_slidemind_configs');
            $editor_role->add_cap('read_slidemind_config');
            $editor_role->add_cap('delete_slidemind_config');
            // Note: no manage_slidemind_settings for editors
        }
    }

    /**
     * Create or retrieve the encryption key
     */
    private static function create_encryption_key() {
        // Check if a key already exists
        $existing_key = get_option('slidemind_encryption_key');

        if (empty($existing_key)) {
            // Generate an AES-256 key (32 bytes)
            $key = wp_generate_password(32, true, true);

            // Store the key securely
            // Note: In a production environment, this key should be
            // stored in wp-config.php or in an environment variable
            update_option('slidemind_encryption_key', base64_encode($key));
        }
    }

    /**
     * Seed default templates into the database
     */
    private static function seed_default_templates() {
        // Manually load dependencies (plugins_loaded hasn't fired yet)
        require_once SLIDEMIND_PLUGIN_PATH . 'includes/Core/class-api-key-manager.php';
        require_once SLIDEMIND_PLUGIN_PATH . 'includes/Core/class-config-repository.php';
        require_once SLIDEMIND_PLUGIN_PATH . 'includes/Core/class-template-manager.php';

        $api_key_manager = new Core\ApiKeyManager();
        $config_repository = new Core\ConfigRepository($api_key_manager);
        $template_manager = new Core\TemplateManager($config_repository);

        $template_manager->seed_defaults();

        // Mark the default templates as favorites (if not already configured)
        $settings = get_option('slidemind_settings', []);
        if (!isset($settings['favorite_templates']) || empty($settings['favorite_templates'])) {
            $settings['favorite_templates'] = ['quiz', 'open-question', 'formative-eval', 'socratic', 'roleplay', 'guided-exploration'];
            update_option('slidemind_settings', $settings);
        }
    }

    /**
     * Migrate settings for multi-provider support
     *
     * Copies the existing global API key to slidemind_api_key_openrouter
     * and sets the default provider if not yet configured.
     */
    private static function migrate_provider_settings() {
        $db_version = get_option('slidemind_db_version', '0');

        // Only migrate if coming from a version < 1.2
        if (version_compare($db_version, '1.2', '>=')) {
            return;
        }

        // Copy the existing global key to slidemind_api_key_openrouter
        $existing_key = get_option('slidemind_global_api_key', '');
        if (!empty($existing_key) && empty(get_option('slidemind_api_key_openrouter', ''))) {
            update_option('slidemind_api_key_openrouter', $existing_key);
        }

        // Set the default global provider
        if (empty(get_option('slidemind_global_provider', ''))) {
            update_option('slidemind_global_provider', 'openrouter');
        }
    }

    /**
     * Update the DB schema if needed (called on every plugin load)
     */
    public static function maybe_upgrade() {
        $current = get_option('slidemind_db_version', '0');
        if (version_compare($current, self::$db_version, '>=')) {
            // Self-heal: if version flag was set but migration failed (MySQL compat issue)
            self::repair_session_id_schema();
            return;
        }

        self::migrate_session_id_column();
        self::create_tables();
        self::migrate_formation_to_course();
        update_option('slidemind_db_version', self::$db_version);
    }

    /**
     * Repairs session_id schema if the migration flag was set but the column/index are missing.
     *
     * Covers the case where DROP INDEX IF EXISTS failed on MySQL < 8.0.28,
     * leaving the flag set but the schema unchanged.
     */
    private static function repair_session_id_schema() {
        if (!get_option('slidemind_session_id_migrated')) {
            return;
        }

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

        // Check if session_id column exists
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $col = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s AND COLUMN_NAME = 'session_id'",
                $table
            )
        );

        if ($col) {
            // Column exists — check if the UNIQUE KEY includes it
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $has_session_in_key = $wpdb->get_var(
                $wpdb->prepare(
                    "SELECT COUNT(1) FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s AND INDEX_NAME = 'unique_memory' AND COLUMN_NAME = 'session_id'",
                    $table
                )
            );
            if ($has_session_in_key) {
                return; // Schema is correct
            }
        }

        // Schema needs repair — reset flag and re-run migration
        delete_option('slidemind_session_id_migrated');
        update_option('slidemind_db_version', '1.5'); // Force re-run of maybe_upgrade on next load

        // Run immediately
        self::migrate_session_id_column();

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

        update_option('slidemind_db_version', self::$db_version);
    }

    /**
     * Adds session_id column and rebuilds the UNIQUE KEY for anonymous sessions.
     *
     * dbDelta can add a column but cannot modify an existing UNIQUE KEY,
     * so we DROP the old key first and let dbDelta recreate the new one.
     * Idempotent via slidemind_session_id_migrated flag.
     */
    private static function migrate_session_id_column() {
        if (get_option('slidemind_session_id_migrated')) {
            return;
        }

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

        // Check if the table exists (fresh installs handled by create_tables)
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $table_exists = $wpdb->get_var(
            $wpdb->prepare('SHOW TABLES LIKE %s', $table)
        );

        if (!$table_exists) {
            update_option('slidemind_session_id_migrated', '1');
            return;
        }

        // Drop old UNIQUE KEY if it exists (MySQL-compatible — no IF EXISTS syntax)
        // phpcs:disable WordPress.DB.DirectDatabaseQuery
        $index_exists = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(1) FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema = DATABASE() AND table_name = %s AND index_name = 'unique_memory'",
                $table
            )
        );
        if ($index_exists) {
            $wpdb->query($wpdb->prepare("ALTER TABLE %i DROP INDEX unique_memory", $table));
        }
        // phpcs:enable WordPress.DB.DirectDatabaseQuery

        // dbDelta in create_tables() will add the column and new UNIQUE KEY
        update_option('slidemind_session_id_migrated', '1');
    }

    /**
     * Migrate "formation" to "course" across the entire database
     *
     * Renames config_type, meta keys, meta values,
     * memory scopes and placeholders in system prompts.
     * Idempotent via the slidemind_formation_renamed flag.
     */
    private static function migrate_formation_to_course() {
        if (get_option('slidemind_formation_renamed')) {
            return;
        }

        global $wpdb;

        // 1. Rename config type: formation → course
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->query(
            "UPDATE {$wpdb->postmeta}
             SET meta_value = 'course'
             WHERE meta_key = '_slidemind_config_type'
               AND meta_value = 'formation'"
        );

        // 2. Rename meta keys
        $meta_key_renames = [
            '_slidemind_formation_theme'            => '_slidemind_course_theme',
            '_slidemind_formation_objectives'       => '_slidemind_course_objectives',
            '_slidemind_formation_content'          => '_slidemind_course_content',
            '_slidemind_formation_response_example' => '_slidemind_course_response_example',
            '_slidemind_parent_formation_id'        => '_slidemind_parent_course_id',
            '_slidemind_override_formation'         => '_slidemind_override_course',
        ];

        foreach ($meta_key_renames as $old_key => $new_key) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->query($wpdb->prepare(
                "UPDATE {$wpdb->postmeta}
                 SET meta_key = %s
                 WHERE meta_key = %s",
                $new_key,
                $old_key
            ));
        }

        // 3. Rename meta value for interaction scope
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->query(
            "UPDATE {$wpdb->postmeta}
             SET meta_value = 'course'
             WHERE meta_key = '_slidemind_save_interaction_scope'
               AND meta_value = 'formation'"
        );

        // 4. Rename scope in learner memory table
        $memory_table = $wpdb->prefix . 'slidemind_learner_memory';
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->query(
            $wpdb->prepare(
                "UPDATE %i
                 SET scope = 'course'
                 WHERE scope = 'formation'",
                $memory_table
            )
        );
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

        // 5. Migrate {{formation_*}} → {{course_*}} placeholders in system prompts
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->query(
            "UPDATE {$wpdb->postmeta}
             SET meta_value = REPLACE(meta_value, '{{formation_', '{{course_')
             WHERE meta_key = '_slidemind_system_prompt'
               AND meta_value LIKE '%{{formation_%'"
        );

        // 6. Migrate memory.formation. → memory.course. scoped memory variables in system prompts
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->query(
            "UPDATE {$wpdb->postmeta}
             SET meta_value = REPLACE(meta_value, 'memory.formation.', 'memory.course.')
             WHERE meta_key = '_slidemind_system_prompt'
               AND meta_value LIKE '%memory.formation.%'"
        );

        // Mark migration as done
        update_option('slidemind_formation_renamed', '1');
    }

    /**
     * Deactivation method
     */
    public static function deactivate() {
        // Clean up transients
        delete_transient('slidemind_openrouter_models');
        delete_transient('slidemind_openai_models');
        delete_transient('slidemind_anthropic_models');
        delete_transient('slidemind_mistral_models');

        // Remove purge cron jobs
        wp_clear_scheduled_hook('slidemind_purge_logs_cron');
        wp_clear_scheduled_hook('slidemind_purge_memory_cron');

        // Flush rewrite rules
        flush_rewrite_rules();
    }
}
