<?php
/**
 * Active Logins Module
 *
 * @package     WPUltimateSecurity\UltimateSecurity\Modules\Authentication
 * @since       1.0.0
 */

declare(strict_types=1);

namespace WPUltimateSecurity\UltimateSecurity\Modules\Authentication;

use WPUltimateSecurity\UltimateSecurity\Modules\Base\AbstractModule;
use WPUltimateSecurity\UltimateSecurity\Support\Helpers\Utils;
use WPUltimateSecurity\UltimateSecurity\Support\Helpers\DateHelper;
use WPUltimateSecurity\UltimateSecurity\Modules\TestMode\TestModeService;
use WP_Error;
use WP_Session_Tokens;
use WP_User;

/**
 * Active Logins Module
 *
 * @since 1.0.0
 * @since 2.0.0 Migrated to extend AbstractModule.
 */
class ActiveLogins extends AbstractModule
{
    public const MODULE_ID = 'auth.active_logins';
    protected const VERSION = '2.0.0';

    public static function getId(): string
    {
        return self::MODULE_ID;
    }

    public static function getName(): string
    {
        return __('Active Logins', 'ultimate-security');
    }

    public static function getDomain(): string
    {
        return 'authentication';
    }

    public static function getConfigSchema(): array
    {
        return [
            'enable' => [
                'type' => 'boolean',
                'default' => false,
                'label' => __('Enable Active Logins Limit', 'ultimate-security'),
            ],
            'max_session' => [
                'type' => 'integer',
                'default' => 2,
                'label' => __('Maximum Sessions', 'ultimate-security'),
            ],
        ];
    }

    public static function boot(): void
    {
        self::action('wp_ajax_ultimate_security_send_password_reset_emails', [self::class, 'ultimate_security_send_password_reset_emails']);
        self::action('wp_ajax_nopriv_ultimate_security_send_password_reset_emails', [self::class, 'ultimate_security_send_password_reset_emails']);

        self::filter('authenticate', [self::class, 'ultimate_security_restrict_user_login_sessions'], 30, 3);
        self::action('clear_auth_cookie', [self::class, 'save_last_logout_time']);
    }

    /**
     * @param WP_User|WP_Error|null $user
     * @param string $username
     * @param string $password
     * @return WP_User|WP_Error|null
     */
    public static function ultimate_security_restrict_user_login_sessions($user, string $username, string $password)
    {
        $ultimate_security_options = Utils::ultimate_security_get_option();
        $enable = isset($ultimate_security_options['login']['active_logins']['enable']) ? sanitize_text_field(wp_unslash($ultimate_security_options['login']['active_logins']['enable'])) : 0;

        $max_session = isset($ultimate_security_options['login']['active_logins']['max_session']) ? sanitize_text_field(wp_unslash($ultimate_security_options['login']['active_logins']['max_session'])) : 2;

        if (is_wp_error($user) || empty($user)) {
            return $user;
        }

        if (isset($user->ID) && $enable) {
            $user_id = $user->ID;

            if (class_exists('WP_Session_Tokens')) {
                $session_tokens = WP_Session_Tokens::get_instance($user_id);
                $sessions = $session_tokens->get_all();

                if (count($sessions) >= (int) $max_session) {
                    if (TestModeService::shouldSimulate($user_id)) {
                        TestModeService::logSimulation(
                            'active_logins',
                            'too_many_sessions',
                            sprintf(
                                esc_html__('User would be blocked - has %d sessions, max is %d', 'ultimate-security'),
                                count($sessions),
                                $max_session
                            ),
                            [
                                'current_sessions' => count($sessions),
                                'max_sessions' => $max_session,
                            ]
                        );
                        return $user;
                    }

                    return new WP_Error(
                        'too_many_sessions',
                        sprintf(
                            esc_html__('You have reached the maximum number of allowed devices (%1$s). Please log out from another device to log in here. You are currently logged into %2$s devices.', 'ultimate-security'),
                            esc_html((string) $max_session),
                            esc_html((string) count($sessions))
                        )
                    );
                }
            }
        }

        return $user;
    }

    public static function ultimate_security_send_password_reset_emails(): void
    {
        if (isset($_POST['security']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['security'])), 'ultimate_security_nonce')) {
            if (!current_user_can('manage_options')) {
                wp_send_json_error(array('error_message' => esc_html__('You do not have permission to access this resource.', 'ultimate-security')));
            }
            $user_ids = isset($_REQUEST['user_ids']) ? sanitize_text_field(wp_unslash($_REQUEST['user_ids'])) : '';
            if ($user_ids) {
                $userArr = explode(",", $user_ids);
                foreach ($userArr as $user_id) {
                    $user = get_user_by('ID', $user_id);

                    if ($user) {
                        retrieve_password($user->user_login);
                    } else {
                        wp_send_json_error(array('error_message' => esc_html__('Users not found', 'ultimate-security')));
                    }
                }
            } else {
                wp_send_json_error(array('error_message' => esc_html__('Users not found', 'ultimate-security')));
            }
            wp_send_json_success(array('success_message' => esc_html__('Email send to users successfully!', 'ultimate-security')));
        } else {
            wp_send_json_error(array('error_message' => esc_html__('Nonce verification failed. Please try again.', 'ultimate-security')));
        }
        wp_die();
    }

    public static function save_last_logout_time(): void
    {
        $user = wp_get_current_user();

        if ($user && $user->ID) {
            update_user_meta($user->ID, 'last_logout_time', DateHelper::now());
        }
    }
}
