<?php
/**
 * Custom Login Logo Module
 *
 * @package CustomLoginLogo
 * @since 1.0.0
 */

namespace CustomLoginLogo;

use WP_PowerSuite\Core\AbstractModule;
use WP_PowerSuite\Core\OptionStoreModuleSettingsRepository;

class Module extends AbstractModule {

	private const MODULE_ID = 'custom-login-logo';
	private const MODULE_VERSION = '1.3.0';

	private bool $login_hooks_registered = false;

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

	public function getName(): string {
		return __( 'Custom Login Logo', 'wp-powersuite' );
	}

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

	public function getDescription(): string {
		return __( 'Your logo on the login page for a branded sign-in experience.', 'wp-powersuite' );
	}

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

	protected function registerHooks(): void {
		add_action( 'login_init', [ $this, 'registerLoginHooks' ], 0 );
		add_action( 'wpps_before_custom_login_render', [ $this, 'registerLoginHooks' ], 0 );
	}

	/**
	 * Register login screen hooks once per request (standard or custom login URL).
	 */
	public function registerLoginHooks(): void {
		if ( $this->login_hooks_registered || $this->isDelegatedToLoginPageCustomizor() ) {
			return;
		}

		$this->login_hooks_registered = true;

		$settings = $this->getResolvedSettings();
		$logo_url = $this->resolveLogoUrl( $settings );

		if ( $logo_url === '' ) {
			return;
		}

		add_action( 'login_enqueue_scripts', [ $this, 'enqueueLoginLogoStyles' ] );
		add_action( 'login_footer', [ $this, 'injectLoginLogoImg' ], 5 );
	}

