<?php
/**
 * Single "Or" block for wp-login and Woo: one heading, all provider buttons.
 *
 * @package WP_PowerSuite\OAuth\UI
 */

namespace WP_PowerSuite\OAuth\UI;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class SocialLoginFormGroup {

	public const CONTEXT_WP_LOGIN = 'wp_login';
	public const CONTEXT_WOO      = 'woo';

	/** Display order; register missing slugs are skipped. */
	private const ORDER = [ 'google', 'facebook', 'github' ];

	private static bool $booted = false;

	/**
	 * @var array<string, array{cb: callable, woo: bool}>
	 */
	private static array $registrations = [];

	/**
	 * @param callable(string $context): ?array{html: string, icon_only: bool, row_inline: bool} $callback
	 */
	public static function register( string $slug, callable $callback, bool $include_woocommerce = false ): void {
		$slug = sanitize_key( $slug );
		if ( $slug === '' ) {
			return;
		}
		self::$registrations[ $slug ] = [
			'cb'  => $callback,
			'woo' => $include_woocommerce,
		];
		self::boot();
	}

	private static function boot(): void {
		if ( self::$booted ) {
			return;
		}
		self::$booted = true;
		add_action( 'login_form', [ self::class, 'render_wp_login' ], 9999 );
		add_action( 'woocommerce_login_form', [ self::class, 'render_woocommerce' ], 20 );
		add_action( 'woocommerce_register_form', [ self::class, 'render_woocommerce' ], 20 );
	}

	/**
	 * "──────── OR ────────" style separator (line / text / line).
	 * When $icon_only_mode is true (all providers use icon-only buttons), the label becomes "OR SIGN IN WITH".
	 */
	public static function or_separator_html( bool $icon_only_mode = false ): string {
		$classes = 'wpps-sl-embedded__or';
		if ( $icon_only_mode ) {
			/* translators: Separator label when social buttons show icons only. */
			$text  = __( 'OR SIGN IN WITH', 'wp-powersuite' );
			$label = _x( 'Or sign in with', 'accessibility label for the social login separator', 'wp-powersuite' );
			$classes .= ' wpps-sl-embedded__or--signin-with';
		} else {
			$text  = __( 'OR', 'wp-powersuite' );
			$label = _x( 'Or', 'accessibility label for the social login separator', 'wp-powersuite' );
		}
		return '<div class="' . esc_attr( $classes ) . '" role="separator" aria-label="' . esc_attr( $label ) . '">'
			. '<span class="wpps-sl-embedded__or-line" aria-hidden="true"></span>'
			. '<span class="wpps-sl-embedded__or-text">' . esc_html( $text ) . '</span>'
			. '<span class="wpps-sl-embedded__or-line" aria-hidden="true"></span></div>';
	}

	public static function render_wp_login(): void {
		$items = self::collect( self::CONTEXT_WP_LOGIN );
		if ( $items === [] ) {
			return;
		}
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- build_markup() returns escaped HTML.
		echo self::build_markup( $items, true );
	}

	public static function render_woocommerce(): void {
		$items = self::collect( self::CONTEXT_WOO );
		if ( $items === [] ) {
			return;
		}
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo self::build_markup( $items, false );
	}

	/**
	 * @return list<array{slug: string, html: string, row_inline: bool, icon_only: bool}>
	 */
	private static function collect( string $context ): array {
		$is_woo = ( self::CONTEXT_WOO === $context );
		$out    = [];
		foreach ( self::ORDER as $slug ) {
			if ( ! isset( self::$registrations[ $slug ] ) ) {
				continue;
			}
			$row = self::$registrations[ $slug ];
			if ( $is_woo && ! $row['woo'] ) {
				continue;
			}
			/** @var ?array{html: string, icon_only?: bool, row_inline?: bool} $data */
			$data = call_user_func( $row['cb'], $context );
			if ( ! is_array( $data ) || (string) ( $data['html'] ?? '' ) === '' ) {
				continue;
			}
			$row_inline = array_key_exists( 'row_inline', $data )
				? (bool) $data['row_inline']
				: ! empty( $data['icon_only'] );
			$out[] = [
				'slug'       => $slug,
				'html'       => (string) $data['html'],
				'row_inline' => $row_inline,
				'icon_only'  => ! empty( $data['icon_only'] ),
			];
		}
		return $out;
	}

	/**
	 * @param list<array{slug: string, html: string, row_inline: bool, icon_only: bool}> $items
	 */
	private static function build_markup( array $items, bool $is_wp_login_form ): string {
		$all_row = $items !== [] && ! in_array( false, array_column( $items, 'row_inline' ), true );
		$wrappers  = [];
		if ( $all_row ) {
			$wrappers[] = 'wpps-sl-embedded--inline';
		}
		if ( $is_wp_login_form ) {
			$wrappers[] = 'wpps-sl-embedded--wp-login';
		} else {
			$wrappers[] = 'wpps-sl-embedded--woo';
		}
		$all_icon  = $items !== [] && ! in_array( false, array_column( $items, 'icon_only' ), true );
		$cls   = 'wpps-sl-embedded' . ( $wrappers ? ' ' . implode( ' ', $wrappers ) : '' );
		$or    = self::or_separator_html( $all_icon );
		$inner = '';
		foreach ( $items as $it ) {
			$inner .= '<div class="wpps-sl-item wpps-sl-item--' . esc_attr( $it['slug'] ) . '">' . $it['html'] . '</div>';
		}

		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $inner is provider HTML
		$block = '<div class="' . esc_attr( $cls ) . '" data-wpps-social-embed="1">'
			. $or
			. '<div class="wpps-sl-embedded__buttons">' . $inner . '</div>'
			. '</div>';

		if ( $is_wp_login_form ) {
			return '<div id="wpps-sl-embed-container" class="wpps-sl-embed-container" data-wpps-sl-embed="1">' . $block . '</div>';
		}
		return $block;
	}
}
