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

namespace Hafenstudios\Kurato\Cockpit;

defined( 'ABSPATH' ) || exit;

/**
 * Produktions-Verwaltung der Schattennutzer (Bauplan Kap. 4.3). Je Agent ein
 * WP-Nutzer mit Rolle kurato_agent, verknuepft ueber die Nutzer-Meta
 * `kurato_agent_id`. Passwort-Login dieser Konten ist per Filter unterbunden
 * (AdminGuard); das gesetzte Passwort ist Zufall und wird nie herausgegeben.
 */
class WpShadowUserStore implements ShadowUserStore {

	private const META_AGENT_ID = 'kurato_agent_id';
	private const META_DISABLED = 'kurato_cockpit_disabled';

	/**
	 * @param string $agent_id Agent-ID.
	 * @return int|null
	 */
	public function find_by_agent( string $agent_id ): ?int {
		$users = get_users(
			array(
				'meta_key'   => self::META_AGENT_ID, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
				'meta_value' => $agent_id,           // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
				'number'     => 1,
				'fields'     => 'ID',
			)
		);
		if ( empty( $users ) ) {
			return null;
		}
		return (int) $users[0];
	}

	/**
	 * @param string $agent_id Agent-ID.
	 * @param string $email    E-Mail.
	 * @param string $name     Anzeigename.
	 * @return int
	 */
	public function create( string $agent_id, string $email, string $name ): int {
		$login = 'kurato_agent_' . substr( md5( $agent_id ), 0, 12 );
		$email = is_email( $email ) ? $email : ( $login . '@cockpit.invalid' );

		$user_id = wp_insert_user(
			array(
				'user_login'   => $login,
				'user_email'   => $email,
				'display_name' => '' !== $name ? $name : $login,
				'nickname'     => '' !== $name ? $name : $login,
				'user_pass'    => wp_generate_password( 40, true, true ),
				'role'         => CockpitRole::ROLE,
			)
		);

		if ( is_wp_error( $user_id ) ) {
			return 0;
		}

		update_user_meta( $user_id, self::META_AGENT_ID, $agent_id );
		update_user_meta( $user_id, self::META_DISABLED, '0' );
		return (int) $user_id;
	}

	/**
	 * @param int    $wp_user_id WP-Nutzer-ID.
	 * @param string $email      E-Mail.
	 * @param string $name       Anzeigename.
	 * @return void
	 */
	public function update( int $wp_user_id, string $email, string $name ): void {
		$data = array( 'ID' => $wp_user_id );
		if ( is_email( $email ) ) {
			$data['user_email'] = $email;
		}
		if ( '' !== $name ) {
			$data['display_name'] = $name;
		}
		if ( count( $data ) > 1 ) {
			wp_update_user( $data );
		}
	}

	/**
	 * @param int  $wp_user_id WP-Nutzer-ID.
	 * @param bool $active     Aktiv?
	 * @return void
	 */
	public function set_active( int $wp_user_id, bool $active ): void {
		update_user_meta( $wp_user_id, self::META_DISABLED, $active ? '0' : '1' );

		// Reaktivierung stellt die Rolle wieder her (nach deactivate_all beim
		// Trennen wurde sie entzogen; agents/sync heilt das beim Re-Pairing).
		if ( $active ) {
			$user = get_user_by( 'id', $wp_user_id );
			if ( $user instanceof \WP_User && ! in_array( CockpitRole::ROLE, (array) ( $user->roles ?? array() ), true ) ) {
				$user->set_role( CockpitRole::ROLE );
			}
		}
	}

	/**
	 * Entrechtet alle Schattennutzer (Trennen der Kopplung, CP1-9): Sperr-Meta
	 * plus Rollen-Entzug. Ohne Rolle bleiben null Capabilities, auch nach einem
	 * Passwort-Reset; der Nutzer selbst bleibt fuer die Attribution bestehen.
	 *
	 * @return void
	 */
	public function deactivate_all(): void {
		$users = get_users( array( 'role' => CockpitRole::ROLE ) );
		foreach ( $users as $user ) {
			if ( ! $user instanceof \WP_User ) {
				continue;
			}
			update_user_meta( (int) $user->ID, self::META_DISABLED, '1' );
			$user->set_role( '' );
		}
	}
}