	/**
	 * When Login Page Customizer (Pro) has form logo settings active, defer to it.
	 */
	private function isDelegatedToLoginPageCustomizor(): bool {
		if ( ! OptionStoreModuleSettingsRepository::isModuleEnabled( 'login-page-customizor' ) ) {
			return false;
		}

		$settings = OptionStoreModuleSettingsRepository::forModule( 'login-page-customizor' )->all( [] );
		if ( ! is_array( $settings ) ) {
			return false;
		}

		if ( ! empty( $settings['hide_logo'] ) && $settings['hide_logo'] !== '0' ) {
			return true;
		}

		$source = isset( $settings['logo_source'] ) ? (string) $settings['logo_source'] : 'upload';
		if ( $source === 'site_icon' && get_site_icon_url( 512 ) ) {
			return true;
		}
		if ( $source === 'url' && ! empty( $settings['logo_external_url'] ) ) {
			return true;
		}
		if ( ! empty( $settings['logo_url'] ) ) {
			return true;
		}

		$align = isset( $settings['logo_alignment'] ) ? (string) $settings['logo_alignment'] : 'center';
		if ( in_array( $align, [ 'left', 'right' ], true ) ) {
			return true;
		}

		foreach ( [ 'logo_width_desktop', 'logo_width_tablet', 'logo_width_mobile' ] as $key ) {
			if ( isset( $settings[ $key ] ) && is_numeric( $settings[ $key ] ) && (int) $settings[ $key ] > 0 ) {
				return true;
			}
		}

		foreach ( [ 'logo_margin_top', 'logo_margin_bottom' ] as $key ) {
			$value = isset( $settings[ $key ] ) ? trim( (string) $settings[ $key ] ) : '';
			if ( $value !== '' && is_numeric( $value ) ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * @return array<string, mixed>
	 */
	private function getResolvedSettings(): array {
		$defaults = $this->getDefaultSettings();
		$saved    = $this->moduleSettings()->all( [] );

		return array_merge( $defaults, is_array( $saved ) ? $saved : [] );
	}

	/**
	 * @param array<string, mixed> $settings Module settings.
	 */
	private function resolveLogoUrl( array $settings ): string {
		$source = $settings['logo_source'] ?? 'upload';

		if ( $source === 'site_icon' ) {
			$icon = get_site_icon_url( 512 );
			return is_string( $icon ) && $icon !== '' ? $icon : '';
		}

		$logo_url = isset( $settings['logo_url'] ) ? trim( (string) $settings['logo_url'] ) : '';
		if ( $logo_url === '' || ! $this->isValidLogoUrl( $logo_url ) ) {
			return '';
		}

		return esc_url( $logo_url );
	}

	public function enqueueLoginLogoStyles(): void {
		$settings = $this->getResolvedSettings();
		$logo_url = $this->resolveLogoUrl( $settings );

		if ( $logo_url === '' ) {
			return;
		}

		$width  = min( 500, max( 50, absint( $settings['logo_width'] ?? 200 ) ) );
		$height = min( 200, max( 30, absint( $settings['logo_height'] ?? 80 ) ) );
		$mode   = $settings['logo_size_mode'] ?? 'contain';

		$base = defined( 'WP_POWERSUITE_PLUGIN_URL' ) ? WP_POWERSUITE_PLUGIN_URL : '';
		$url  = $base . 'modules/' . self::MODULE_ID . '/assets/custom-login-logo.css';

		wp_enqueue_style( 'wpps-custom-login-logo', $url, [], self::MODULE_VERSION );

		$selector = '.login:not(.interim-login) h1 a,.login:not(.interim-login) h1.wp-login-logo a';

		if ( ( $settings['logo_source'] ?? 'upload' ) === 'site_icon' ) {
			$size_css = match ( $mode ) {
				'fixed'   => "background-size:{$width}px {$height}px;width:{$width}px;height:{$height}px",
				'cover'   => "background-size:cover;width:{$width}px;height:{$height}px",
				default   => "background-size:contain;width:{$width}px;height:{$height}px",
			};
			$inline = $selector . '{background-image:url(' . esc_url( $logo_url ) . ') !important;' . $size_css . ' !important;}';
			wp_add_inline_style( 'wpps-custom-login-logo', $inline );
			return;
		}

		$inline = $selector . '{background-image:none !important;width:auto !important;height:auto !important;overflow:visible !important;padding:0 !important;}';
		$inline .= '.login:not(.interim-login) h1 a .wpps-custom-login-logo-img,.login:not(.interim-login) h1.wp-login-logo a .wpps-custom-login-logo-img{';
		$inline .= 'max-width:' . $width . 'px;max-height:' . $height . 'px;width:auto;height:auto;display:block;object-fit:contain;}';

		wp_add_inline_style( 'wpps-custom-login-logo', $inline );
	}

	public function injectLoginLogoImg(): void {
		$settings = $this->getResolvedSettings();

		if ( ( $settings['logo_source'] ?? 'upload' ) === 'site_icon' ) {
			return;
		}

		$logo_url = $this->resolveLogoUrl( $settings );
		if ( $logo_url === '' ) {
			return;
		}

		$alt = $this->getLogoAltText();
		?>
		<script>
		(function() {
			var link = document.querySelector('.login:not(.interim-login) h1.wp-login-logo a') || document.querySelector('.login:not(.interim-login) h1 a');
			if (!link) return;
			var img = document.createElement('img');
			img.src = <?php echo wp_json_encode( $logo_url ); ?>;
			img.alt = <?php echo wp_json_encode( $alt ); ?>;
			img.className = 'wpps-custom-login-logo-img';
			link.innerHTML = '';
			link.appendChild(img);
		})();
		</script>
		<?php
	}

	private function getLogoAltText(): string {
		$name = get_bloginfo( 'name', 'display' );
		return is_string( $name ) && $name !== '' ? $name : '';
	}

	private function isValidLogoUrl( string $url ): bool {
		if ( $url === '' ) {
			return false;
		}

		$url = esc_url_raw( $url );
		if ( $url === '' ) {
			return false;
		}

		$allowed = array_filter( [
			untrailingslashit( home_url() ),
			untrailingslashit( site_url() ),
			untrailingslashit( content_url() ),
			untrailingslashit( ( wp_upload_dir() )['baseurl'] ?? '' ),
		] );

		foreach ( $allowed as $base ) {
			if ( str_starts_with( $url, $base . '/' ) || $url === $base ) {
				return true;
			}
		}

		return false;
	}

	public function getDefaultSettings(): array {
		return [
			'logo_source'    => 'upload',
			'logo_url'         => '',
			'logo_width'       => 200,
			'logo_height'      => 80,
			'logo_size_mode'   => 'contain',
		];
	}
}
