<?php
/**
 * Handles the Custom Login Error Message feature for Guard Dog.
 *
 * @package GuardDog
 * @since 1.3.0 // Or your appropriate starting version for this feature
 */

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

class Guard_Dog_Login_Errors {

    /**
     * Constructor. Adds the filter.
     *
     * @since 1.3.0
     */
    public function __construct() {
        $this->add_hooks();
    }

    /**
     * Adds the necessary WordPress hooks.
     *
     * @since 1.3.0
     */
    public function add_hooks() {
        add_filter('login_errors', [$this, 'filter_login_errors'], 99); // Use priority 99 to run after most other checks
    }

    /**
     * Filters the login error messages.
     *
     * Replaces standard errors with a generic one if configured, but preserves specific
     * errors like 2FA prompts.
     *
     * @since 1.3.0
     * @param string $error The HTML error message to be displayed.
     * @return string Filtered error message.
     */
    public function filter_login_errors($error) {
        // Check if the generic error setting exists and is populated.
        $option_key = 'guard_dog_generic_login_error'; // Default to string key
        if (class_exists('Guard_Dog_Admin_Settings')) {
            $option_key = Guard_Dog_Admin_Settings::OPTION_GENERIC_ERROR;
        }

        $generic_message_setting = get_option($option_key, '');
        // If the generic message is blank or only whitespace, always return the original error
        if (trim($generic_message_setting) === '') {
            return $error;
        }

        // Only proceed if a generic message is configured
        if (!empty($generic_message_setting)) {

            // Check if the current error is one of our 2FA errors that should NOT be hidden.
            // Assumes Guard_Dog_Two_Factor_Auth class is loaded and constants defined.
            $is_critical_error = false;
            if (class_exists('Guard_Dog_Two_Factor_Auth')) {
                // Check if the error message contains the specific WP_Error codes.
                // Note: $error is the MESSAGE, not the CODE here. We need to check if the CODE was the trigger.
                // A more robust way is to check the global $wp_error object if possible, but login_errors filter doesn't pass it.
                // Alternative: Check if the error message contains parts of the 2FA error messages.
                $is_critical_error = (
                    strpos($error, Guard_Dog_Two_Factor_Auth::ERROR_CODE_REQUIRED) !== false || // Check if code is embedded
                    strpos($error, Guard_Dog_Two_Factor_Auth::ERROR_CODE_INVALID) !== false || // Check if code is embedded
                    strpos($error, 'Verification Required') !== false || // Fallback message check
                    strpos($error, 'verification code is incorrect') !== false // Fallback message check
                );
            }

            // If it's a critical error (like 2FA needed), keep the original message.
            if ($is_critical_error) {
                return $error;
            }

            // List of substrings found in standard WP login error messages (case-insensitive check)
            // These are the errors we WANT to hide with the generic message.
            $standard_error_fragments = [
                'is incorrect', // Covers incorrect password message like "...is incorrect."
                'unknown username',
                'invalid username', // Covers both common username errors
                'unknown email address',
                'invalid email address', // Covers both common email errors
                'username field is empty',
                'password field is empty',
                'invalid key', // Password reset key invalid/expired
                'expired key'  // Password reset key expired
                // Add more specific fragments if needed, avoid overly generic ones
            ];

            // Check if the incoming error string contains any standard fragments
            $error_lower = strtolower($error); // Case-insensitive comparison
            $is_standard_error_to_hide = false;
            foreach ($standard_error_fragments as $fragment) {
                if (strpos($error_lower, $fragment) !== false) {
                    $is_standard_error_to_hide = true;
                    break;
                }
            }

            // If it's a standard error we want to hide, return the sanitized generic message.
            if ($is_standard_error_to_hide) {
                // Sanitize the stored generic message using wp_kses_post
                return wp_kses_post($generic_message_setting);
            }
        }

        // Return the original error if no generic message is set, or if it's not an error we want to hide.
        return $error;
    }

} // End class Guard_Dog_Login_Errors
