<?php
/**
 * @package   admintoolswp
 * @copyright Copyright (c)2017-2026 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU GPL version 3 or later
 */

use Akeeba\AdminTools\Admin\Helper\Language;
use Akeeba\AdminTools\Admin\Helper\Wordpress;

defined('ADMINTOOLSINC') or die;

class AtsystemFeatureDisableobsoleteadmins extends AtsystemFeatureAbstract
{
	protected $loadOrder = 950;

	/**
	 * Is this feature enabled?
	 *
	 * @return bool
	 */
	public function isEnabled()
	{
		return true;
	}

	/**
	 * Register custom hooks to display and save extra user profile fields
	 */
	public function onCustomHooks()
	{
		add_action('edit_user_profile', [$this, 'displayExtraFields']);
		add_action('show_user_profile', [$this, 'displayExtraFields']);
		add_action('personal_options_update', [$this, 'saveExtraFields']);
		add_action('edit_user_profile_update', [$this, 'saveExtraFields']);
	}

	/**
	 * Run the periodic check for obsolete admins
	 */
	public function onWordPressInit()
	{
		$lastRun  = $this->cparams->getValue('disableobsoleteadmins_lastrun', 0);
		$freq     = (int) $this->cparams->getValue('disableobsoleteadmins_freq', 24);
		$interval = $freq * 3600;

		if (time() - $lastRun < $interval)
		{
			return;
		}

		$this->cparams->setValue('disableobsoleteadmins_lastrun', time(), true);

		$roles   = $this->cparams->getValue('disableobsoleteadmins_roles', 'administrator');

		if (is_string($roles))
		{
			$roles = explode(',', $roles);
		}

		$maxDays = (int) $this->cparams->getValue('disableobsoleteadmins_maxdays', 90);

		if (empty($roles))
		{
			return;
		}

		$maxTimestamp = time() - ($maxDays * 86400);

		$users = get_users(['role__in' => $roles]);

		foreach ($users as $user)
		{
			$lastLogin = get_user_meta($user->ID, 'admintoolswp_last_login', true);

			// If we don't have a last login timestamp, we ignore the user
			if ($lastLogin === '')
			{
				continue;
			}

			// If we have a last login timestamp of 0, we assume the user has never logged in.
			// However, to be safe, we might want to check the registration date if it's available.
			if (!$lastLogin)
			{
				$registered = strtotime($user->user_registered);
				$lastLogin  = $registered;
			}

			if ($lastLogin < $maxTimestamp)
			{
				update_user_meta($user->ID, 'admintoolswp_blocked', 1);
			}
		}
	}

	/**
	 * Prevent blocked users from authenticating
	 *
	 * @param   WP_Error|WP_User  $user
	 * @param   string            $username
	 * @param   string            $password
	 *
	 * @return  WP_User|WP_Error
	 */
	public function onUserAuthenticate($user, $username, $password)
	{
		if ($user instanceof WP_User)
		{
			$isBlocked = get_user_meta($user->ID, 'admintoolswp_blocked', true);

			if ($isBlocked)
			{
				return new WP_Error('admintoolswp_blocked', Language::_('COM_ADMINTOOLS_ERROR_USER_BLOCKED'));
			}
		}

		return $user;
	}

	/**
	 * Track last login time
	 *
	 * @param   string   $user_login
	 * @param   WP_User  $user
	 */
	public function onUserLogin($user_login, $user)
	{
		if ($user instanceof WP_User)
		{
			update_user_meta($user->ID, 'admintoolswp_last_login', time());
			// Unblock if they somehow managed to log in (e.g. administrator unblocked them)
			delete_user_meta($user->ID, 'admintoolswp_blocked');
		}
	}

	/**
	 * Intercept user profile saving to prevent unblocking if protected
	 *
	 * @param   WP_Error  $errors  Holds the full stack of WP errors
	 * @param   bool      $update  Is this a new user or updating an existing one?
	 * @param   WP_User   $user    WordPress user object
	 */
	public function onUserBeforeSave(&$errors, $update, &$user)
	{
		if (!$update)
		{
			// All newly created users must have this user meta field with its value set to 0.
			$user->admintoolswp_last_login = 0;

			return;
		}

		if (!isset($user->ID))
		{
			return;
		}

		// If a user is saved but does not have the admintoolswp_last_login meta field then we set it to 0
		$lastLogin = get_user_meta($user->ID, 'admintoolswp_last_login', true);

		if ($lastLogin === '')
		{
			update_user_meta($user->ID, 'admintoolswp_last_login', 0);
		}

		// if, however, we are saving our own user we set the value of this field to the current timestamp.
		if ($user->ID == get_current_user_id())
		{
			update_user_meta($user->ID, 'admintoolswp_last_login', time());
		}

		$protected = $this->cparams->getValue('disableobsoleteadmins_protected', 1);

		if (!$protected)
		{
			return;
		}

		$isBlocked = get_user_meta($user->ID, 'admintoolswp_blocked', true);

		if ($isBlocked)
		{
			// If it's not a super admin, prevent unblocking
			if (!is_super_admin())
			{
				update_user_meta($user->ID, 'admintoolswp_blocked', 1);
			}
		}
	}

	/**
	 * Public function used to display the additional fields in the user profile
	 *
	 * @param   WP_User  $user
	 */
	public function displayExtraFields($user)
	{
		$blocked_label    = Language::_('COM_ADMINTOOLS_LBL_USER_BLOCKED');
		$last_login_label = Language::_('COM_ADMINTOOLS_LBL_USER_LAST_LOGIN');
		$never_label      = Language::_('COM_ADMINTOOLS_LBL_USER_NEVER');

		$isBlocked = get_user_meta($user->ID, 'admintoolswp_blocked', true);
		$checked   = $isBlocked ? 'checked="checked"' : '';

		$lastLogin = get_user_meta($user->ID, 'admintoolswp_last_login', true);
		$lastLoginDisplay = $never_label;

		if ($lastLogin)
		{
			$lastLoginDisplay = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $lastLogin);
		}

		$html = <<<HTML
<h3>AdminTools for WordPress</h3>
<table class="form-table">
	<tr>
    	<th><label for="admintoolswp_blocked">$blocked_label</label></th>
      	<td>
      		<input type="checkbox" name="admintoolswp_blocked" id="admintoolswp_blocked" value="1" $checked />
		</td>
	</tr>
	<tr>
    	<th><label>$last_login_label</label></th>
      	<td>
      		<input type="text" value="$lastLoginDisplay" class="regular-text" readonly />
		</td>
	</tr>
</table>
HTML;

		echo $html;
	}

	/**
	 * Saves the additional fields from the user profile
	 *
	 * @param   int  $user_id
	 */
	public function saveExtraFields($user_id)
	{
		if (!current_user_can('edit_user', $user_id))
		{
			return;
		}

		if (isset($_POST['admintoolswp_blocked']) && $_POST['admintoolswp_blocked'] == '1')
		{
			update_user_meta($user_id, 'admintoolswp_blocked', 1);
		}
		else
		{
			delete_user_meta($user_id, 'admintoolswp_blocked');
		}
	}

	/**
	 * Fires as soon as the user as been saved
	 *
	 * @param   int  $user_id
	 */
	public function onUserAfterSave($user_id)
	{
		$user = get_userdata($user_id);

		if (isset($user->admintoolswp_last_login))
		{
			update_user_meta($user_id, 'admintoolswp_last_login', $user->admintoolswp_last_login);
		}
	}
}
