<?php
/**
 * UI helper.
 *
 * Central home for the approved design system in PHP: asset enqueue (scoped
 * admin.css + admin.js + Tabler icon font), the logo SVG, and reusable render
 * helpers (page header, stat tile, badge, card open/close, notice) so every
 * Helm screen emits consistent, design-matched markup.
 *
 * All Helm admin pages wrap their output in <div class="ph-wrap"> … </div> so
 * the scoped CSS applies and nothing leaks into wp-admin.
 *
 * @package Platform\Helm\Core
 */

declare( strict_types = 1 );

namespace Platform\Helm\Core;

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

final class Ui {

	private const TABLER_VERSION = '3.19.0';

	private static bool $assets_registered = false;

	public function register_hooks(): void {
		add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
	}

	/**
	 * Robustly decide whether the current admin screen belongs to Platform
	 * Helm. We check three independent signals because the hook suffix WP
	 * passes to admin_enqueue_scripts varies by how a page was registered
	 * (toplevel_page_*, helm_page_*, admin_page_* for hidden pages, etc.):
	 *   1. The enqueue hook string contains our slug.
	 *   2. The ?page= query arg starts with our slug.
	 *   3. The current screen id contains our slug.
	 * Any one match is enough.
	 */
	private function is_helm_screen( string $hook ): bool {
		if ( false !== strpos( $hook, 'platform-helm' ) ) {
			return true;
		}
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( (string) $_GET['page'] ) ) : '';
		if ( '' !== $page && 0 === strpos( $page, 'platform-helm' ) ) {
			return true;
		}
		if ( function_exists( 'get_current_screen' ) ) {
			$screen = get_current_screen();
			if ( $screen && isset( $screen->id ) && false !== strpos( (string) $screen->id, 'platform-helm' ) ) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Enqueue Helm admin assets only on Helm screens.
	 */
	public function enqueue( string $hook ): void {
		if ( ! $this->is_helm_screen( $hook ) ) {
			return;
		}

		wp_enqueue_style(
			'platform-helm-admin',
			PLATFORM_HELM_URL . 'assets/css/admin.css',
			[],
			PLATFORM_HELM_VERSION
		);

		// Tabler icon webfont. Prefer a bundled copy — it works offline and is
		// required for WordPress.org (no external CDN assets). Fall back to the
		// jsDelivr CDN only when the font has not been bundled locally.
		$local_tabler = 'assets/fonts/tabler/tabler-icons.min.css';
		if ( file_exists( PLATFORM_HELM_DIR . $local_tabler ) ) {
			wp_enqueue_style( 'tabler-icons', PLATFORM_HELM_URL . $local_tabler, [], self::TABLER_VERSION );
		} else {
			wp_enqueue_style(
				'tabler-icons',
				'https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@' . self::TABLER_VERSION . '/dist/tabler-icons.min.css',
				[],
				self::TABLER_VERSION
			);
		}

		wp_enqueue_script(
			'platform-helm-admin',
			PLATFORM_HELM_URL . 'assets/js/admin.js',
			[],
			PLATFORM_HELM_VERSION,
			true
		);

		wp_localize_script( 'platform-helm-admin', 'phAdmin', [
			'ajaxUrl' => admin_url( 'admin-ajax.php' ),
			'nonce'   => wp_create_nonce( 'ph_admin_nonce' ),
			'strings' => [
				'active'   => __( 'Active', 'platform-helm' ),
				'inactive' => __( 'Inactive', 'platform-helm' ),
				'saving'   => __( 'Saving…', 'platform-helm' ),
			],
		] );
	}

	/* ===================================================================== *
	 * LOGO
	 * ===================================================================== */

	/**
	 * Inline logo SVG (the Helm wheel). Variants: blue, white-on-dark, outline.
	 * Geometry adapted from the approved design's logo spec.
	 */
	public static function logo_svg( int $size = 32, string $variant = 'blue' ): string {
		$cx          = $size / 2;
		$rx          = round( $size * 0.25 );
		$r_ring      = $size * 0.15625;
		$sw          = $size * 0.0625;
		$r_hub       = $size * 0.078125;
		$spoke_start = $size * 0.125;
		$spoke_end   = $size * 0.28125;
		$diag_start  = $size * 0.2420;
		$o           = $size * 0.241;

		switch ( $variant ) {
			case 'white-on-dark':
				$fill = 'rgba(255,255,255,0.15)'; $stroke = '#ffffff'; $hub = '#ffffff';
				break;
			case 'outline':
				$fill = 'none'; $stroke = '#0047AB'; $hub = '#0047AB';
				break;
			case 'blue':
			default:
				$fill = '#0047AB'; $stroke = '#ffffff'; $hub = '#ffffff';
				break;
		}

		$line = function ( $x1, $y1, $x2, $y2 ) use ( $stroke, $sw ) {
			return sprintf(
				'<line x1="%s" y1="%s" x2="%s" y2="%s" stroke="%s" stroke-width="%s" stroke-linecap="round"/>',
				$x1, $y1, $x2, $y2, esc_attr( $stroke ), esc_attr( (string) $sw )
			);
		};

		$svg  = sprintf( '<svg width="%1$d" height="%1$d" viewBox="0 0 %1$d %1$d" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">', $size );
		$svg .= sprintf( '<rect width="%1$d" height="%1$d" rx="%2$s" fill="%3$s"/>', $size, esc_attr( (string) $rx ), esc_attr( $fill ) );
		$svg .= sprintf( '<circle cx="%1$s" cy="%1$s" r="%2$s" stroke="%3$s" stroke-width="%4$s" fill="none"/>', esc_attr( (string) $cx ), esc_attr( (string) $r_ring ), esc_attr( $stroke ), esc_attr( (string) $sw ) );
		// Cardinal spokes.
		$svg .= $line( $cx, $spoke_start, $cx, $spoke_end );
		$svg .= $line( $cx, $size - $spoke_start, $cx, $size - $spoke_end );
		$svg .= $line( $spoke_start, $cx, $spoke_end, $cx );
		$svg .= $line( $size - $spoke_start, $cx, $size - $spoke_end, $cx );
		// Diagonal spokes.
		$svg .= $line( $cx - $o, $cx - $o, $cx - $diag_start, $cx - $diag_start );
		$svg .= $line( $cx + $o, $cx + $o, $cx + $diag_start, $cx + $diag_start );
		$svg .= $line( $cx + $o, $cx - $o, $cx + $diag_start, $cx - $diag_start );
		$svg .= $line( $cx - $o, $cx + $o, $cx - $diag_start, $cx + $diag_start );
		// Hub.
		$svg .= sprintf( '<circle cx="%1$s" cy="%1$s" r="%2$s" fill="%3$s"/>', esc_attr( (string) $cx ), esc_attr( (string) $r_hub ), esc_attr( $hub ) );
		$svg .= '</svg>';
		return $svg;
	}

	/**
	 * Base64 data-URI of the logo, for the WP admin menu icon.
	 */
	public static function logo_menu_icon(): string {
		// Use the menu-grey colour WP expects; it recolours on hover/active.
		$svg = self::logo_svg( 20, 'blue' );
		// Recolour to a neutral so it sits well in the dark menu.
		$svg = str_replace( [ '#0047AB', '#ffffff' ], [ '#a7aaad', '#1d2327' ], $svg );
		return 'data:image/svg+xml;base64,' . base64_encode( $svg );
	}

	/* ===================================================================== *
	 * RENDER HELPERS (match the approved mockup's class vocabulary)
	 * ===================================================================== */

	/**
	 * Open the page wrapper + header. Pair with close_page().
	 * Markup mirrors the mockup: .page-header > (.ph-title/.ph-subtitle) + .ph-actions
	 */
	public static function open_page( string $title, string $subtitle = '', string $actions_html = '' ): void {
		echo '<div class="ph-wrap"><main class="ph-content">';
		echo '<div class="page-header"><div>';
		echo '<h1 class="ph-title">' . esc_html( $title ) . '</h1>';
		if ( '' !== $subtitle ) {
			echo '<p class="ph-subtitle">' . esc_html( $subtitle ) . '</p>';
		}
		echo '</div>';
		if ( '' !== $actions_html ) {
			echo '<div class="ph-actions">' . self::kses_actions( $actions_html ) . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		}
		echo '</div>';
	}

	/**
	 * Sanitiser for the page-header action slot. Like wp_kses_post() but also
	 * permits a <button> to submit a form by id via the HTML5 `form` attribute,
	 * so a header "Save" button can drive a form rendered lower on the page —
	 * the pattern used throughout the design.
	 *
	 * @param string $html
	 */
	private static function kses_actions( string $html ): string {
		return wp_kses(
			$html,
			[
				'a'      => [ 'href' => true, 'class' => true, 'target' => true, 'rel' => true, 'title' => true ],
				'button' => [ 'type' => true, 'name' => true, 'value' => true, 'form' => true, 'class' => true, 'id' => true, 'disabled' => true ],
				'i'      => [ 'class' => true, 'aria-hidden' => true ],
				'span'   => [ 'class' => true ],
			]
		);
	}

	public static function close_page(): void {
		echo '</main></div>';
	}

	/**
	 * Badge. Types: info, success, warning, danger, neutral, new.
	 */
	public static function badge( string $label, string $type = 'info', string $icon = '' ): string {
		$icon_html = '' !== $icon ? '<i class="ti ' . esc_attr( $icon ) . '" aria-hidden="true"></i> ' : '';
		return '<span class="badge badge-' . esc_attr( $type ) . '">' . $icon_html . esc_html( $label ) . '</span>';
	}

	/**
	 * Notice. Types: info, success, warning, danger.
	 */
	public static function notice( string $message_html, string $type = 'info' ): void {
		echo '<div class="notice notice-' . esc_attr( $type ) . '">' . wp_kses_post( $message_html ) . '</div>';
	}

	/**
	 * Stat tile matching the mockup. $color: blue|green|amber|red.
	 * $delta_type: up|warn|danger|'' .
	 */
	public static function stat_tile( string $label, string $value, string $color = 'blue', string $icon = 'ti-chart-bar', string $delta = '', string $delta_type = '', string $value_color = '' ): void {
		$vc = '' !== $value_color ? ' ' . $value_color : '';
		?>
		<div class="stat-tile st-<?php echo esc_attr( $color ); ?>">
			<div class="st-icon <?php echo esc_attr( $color ); ?>" aria-hidden="true"><i class="ti <?php echo esc_attr( $icon ); ?>"></i></div>
			<p class="st-label"><?php echo esc_html( $label ); ?></p>
			<p class="st-value<?php echo esc_attr( $vc ); ?>"><?php echo esc_html( $value ); ?></p>
			<?php if ( '' !== $delta ) : ?>
				<p class="st-delta <?php echo esc_attr( $delta_type ); ?>"><?php echo esc_html( $delta ); ?></p>
			<?php endif; ?>
		</div>
		<?php
	}

	/**
	 * Card open/close. Header is optional.
	 */
	public static function card_open( string $title = '', string $action_html = '', string $title_icon = '', string $extra_class = '' ): void {
		echo '<div class="card' . ( '' !== $extra_class ? ' ' . esc_attr( $extra_class ) : '' ) . '">';
		if ( '' !== $title || '' !== $action_html ) {
			echo '<div class="card-header">';
			if ( '' !== $title ) {
				$icon = '' !== $title_icon ? '<i class="ti ' . esc_attr( $title_icon ) . '"></i> ' : '';
				echo '<div class="card-title">' . $icon . esc_html( $title ) . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			}
			if ( '' !== $action_html ) {
				echo '<div class="card-action">' . wp_kses_post( $action_html ) . '</div>';
			}
			echo '</div>';
		}
		echo '<div class="card-body">';
	}

	public static function card_close(): void {
		echo '</div></div>';
	}
}
