<?php
/**
 * @package Hafenstudios\Kurato
 */

namespace Hafenstudios\Kurato\Cockpit;

defined( 'ABSPATH' ) || exit;

/**
 * Sperrt Schattennutzer aus dem wp-admin aus (Bauplan Versprechen 2, Kap. 4.3).
 *
 * - admin_init-Guard: jeder wp-admin-Aufruf eines kurato_agent wird auf die
 *   konfigurierte Cockpit-URL umgeleitet (keine Ausnahme, auch kein Profil).
 * - Admin-Bar aus.
 * - Passwort-Login der Schattennutzer per Filter unterbunden (Anmeldung nur
 *   ueber Cockpit-Tickets).
 *
 * Wird nur bei abgeschlossenem Pairing registriert (Null-Risiko-Default).
 */
class AdminGuard {

	private Config $config;

	/**
	 * @param Config $config Kopplungs-Zustand (fuer die Redirect-Ziel-URL).
	 */
	public function __construct( Config $config ) {
		$this->config = $config;
	}

	/**
	 * Registriert die Hooks.
	 *
	 * @return void
	 */
	public function register(): void {
		add_action( 'admin_init', array( $this, 'guard_admin' ), 0 );
		add_filter( 'show_admin_bar', array( $this, 'hide_admin_bar' ) );
		add_filter( 'authenticate', array( $this, 'block_password_login' ), 30 );
	}

	/**
	 * Leitet Agents aus dem wp-admin auf die Cockpit-URL um.
	 *
	 * @return void
	 */
	public function guard_admin(): void {
		$is_ajax = ( function_exists( 'wp_doing_ajax' ) && wp_doing_ajax() )
			|| ( defined( 'DOING_AJAX' ) && DOING_AJAX );

		if ( ! self::should_block_admin( true, (bool) $is_ajax, $this->current_user_is_agent() ) ) {
			return;
		}

		wp_safe_redirect( $this->config->origin(), 302, 'Kurato Cockpit' );
		exit;
	}

	/**
	 * Blendet die Admin-Bar fuer Agents aus.
	 *
	 * @param bool $show Bisheriger Wert.
	 * @return bool
	 */
	public function hide_admin_bar( $show ) {
		return $this->current_user_is_agent() ? false : $show;
	}

	/**
	 * Unterbindet den Passwort-Login von Schattennutzern.
	 *
	 * @param \WP_User|\WP_Error|null $user Ergebnis der bisherigen Auth-Kette.
	 * @return \WP_User|\WP_Error|null
	 */
	public function block_password_login( $user ) {
		if ( $user instanceof \WP_User && self::should_block_login( (array) ( $user->roles ?? array() ) ) ) {
			return new \WP_Error(
				'kurato_cockpit_login_blocked',
				__( 'Dieses Konto meldet sich im Cockpit an, nicht im WordPress-Login. Naechster Schritt: Oeffnen Sie das Cockpit und melden Sie sich dort an.', 'kurato' )
			);
		}
		return $user;
	}

	/**
	 * Reine Entscheidung: soll ein wp-admin-Aufruf blockiert werden?
	 *
	 * @param bool $is_admin Ist es ein wp-admin-Kontext?
	 * @param bool $is_ajax  Ist es ein admin-ajax-Aufruf?
	 * @param bool $is_agent Ist der aktuelle Nutzer ein Agent?
	 * @return bool
	 */
	public static function should_block_admin( bool $is_admin, bool $is_ajax, bool $is_agent ): bool {
		return $is_admin && ! $is_ajax && $is_agent;
	}

	/**
	 * Reine Entscheidung: soll der Passwort-Login blockiert werden?
	 *
	 * @param array<int, string> $roles Rollen des Nutzers.
	 * @return bool
	 */
	public static function should_block_login( array $roles ): bool {
		return in_array( CockpitRole::ROLE, $roles, true );
	}

	/**
	 * Ist der aktuelle Nutzer ein Agent?
	 *
	 * @return bool
	 */
	private function current_user_is_agent(): bool {
		if ( ! function_exists( 'wp_get_current_user' ) ) {
			return false;
		}
		$user = wp_get_current_user();
		return $user instanceof \WP_User && in_array( CockpitRole::ROLE, (array) ( $user->roles ?? array() ), true );
	}
}
