<?php

namespace UsernameBodyClass;

use WP_PowerSuite\Core\AbstractModule;

class Module extends AbstractModule {

	private const MODULE_ID      = 'username-body-class';
	private const MODULE_VERSION = '1.0.3';

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

	public function getName(): string {
		return __( 'Username Body Class', 'wp-powersuite' );
	}

	public function getVersion(): string {
		return self::MODULE_VERSION;
	}

	public function getDescription(): string {
		return __( 'Body classes for logged-in username and user ID—useful for theme tweaks and personalization. Privacy note: the username and ID appear in the page HTML source for that logged-in user.', 'wp-powersuite' );
	}

	public function getContext(): string|array {
		return [ 'frontend', 'admin' ];
	}

	protected function registerHooks(): void {
		if ( is_admin() ) {
			add_filter( 'admin_body_class', [ $this, 'addAdminUsernameBodyClasses' ], 10, 1 );
		} else {
			add_filter( 'body_class', [ $this, 'addUsernameBodyClasses' ], 10, 1 );
		}
	}

	public function addUsernameBodyClasses( array $classes ): array {
		return self::mergeIntoArray( $classes, self::collectUsernameClasses() );
	}

	public function addAdminUsernameBodyClasses( string $classes ): string {
		return self::appendToString( $classes, self::collectUsernameClasses() );
	}

	/**
	 * @return list<string>
	 */
	public static function collectUsernameClasses(): array {
		if ( ! is_user_logged_in() ) {
			return [];
		}

		$user = wp_get_current_user();
		if ( ! $user->exists() ) {
			return [];
		}

		$out = [];
		$user_class = 'user-' . sanitize_html_class( $user->user_login, 'user' );
		if ( ! in_array( $user_class, $out, true ) ) {
			$out[] = $user_class;
		}

		$id_class = 'user-id-' . (int) $user->ID;
		if ( ! in_array( $id_class, $out, true ) ) {
			$out[] = $id_class;
		}

		return $out;
	}

	/**
	 * @param list<string> $classes
	 * @param list<string> $extra
	 * @return list<string>
	 */
	private static function mergeIntoArray( array $classes, array $extra ): array {
		foreach ( $extra as $class ) {
			if ( ! in_array( $class, $classes, true ) ) {
				$classes[] = $class;
			}
		}

		return $classes;
	}

	/**
	 * @param list<string> $extra
	 */
	private static function appendToString( string $classes, array $extra ): string {
		if ( $extra === [] ) {
			return $classes;
		}

		$existing = preg_split( '/\s+/', trim( $classes ) );
		$existing = is_array( $existing ) ? $existing : [];

		foreach ( $extra as $class ) {
			if ( ! in_array( $class, $existing, true ) ) {
				$classes .= ' ' . $class;
				$existing[] = $class;
			}
		}

		return $classes;
	}
}
