<?php
/**
 * Code Snippet Admin Bar Info
 *
 * Shows which snippets are loaded on the current page in the admin bar.
 *
 * @package CodeSnippet
 * @since 1.0.0
 */

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

/**
 * Track and display loaded snippets in admin bar.
 */
class Wpps_Cs_Admin_Bar {

	/** @var array<int, \WP_Post> Loaded snippets by post ID (unique). */
	public $loaded_snippets = [];

	/** @var \CodeSnippet\Module */
	private $module;

	public function __construct( \CodeSnippet\Module $module ) {
		$this->module = $module;
		add_action( 'admin_bar_menu', [ $this, 'add_admin_bar_info' ], 999 );
		// Admin Only, and Frontend Only snippets are tracked.
		add_filter( 'wpps_code_snippet_output', [ $this, 'track_snippet' ], 999, 3 );
		add_action( 'wpps_snippet_loaded', [ $this, 'track_snippet_direct' ], 10, 2 );
		// Auth is ready at init. plugins_loaded is too early (and may already have fired).
		if ( did_action( 'init' ) ) {
			$this->maybe_init();
		} else {
			add_action( 'init', [ $this, 'maybe_init' ], 20 );
		}
	}

	public function maybe_init(): void {
		if ( ! $this->module->isEnabled() ) {
			return;
		}
		if ( ! \CodeSnippet\Module::getSetting( 'admin_bar_info', true ) ) {
			return;
		}
		if ( ! is_user_logged_in() || ! current_user_can( 'manage_options' ) ) {
			return;
		}
		add_action( 'wp_footer', [ $this, 'add_footer_info' ], 99999 );
		add_action( 'admin_footer', [ $this, 'add_footer_info' ], 999999 );
	}

	/**
	 * Track snippet via action (for merged PHP that bypasses output filter).
	 *
	 * @param \WP_Post $post     Snippet post.
	 * @param string   $location Location slug.
	 */
	public function track_snippet_direct( \WP_Post $post, string $location ): void {
		$this->loaded_snippets[ $post->ID ] = $post;
	}

	/**
	 * Track snippet when it outputs.
	 *
	 * @param string   $output Snippet output.
	 * @param string   $type   Code type.
	 * @param \WP_Post $post   Snippet post.
	 * @return string
	 */
	public function track_snippet( string $output, string $type, \WP_Post $post ): string {
		$this->loaded_snippets[ $post->ID ] = $post;
		return $output;
	}

	/**
	 * Add admin bar menu.
	 *
	 * @param \WP_Admin_Bar $wp_admin_bar Admin bar.
	 */
	public function add_admin_bar_info( \WP_Admin_Bar $wp_admin_bar ): void {
		if ( ! $this->module->isEnabled() || ! \CodeSnippet\Module::getSetting( 'admin_bar_info', true ) ) {
			return;
		}
		if ( ! is_user_logged_in() || ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$total = count( $this->loaded_snippets );

		$wp_admin_bar->add_menu(
			[
				'id'    => 'wpps-cs-admin-bar',
				'title' => 'Code Snippets' . ( $total > 0 ? ' (' . $total . ')' : '' ),
				'href'  => admin_url( 'admin.php?page=powersuite-code-snippet' ),
				'meta'  => [ 'class' => 'wpps-cs-admin-bar-info menupop' ],
			]
		);

		// Flat children under the top menu — nested WP admin-bar menus are unreliable.
		$wp_admin_bar->add_menu(
			[
				'id'     => 'wpps-cs-loaded',
				'parent' => 'wpps-cs-admin-bar',
				'title'  => __( 'Loaded on this page', 'wp-powersuite' ),
				'meta'   => [ 'class' => 'wpps-cs-admin-bar-description' ],
			]
		);

		// Placeholder removed by footer JS and replaced with the snippet list.
		$wp_admin_bar->add_menu(
			[
				'id'     => 'wpps-cs-admin-bar-replace',
				'parent' => 'wpps-cs-admin-bar',
				'title'  => __( 'Loading…', 'wp-powersuite' ),
				'meta'   => [ 'class' => 'wpps-cs-admin-bar-submenu' ],
			]
		);

		$wp_admin_bar->add_menu(
			[
				'id'     => 'wpps-cs-add-snippet',
				'parent' => 'wpps-cs-admin-bar',
				'title'  => __( '+ Add Snippet', 'wp-powersuite' ),
				'href'   => admin_url( 'admin.php?page=powersuite-code-snippet&action=add' ),
				'meta'   => [ 'class' => 'wpps-cs-admin-bar-submenu wpps-cs-admin-bar-separator' ],
			]
		);

		$wp_admin_bar->add_menu(
			[
				'id'     => 'wpps-cs-settings',
				'parent' => 'wpps-cs-admin-bar',
				'title'  => __( 'Settings', 'wp-powersuite' ),
				'href'   => admin_url( 'admin.php?page=powersuite-code-snippet&view=settings' ),
				'meta'   => [ 'class' => 'wpps-cs-admin-bar-submenu' ],
			]
		);
	}

	/**
	 * Output footer script with loaded snippets data.
	 */
	public function add_footer_info(): void {
		if ( ! is_admin_bar_showing() ) {
			return;
		}

		$snippets = array_values( $this->loaded_snippets );
		$footer_info = array_map( function ( $post ) {
			$type = get_post_meta( $post->ID, '_wpps_code_type', true ) ?: 'html';
			return [
				'id'         => $post->ID,
				'title'      => esc_html( $post->post_title ),
				'code_type'  => sanitize_key( $type ),
				'edit_link'  => admin_url( 'admin.php?page=powersuite-code-snippet&action=edit&id=' . $post->ID ),
			];
		}, $snippets );
		?>
		<script>
			var wpps_cs_admin_bar_info = <?php echo wp_json_encode( $footer_info ); ?>;
			(function() {
				var count = wpps_cs_admin_bar_info ? wpps_cs_admin_bar_info.length : 0;
				var titleEl = document.querySelector('#wp-admin-bar-wpps-cs-admin-bar > .ab-item');
				if (titleEl) {
					titleEl.textContent = 'Code Snippets' + (count > 0 ? ' (' + count + ')' : '');
				}
				var replaceLi = document.getElementById('wp-admin-bar-wpps-cs-admin-bar-replace');
				if (!replaceLi) return;
				var parentUl = replaceLi.parentNode;
				if (!parentUl) return;
				var insertBefore = replaceLi.nextSibling;
				replaceLi.remove();
				if (!wpps_cs_admin_bar_info || wpps_cs_admin_bar_info.length === 0) {
					var emptyLi = document.createElement('li');
					emptyLi.className = 'wpps-cs-admin-bar-empty';
					var emptyA = document.createElement('a');
					emptyA.className = 'ab-item';
					emptyA.href = '#';
					emptyA.textContent = '<?php echo esc_js( __( 'No snippets loaded', 'wp-powersuite' ) ); ?>';
					emptyLi.appendChild(emptyA);
					parentUl.insertBefore(emptyLi, insertBefore);
					return;
				}
				wpps_cs_admin_bar_info.forEach(function(s) {
					var sli = document.createElement('li');
					var sa = document.createElement('a');
					sa.className = 'ab-item';
					sa.href = s.edit_link || '#';
					var label = s.title || '';
					if (s.code_type) {
						label = label ? (label + ' (' + String(s.code_type).toUpperCase() + ')') : String(s.code_type).toUpperCase();
					}
					sa.textContent = label;
					sli.appendChild(sa);
					parentUl.insertBefore(sli, insertBefore);
				});
			})();
		</script>
		<?php
	}
}
