<?php
/**
 * Main Guard Dog Plugin Class.
 *
 * @package GuardDog
 * @since 1.1.0
 */

if (!defined('ABSPATH')) exit; // Exit if accessed directly

final class Guard_Dog {

    /**
     * Plugin version.
     *
     * @var string
     */
    public $version = '1.9.50';

    /**
     * The single instance of the class.
     *
     * @var Guard_Dog
     * @since 1.1.0
     */
    protected static $_instance = null;

    /**
     * Feature instances.
     *
     * @var array
     * @since 1.1.0
     */
    public $features = [];

    /**
     * Admin instance.
     *
     * @var Guard_Dog_Admin|null
     * @since 1.1.0
     */
    public $admin = null;

    /**
     * Database manager instance.
     *
     * @var Guard_Dog_DB|null
     * @since 1.6.0
     */
    public $db = null;

    /**
     * Activity Log instance.
     *
     * @var Guard_Dog_Activity_Log|null
     * @since 1.6.0
     */
    public $activity_log = null;

    /**
     * Debug instance.
     *
     * @var Guard_Dog_Debug|null
     * @since 1.2.0
     */
    public $debug = null;

    /**
     * Main Guard_Dog Instance.
     *
     * Ensures only one instance of Guard_Dog is loaded or can be loaded.
     *
     * @since 1.1.0
     * @static
     * @see guard_dog_get_instance()
     * @return Guard_Dog - Main instance.
     */
    public static function instance() {
        if (is_null(self::$_instance)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    /**
     * Constructor.
     *
     * @since 1.1.0
     */
    private function __construct() {
        $this->define_constants();
        $this->includes();
        $this->init_hooks();
        $this->init_debug(); // Initialize debug system first
        $this->init_db(); // Initialize DB manager
        $this->init_logging(); // Initialize logging
        $this->init_features(); // Initialize features that might use DB or logging
        $this->init_admin(); // Initialize admin last
    }

    /**
     * Define Guard Dog Constants.
     *
     * @since 1.1.0
     */
    private function define_constants() {
        if (!defined('GUARD_DOG_VERSION')) {
            define('GUARD_DOG_VERSION', $this->version);
        }
        if (!defined('GUARD_DOG_PATH')) {
            define('GUARD_DOG_PATH', plugin_dir_path(GUARD_DOG_PLUGIN_FILE));
        }
        if (!defined('GUARD_DOG_URL')) {
            define('GUARD_DOG_URL', plugin_dir_url(GUARD_DOG_PLUGIN_FILE));
        }
        if (!defined('GUARD_DOG_BASENAME')) {
            define('GUARD_DOG_BASENAME', plugin_basename(GUARD_DOG_PLUGIN_FILE));
        }
    }

    /**
     * Include required core files used in admin and on the frontend.
     *
     * @since 1.1.0
     */
    private function includes() {
        // Include DB class first
        require_once GUARD_DOG_PATH . 'includes/utils/class-guard-dog-db.php';

        // Include View Loader
        require_once GUARD_DOG_PATH . 'includes/utils/class-view-loader.php';

        // Include Utilities
        require_once GUARD_DOG_PATH . 'includes/utils/class-guard-dog-utils.php';
        require_once GUARD_DOG_PATH . 'includes/utils/class-guard-dog-debug.php';

        // Include debug handlers if in admin
        if (is_admin()) {
            require_once GUARD_DOG_PATH . 'includes/utils/class-guard-dog-debug-handlers.php';
        }

        // Include customizer framework (needed on both frontend and admin)
        // Frontend: For rendering customized access denied pages
        // Admin: For customizer interface
        // Loaded before features so they can use customizer classes
        $this->load_customizer_framework();

        // Include feature classes
        require_once GUARD_DOG_PATH . 'includes/features/class-login-url.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-login-form.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-temp-access.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-two-factor-auth.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-email-provider.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-email-two-factor-auth.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-access-control.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-limit-login-attempts.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-activity-log.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-captcha.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-login-errors.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-ip-reputation-checker.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-email-verification.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-password-policy.php';
        require_once GUARD_DOG_PATH . 'includes/utils/class-password-validator.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-session-manager.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-passkeys.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-user-enumeration.php';

        // Include social login provider interface and implementations
        require_once GUARD_DOG_PATH . 'includes/features/social-providers/class-social-provider-interface.php';
        require_once GUARD_DOG_PATH . 'includes/features/social-providers/class-google-provider.php';
        require_once GUARD_DOG_PATH . 'includes/features/social-providers/class-microsoft-provider.php';
        require_once GUARD_DOG_PATH . 'includes/features/social-providers/class-apple-provider.php';
        require_once GUARD_DOG_PATH . 'includes/features/class-social-login.php';

        // Include admin class if in admin area
        if (is_admin()) {
             require_once GUARD_DOG_PATH . 'includes/admin/class-guard-dog-admin.php';

             // Initialize customizer loader (admin menus, assets, AJAX handlers)
             require_once GUARD_DOG_PATH . 'includes/customizer/class-guard-dog-customizer-loader.php';
             Guard_Dog_Customizer_Loader::init();
        }
    }

    /**
     * Load customizer framework files.
     *
     * Loads the base customizer classes and implementations needed for
     * rendering customized pages on both frontend and admin.
     * Does NOT initialize admin-specific features (menus, assets, etc.).
     *
     * @since 1.8.45
     */
    private function load_customizer_framework() {
        // Base classes
        require_once GUARD_DOG_PATH . 'includes/customizer/class-guard-dog-customizer.php';
        require_once GUARD_DOG_PATH . 'includes/customizer/class-guard-dog-customizer-control.php';

        // Load controls
        $controls_path = GUARD_DOG_PATH . 'includes/customizer/controls/';
        require_once $controls_path . 'class-color-control.php';
        require_once $controls_path . 'class-image-control.php';
        require_once $controls_path . 'class-text-control.php';
        require_once $controls_path . 'class-textarea-control.php';
        require_once $controls_path . 'class-number-control.php';
        require_once $controls_path . 'class-checkbox-control.php';

        // Load implementations
        $implementations_path = GUARD_DOG_PATH . 'includes/customizer/implementations/';
        require_once $implementations_path . 'class-email-template-customizer.php';
        require_once $implementations_path . 'class-access-denied-customizer.php';
        require_once $implementations_path . 'class-login-screen-customizer.php';
    }

    /**
     * Hook into actions and filters.
     *
     * @since 1.1.0
     */
    private function init_hooks() {
        // Ensure authentication responses are never cached by reverse proxies (Varnish, Nginx)
        // or CDNs (Cloudflare). Fires inside wp_set_auth_cookie() before output is flushed,
        // so no-cache headers are included in the response that sets auth cookies.
        add_action( 'set_logged_in_cookie', array( $this, 'send_nocache_headers_on_auth' ), 10, 0 );

        // Prevent CDNs from caching the login page. WordPress sets wordpress_test_cookie
        // on the login form; if the response is cached, the Set-Cookie header is stripped.
        // The user's browser never receives the test cookie, and the POST login fails
        // with "Cookies must be enabled to use WordPress."
        add_action( 'login_init', array( $this, 'send_nocache_headers_on_login' ), 1 );

        // Load login screen customizations only inside the login lifecycle.
        // Creating customizer controls during plugin bootstrap triggers translated
        // strings before WordPress init, which can leak debug notices before
        // login cookies or passkey AJAX responses are sent.
        add_action( 'login_init', array( $this, 'init_login_screen_customizer' ), 2 );
    }

    /**
     * Send no-cache headers whenever an authentication cookie is set.
     *
     * Prevents Varnish, Nginx fastcgi_cache, and Cloudflare from caching
     * responses that contain Set-Cookie authentication headers. Without this,
     * multi-layer caching stacks can cache or strip auth cookies, causing
     * users to appear logged out after successful authentication.
     *
     * @since 1.9.20
     */
    public function send_nocache_headers_on_auth() {
        nocache_headers();
    }

    /**
     * Send no-cache headers on login page load.
     *
     * Prevents CDNs from caching wp-login.php responses, which would strip
     * the wordpress_test_cookie Set-Cookie header. Without the test cookie,
     * WordPress's built-in cookie check fails and users see "Cookies must
     * be enabled to use WordPress" even though cookies work fine.
     *
     * @since 1.9.36
     */
    public function send_nocache_headers_on_login() {
        nocache_headers();
    }

    /**
     * Initialize the login screen customizer during the login request lifecycle.
     *
     * @since 1.9.40
     */
    public function init_login_screen_customizer() {
        if ( isset( $this->features['login_screen_customizer'] ) ) {
            return;
        }

        if ( class_exists( 'Guard_Dog_Login_Screen_Customizer' ) ) {
            $this->features['login_screen_customizer'] = new Guard_Dog_Login_Screen_Customizer();
        }
    }

    /**
     * Initialize debug system.
     * 
     * Creates the debug singleton instance and makes it available
     * to all features for centralized logging.
     *
     * @since 1.2.0
     */
    private function init_debug() {
        if (class_exists('Guard_Dog_Debug')) {
            $this->debug = Guard_Dog_Debug::instance();
        }
    }

    /**
     * Initialize database manager.
     *
     * @since 1.6.0
     */
    private function init_db() {
        $this->db = new Guard_Dog_DB();
        // Check and run any pending database migrations
        // The install_tables() method has a version check so it only runs when needed
        $this->db->install_tables();
    }

    /**
     * Initialize Activity Logging.
     *
     * @since 1.6.0
     */
    private function init_logging() {
        if (class_exists('Guard_Dog_Activity_Log')) {
            $this->activity_log = new Guard_Dog_Activity_Log();
            // Pass the activity_log instance to features that need it, or they can access it via the main plugin instance.
        }
    }

    /**
     * Initialize features.
     *
     * @since 1.1.0
     */
    private function init_features() {
        // Ensure DB manager is available
        if (!$this->db) {
            $this->init_db();
        }
        $lla_table_name = $this->db->get_lla_table_name();

        $this->features['login_url'] = new Guard_Dog_Login_Url();
        $this->features['login_form'] = new Guard_Dog_Login_Form();
        $this->features['temp_access'] = new Guard_Dog_Temp_Access($this->activity_log);
        $this->features['two_factor_auth'] = new Guard_Dog_Two_Factor_Auth($this->activity_log);
        $this->features['email_provider'] = new Guard_Dog_Email_Provider();
        $this->features['email_two_factor_auth'] = new Guard_Dog_Email_Two_Factor_Auth($this->activity_log, $this->features['email_provider']);
        $this->features['access_control'] = new Guard_Dog_Access_Control($this->activity_log);
        $this->features['limit_login_attempts'] = new Guard_Dog_Limit_Login_Attempts( $lla_table_name, $this->activity_log );
        $this->features['captcha'] = Guard_Dog_Captcha::instance();
        $this->features['ip_reputation'] = new Guard_Dog_Ip_Reputation_Checker( $this->activity_log );
        $this->features['email_verification'] = new Guard_Dog_Email_Verification($this->activity_log, $this->features['email_provider']);
        $this->features['password_policy'] = new Guard_Dog_Password_Policy($this->activity_log);
        $this->features['session_manager'] = new Guard_Dog_Session_Manager($this->activity_log, $this->features['ip_reputation']);
        $this->features['passkeys'] = new Guard_Dog_Passkeys($this->activity_log);
        $this->features['user_enumeration'] = new Guard_Dog_User_Enumeration($this->activity_log);
        $this->features['social_login'] = new Guard_Dog_Social_Login($this->activity_log);

    }

    /**
     * Get an initialized feature instance by key.
     *
     * This gives custom login integrations a stable surface instead of reaching
     * into the public $features array directly.
     *
     * @since 1.9.40
     * @param string $feature Feature key.
     * @return object|null Feature instance when available.
     */
    public function get_feature( $feature ) {
        $feature = sanitize_key( $feature );

        return isset( $this->features[ $feature ] ) ? $this->features[ $feature ] : null;
    }

    /**
     * Write an Activity Log entry through Guard Dog's supported public API.
     *
     * @since 1.9.45
     * @param string $event_type Registered activity-log event slug.
     * @param array  $args       Optional log context: username, user_id, ip_address, object_id, object_type, details.
     * @return bool True when the log entry was accepted, false when unavailable, disabled, invalid, or failed.
     */
    public function log_activity( $event_type, array $args = [] ): bool {
        if ( ! $this->activity_log instanceof Guard_Dog_Activity_Log ) {
            return false;
        }

        $event_type = sanitize_key( (string) $event_type );

        if ( '' === $event_type ) {
            return false;
        }

        return $this->activity_log->add_log_entry( $event_type, $args );
    }

    /**
     * Check whether Guard Dog can participate in custom login 2FA.
     *
     * @since 1.9.40
     * @return bool
     */
    public function is_login_2fa_available() {
        $two_factor_auth = $this->get_feature( 'two_factor_auth' );
        $email_2fa       = $this->get_feature( 'email_two_factor_auth' );

        return (
            $two_factor_auth &&
            method_exists( $two_factor_auth, 'verify_user_2fa_code' )
        ) || (
            $email_2fa &&
            method_exists( $email_2fa, 'verify_code' )
        );
    }

    /**
     * Return the login 2FA methods enabled for a user.
     *
     * @since 1.9.40
     * @param int|WP_User|string $user User ID, user object, username, or email.
     * @return array
     */
    public function get_login_2fa_status( $user ) {
        $user = $this->normalize_user( $user );

        $status = array(
            'available'          => $this->is_login_2fa_available(),
            'requires_2fa'       => false,
            'has_app_2fa'        => false,
            'has_email_2fa'      => false,
            'has_recovery_codes' => false,
            'user_id'            => $user ? $user->ID : 0,
        );

        if ( ! $user ) {
            return $status;
        }

        $two_factor_auth = $this->get_feature( 'two_factor_auth' );
        $email_2fa       = $this->get_feature( 'email_two_factor_auth' );

        if ( $two_factor_auth && method_exists( $two_factor_auth, 'is_2fa_enabled_for_user' ) ) {
            $status['has_app_2fa'] = (bool) $two_factor_auth->is_2fa_enabled_for_user( $user->ID );
        }

        if (
            get_option( 'guard_dog_email_2fa_enabled', false ) &&
            $email_2fa &&
            method_exists( $email_2fa, 'is_email_2fa_enabled_for_user' )
        ) {
            $status['has_email_2fa'] = (bool) $email_2fa->is_email_2fa_enabled_for_user( $user->ID );
        }

        if ( ! $status['has_email_2fa'] && get_user_meta( $user->ID, '_guard_dog_email_2fa_enabled', true ) ) {
            $status['has_email_2fa'] = true;
        }

        if (
            $status['has_app_2fa'] &&
            $two_factor_auth &&
            method_exists( $two_factor_auth, 'user_has_recovery_codes' )
        ) {
            $status['has_recovery_codes'] = (bool) $two_factor_auth->user_has_recovery_codes( $user->ID );
        }

        $status['requires_2fa'] = $status['has_app_2fa'] || $status['has_email_2fa'];

        return apply_filters( 'guard_dog_login_2fa_status', $status, $user );
    }

    /**
     * Send an email 2FA code for a custom login flow.
     *
     * @since 1.9.40
     * @param int|WP_User|string $user User ID, user object, username, or email.
     * @return array|WP_Error
     */
    public function send_login_email_2fa_code( $user ) {
        $user = $this->normalize_user( $user );

        if ( ! $user ) {
            return new WP_Error( 'invalid_user', __( 'Invalid user.', 'guard-dog' ) );
        }

        $email_2fa = $this->get_feature( 'email_two_factor_auth' );

        if ( ! $email_2fa || ! method_exists( $email_2fa, 'send_verification_code' ) ) {
            return new WP_Error( 'email_2fa_unavailable', __( 'Email two-factor authentication is not available.', 'guard-dog' ) );
        }

        if ( method_exists( $email_2fa, 'is_email_2fa_enabled_for_user' ) && ! $email_2fa->is_email_2fa_enabled_for_user( $user->ID ) ) {
            return new WP_Error( 'email_2fa_not_enabled', __( 'Email two-factor authentication is not enabled for this user.', 'guard-dog' ) );
        }

        $result = $email_2fa->send_verification_code( $user->ID );

        if ( is_array( $result ) && ! empty( $result['success'] ) ) {
            return $result;
        }

        $message = is_array( $result ) && ! empty( $result['message'] )
            ? $result['message']
            : __( 'Unable to send the verification code.', 'guard-dog' );

        return new WP_Error( 'email_2fa_send_failed', $message, $result );
    }

    /**
     * Verify a 2FA code for a custom login flow.
     *
     * @since 1.9.40
     * @param int|WP_User|string $user   User ID, user object, username, or email.
     * @param string             $code   Verification or recovery code.
     * @param string             $method 2FA method: app, email, or recovery.
     * @return array|WP_Error
     */
    public function verify_login_2fa_code( $user, $code, $method = 'app' ) {
        $user = $this->normalize_user( $user );

        if ( ! $user ) {
            return new WP_Error( 'invalid_user', __( 'Invalid user.', 'guard-dog' ) );
        }

        if ( ! in_array( $method, array( 'app', 'email', 'recovery' ), true ) ) {
            return new WP_Error( 'invalid_2fa_method', __( 'Invalid two-factor authentication method.', 'guard-dog' ) );
        }

        if ( 'email' === $method ) {
            $email_2fa = $this->get_feature( 'email_two_factor_auth' );

            if ( ! $email_2fa || ! method_exists( $email_2fa, 'verify_code' ) ) {
                return new WP_Error( 'email_2fa_unavailable', __( 'Email-based two-factor authentication is not available.', 'guard-dog' ) );
            }

            $result = $email_2fa->verify_code( $user->ID, $code );

            if ( is_array( $result ) && ! empty( $result['success'] ) ) {
                return array(
                    'success' => true,
                    'message' => isset( $result['message'] ) ? $result['message'] : __( 'Verification successful.', 'guard-dog' ),
                    'user_id' => $user->ID,
                );
            }

            $message = is_array( $result ) && ! empty( $result['message'] )
                ? $result['message']
                : __( 'Email verification code is incorrect.', 'guard-dog' );

            return new WP_Error( 'email_2fa_failed', $message, $result );
        }

        $two_factor_auth = $this->get_feature( 'two_factor_auth' );

        if ( ! $two_factor_auth || ! method_exists( $two_factor_auth, 'verify_user_2fa_code' ) ) {
            return new WP_Error( 'app_2fa_unavailable', __( 'App-based two-factor authentication is not available.', 'guard-dog' ) );
        }

        $nonce  = wp_create_nonce( 'guard_dog_verify_2fa_login_' . $user->ID );
        $result = $two_factor_auth->verify_user_2fa_code( $user->user_login, $code, $nonce );

        if ( is_array( $result ) && ! empty( $result['success'] ) ) {
            return $result;
        }

        $message = is_array( $result ) && ! empty( $result['message'] )
            ? $result['message']
            : __( 'Two-factor authentication failed.', 'guard-dog' );

        return new WP_Error( 'app_2fa_failed', $message, $result );
    }

    /**
     * Check whether passkey login is available for public login surfaces.
     *
     * @since 1.9.40
     * @return bool
     */
    public function is_passkey_login_available() {
        $passkeys = $this->get_feature( 'passkeys' );

        return $passkeys && method_exists( $passkeys, 'is_enabled' ) && $passkeys->is_enabled();
    }

    /**
     * Get passkey login button markup.
     *
     * @since 1.9.40
     * @param array $args Optional template args.
     * @return string
     */
    public function get_passkey_login_button_markup( $args = array() ) {
        $passkeys = $this->get_feature( 'passkeys' );

        if ( ! $passkeys || ! method_exists( $passkeys, 'get_login_button_markup' ) ) {
            return '';
        }

        return $passkeys->get_login_button_markup( $args );
    }

    /**
     * Enqueue passkey login assets for custom login surfaces.
     *
     * @since 1.9.40
     * @param array $args Optional asset configuration.
     * @return void
     */
    public function enqueue_passkey_login_assets( $args = array() ) {
        $passkeys = $this->get_feature( 'passkeys' );

        if ( $passkeys && method_exists( $passkeys, 'enqueue_login_assets' ) ) {
            $passkeys->enqueue_login_assets( $args );
        }
    }

    /**
     * Enqueue public login assets needed by Guard Dog 2FA forms.
     *
     * @since 1.9.40
     * @return void
     */
	    public function enqueue_login_2fa_assets() {
	        if ( defined( 'GUARD_DOG_PLUGIN_FILE' ) ) {
	            wp_enqueue_style( 'guard-dog-login-2fa', plugins_url( 'assets/css/guard-dog-login-2fa.css', GUARD_DOG_PLUGIN_FILE ), array(), $this->version );
	        }

	        do_action( 'guard_dog_enqueue_public_login_2fa_assets', $this );
	    }

	    /**
	     * Enqueue frontend account-security assets before rendering.
	     *
	     * @since 1.9.40
	     * @param array $args Optional account-security configuration.
	     * @return void
	     */
	    public function enqueue_account_security_assets( $args = array() ) {
	        $two_factor_auth = $this->get_feature( 'two_factor_auth' );

	        if ( $two_factor_auth && method_exists( $two_factor_auth, 'enqueue_account_security_assets' ) ) {
	            $two_factor_auth->enqueue_account_security_assets( $args );
	        }
	    }

	    /**
	     * Normalize user input to a WP_User object.
     *
     * @since 1.9.40
     * @param int|WP_User|string $user User ID, user object, username, or email.
     * @return WP_User|null
     */
    private function normalize_user( $user ) {
        if ( $user instanceof WP_User ) {
            return $user;
        }

        if ( is_numeric( $user ) ) {
            $user = get_user_by( 'id', absint( $user ) );
        } elseif ( is_string( $user ) ) {
            $user = is_email( $user )
                ? get_user_by( 'email', sanitize_email( $user ) )
                : get_user_by( 'login', sanitize_user( $user ) );
        }

        return ( $user instanceof WP_User ) ? $user : null;
    }

         /**
     * Initialize admin functionality.
     *
     * @since 1.1.0
     */
     private function init_admin() {
         if (is_admin()) {
             // Initialize new multi-page admin interface
             $this->admin = new Guard_Dog_Admin($this->features);
         }
     }

    /**
     * Plugin activation.
     *
     * @since 1.1.0
     * @static
     */
    public static function activate() {
        // Ensure DB class is loaded for activation
        if (!class_exists('Guard_Dog_DB')) {
            require_once GUARD_DOG_PATH . 'includes/utils/class-guard-dog-db.php';
        }
        // Create/Update database tables using a temporary instance if main one not available yet
        $db_manager = new Guard_Dog_DB();
        $db_manager->install_tables();

        if (!class_exists('Guard_Dog_Activity_Log')) {
            require_once GUARD_DOG_PATH . 'includes/features/class-activity-log.php';
        }

        // Initialize Activity Log default settings: enable ALL events by default on fresh activation
        if (!class_exists('Guard_Dog_Activity_Log')) {
            require_once GUARD_DOG_PATH . 'includes/features/class-activity-log.php';
        }
        $existing_settings = get_option('guard_dog_activity_log_settings', null);
        if (!is_array($existing_settings) || !isset($existing_settings['events'])) {
            $settings = ['events' => []];
            $event_types = Guard_Dog_Activity_Log::get_available_event_types();
            foreach ($event_types as $event_key => $info) {
                $settings['events'][$event_key] = 1; // enable by default
            }
            update_option('guard_dog_activity_log_settings', $settings);
        }

        // Clean up legacy option if present (migrated away from old format)
        delete_option('guard_dog_logged_event_types');

        // Add default options
        // Note: guard_dog_login_slug is deliberately NOT seeded here. Creating the
        // row as an empty string makes get_option( 'guard_dog_login_slug', $default )
        // return '' forever, because get_option() only falls back to its default when
        // the option does not exist. That silently defeated every caller's default and
        // turned home_url( $slug ) into the site home page. The option is created when
        // a slug is actually saved; use Guard_Dog_Utils::get_login_base_url() to
        // resolve the login page rather than reading this option directly.
        add_option('guard_dog_temp_access_tokens', [], '', 'no');
        add_option('guard_dog_generic_login_error', '', '', 'yes');
        add_option('guard_dog_access_mode', 'blacklist', '', 'yes');
        add_option('guard_dog_ip_blacklist', '', '', 'no');
        add_option('guard_dog_ip_whitelist', '', '', 'no');
        add_option('guard_dog_user_blacklist', '', '', 'no');
        add_option('guard_dog_user_whitelist', '', '', 'no');
        add_option('guard_dog_site_wide_blocking', false, '', 'yes');
        add_option('guard_dog_access_denied_message', '', '', 'yes');
        add_option(Guard_Dog_Limit_Login_Attempts::OPTION_ENABLED, false, '', 'yes');
        add_option(Guard_Dog_Limit_Login_Attempts::OPTION_MAX_RETRIES, 5, '', 'yes');
        add_option(Guard_Dog_Limit_Login_Attempts::OPTION_LOCKOUT_DURATION, 15, '', 'yes');
        
        // Email 2FA options
        add_option('guard_dog_email_2fa_enabled', false, '', 'yes');
        add_option('guard_dog_email_provider', '', '', 'yes');
        add_option('guard_dog_email_provider_settings', [], '', 'yes');
        add_option('guard_dog_email_provider_global_override', false, '', 'yes');

        // Load feature classes for constants
        if (!class_exists('Guard_Dog_Email_Verification')) {
            require_once GUARD_DOG_PATH . 'includes/features/class-email-verification.php';
        }
        if (!class_exists('Guard_Dog_Password_Policy')) {
            require_once GUARD_DOG_PATH . 'includes/features/class-password-policy.php';
        }

        // Email verification options
        add_option(Guard_Dog_Email_Verification::OPTION_ENABLED, false, '', 'yes');
        add_option(Guard_Dog_Email_Verification::OPTION_EXPIRY, 48, '', 'yes');
        add_option(Guard_Dog_Email_Verification::OPTION_BYPASS_ADMIN, true, '', 'yes');
        add_option(Guard_Dog_Email_Verification::OPTION_RESEND_LIMIT, 3, '', 'yes');
        add_option(Guard_Dog_Email_Verification::OPTION_RESEND_DAILY_LIMIT, 5, '', 'yes');

        // Password policy options
        add_option(Guard_Dog_Password_Policy::OPTION_ENABLED, false, '', 'yes');
        add_option('guard_dog_password_min_length', 12, '', 'yes');
        add_option('guard_dog_password_require_uppercase', true, '', 'yes');
        add_option('guard_dog_password_require_lowercase', true, '', 'yes');
        add_option('guard_dog_password_require_numbers', true, '', 'yes');
        add_option('guard_dog_password_require_special', true, '', 'yes');
        add_option('guard_dog_password_block_common', false, '', 'yes');
        add_option('guard_dog_password_block_username', true, '', 'yes');
        add_option('guard_dog_password_block_email', true, '', 'yes');
        add_option('guard_dog_password_reuse_limit', 5, '', 'yes');
        add_option('guard_dog_password_policy_exempt_roles', [], '', 'yes');

        // Session manager options
        add_option('guard_dog_sessions_enabled', true, '', 'yes');
        add_option('guard_dog_sessions_max_per_user', 5, '', 'yes');
        add_option('guard_dog_sessions_timeout_minutes', 60, '', 'yes');
        add_option('guard_dog_sessions_detect_ip_shift', true, '', 'yes');
        add_option('guard_dog_sessions_detect_geo_anomaly', true, '', 'yes');
        add_option('guard_dog_sessions_notify_user', false, '', 'yes');

        // Reverse proxy configuration
        add_option('guard_dog_ip_detection_method', 'auto', '', 'yes');
        add_option('guard_dog_trusted_proxy_ips', '', '', 'no');

        // Passkeys (WebAuthn) options
        add_option('guard_dog_passkeys_enabled', false, '', 'yes');
        add_option('guard_dog_passkeys_bypass_2fa', true, '', 'yes');
        add_option('guard_dog_passkeys_require_user_verification', true, '', 'yes');

        // IP Reputation options
        add_option('guard_dog_ip_reputation_login_enabled', true, '', 'yes');
        add_option('guard_dog_ip_reputation_login_threshold', 80, '', 'yes');
        add_option('guard_dog_ip_reputation_session_enabled', true, '', 'yes');
        add_option('guard_dog_ip_reputation_session_threshold', 90, '', 'yes');
        add_option('guard_dog_ipinfo_token', '', '', 'yes');
        add_option('guard_dog_ip_reputation_disable_geo', false, '', 'yes');

        // User enumeration protection options
        add_option('guard_dog_enum_enabled', false, '', 'yes');
        add_option('guard_dog_enum_bypass_roles', ['administrator'], '', 'yes');
        add_option('guard_dog_enum_auto_block_enabled', true, '', 'yes');
        add_option('guard_dog_enum_auto_block_threshold', 20, '', 'yes');
        add_option('guard_dog_enum_auto_block_window', 60, '', 'yes');
        add_option('guard_dog_enum_auto_block_duration', 1440, '', 'yes');
        add_option('guard_dog_enum_rest_api_block', true, '', 'yes');
        add_option('guard_dog_enum_author_archives_block', true, '', 'yes');
        add_option('guard_dog_enum_login_errors_block', true, '', 'yes');
        add_option('guard_dog_enum_password_reset_block', true, '', 'yes');
        add_option('guard_dog_enum_xmlrpc_block', true, '', 'yes');
        add_option('guard_dog_enum_oembed_block', true, '', 'yes');
        add_option('guard_dog_enum_registration_block', true, '', 'yes');
        add_option('guard_dog_enum_alert_immediate_enabled', false, '', 'yes');
        add_option('guard_dog_enum_alert_immediate_threshold', 10, '', 'yes');
        add_option('guard_dog_enum_alert_immediate_window', 5, '', 'yes');
        add_option('guard_dog_enum_alert_immediate_email', '', '', 'yes');
        add_option('guard_dog_enum_alert_immediate_cooldown', 60, '', 'yes');
        add_option('guard_dog_enum_alert_digest_enabled', false, '', 'yes');
        add_option('guard_dog_enum_alert_digest_frequency', 'weekly', '', 'yes');
        add_option('guard_dog_enum_alert_digest_threshold', 50, '', 'yes');
        add_option('guard_dog_enum_alert_digest_email', '', '', 'yes');

        // Social Login options
        add_option('guard_dog_social_login_enabled', false, '', 'yes');
        add_option('guard_dog_social_auto_link_email', false, '', 'yes');
        add_option('guard_dog_social_auto_create_users', false, '', 'yes');
        add_option('guard_dog_social_new_user_role', 'subscriber', '', 'yes');
        add_option('guard_dog_social_bypass_2fa', false, '', 'yes');
        add_option('guard_dog_social_google_enabled', false, '', 'yes');
        add_option('guard_dog_social_google_client_id', '', '', 'yes');
        add_option('guard_dog_social_google_client_secret', '', '', 'yes');
        add_option('guard_dog_social_microsoft_enabled', false, '', 'yes');
        add_option('guard_dog_social_microsoft_client_id', '', '', 'yes');
        add_option('guard_dog_social_microsoft_client_secret', '', '', 'yes');
        add_option('guard_dog_social_apple_enabled', false, '', 'yes');
        add_option('guard_dog_social_apple_client_id', '', '', 'yes');
        add_option('guard_dog_social_apple_team_id', '', '', 'yes');
        add_option('guard_dog_social_apple_key_id', '', '', 'yes');
        add_option('guard_dog_social_apple_key_file', '', '', 'yes');

        // Create/Update database tables using the local instance created above
        $db_manager->install_tables();

        // Flush rewrite rules
        flush_rewrite_rules();
    }

    /**
     * Plugin deactivation.
     *
     * @since 1.1.0
     * @static
     */
    public static function deactivate() {
        // Flush rewrite rules to remove ours
        flush_rewrite_rules();
        
        // Clear scheduled cron jobs
        $timestamp = wp_next_scheduled('guard_dog_cleanup_expired_blacklist');
        if ($timestamp) {
            wp_unschedule_event($timestamp, 'guard_dog_cleanup_expired_blacklist');
        }

        // Clear session cleanup cron job
        $session_timestamp = wp_next_scheduled('guard_dog_cleanup_sessions');
        if ($session_timestamp) {
            wp_unschedule_event($session_timestamp, 'guard_dog_cleanup_sessions');
        }

        // Clear login attempt lockout cleanup cron job
        $lockout_cleanup_timestamp = wp_next_scheduled(Guard_Dog_Limit_Login_Attempts::CLEANUP_HOOK);
        if ($lockout_cleanup_timestamp) {
            wp_unschedule_event($lockout_cleanup_timestamp, Guard_Dog_Limit_Login_Attempts::CLEANUP_HOOK);
        }

        // Clear enumeration digest email cron job
        $enum_timestamp = wp_next_scheduled('guard_dog_enum_digest_email');
        if ($enum_timestamp) {
            wp_unschedule_event($enum_timestamp, 'guard_dog_enum_digest_email');
        }

        // Clear password baseline seeding cron job
        $baseline_timestamp = wp_next_scheduled('guard_dog_seed_password_baselines');
        if ($baseline_timestamp) {
            wp_unschedule_event($baseline_timestamp, 'guard_dog_seed_password_baselines');
        }

        // Clear session tracking meta from all users so they are not force-logged
        // out if the plugin is reactivated later.
        delete_metadata( 'user', 0, Guard_Dog_Session_Manager::USER_META_HAS_SESSION, '', true );
    }

    /**
     * Force database update (for troubleshooting)
     *
     * @since 1.6.0
     * @static
     */
    public static function force_db_update() {
        if (!class_exists('Guard_Dog_DB')) {
            require_once GUARD_DOG_PATH . 'includes/utils/class-guard-dog-db.php';
        }
        $db_manager = new Guard_Dog_DB();
        $db_manager->force_update();
    }

} // End final class Guard_Dog 
