<?php
/**
 * File Path: includes/admin/class-mbs-admin-dashboard.php
 *
 * Admin Dashboard Page
 *
 * Thin orchestrator: registers enqueue and render hooks, and provides
 * backward-compatible delegation wrappers for templates that call
 * get_catalog_stats(), get_aggregate_health(), fetch_news_feed(), and
 * fetch_brand_feed() on this class directly.
 *
 * Implementation is split across three service classes (REF-008):
 *   MBS_Dashboard_Health_Score  -- per-book and aggregate health scoring
 *   MBS_Dashboard_Feed_Fetcher  -- news feed, brand monitor, AJAX handlers
 *   MBS_Dashboard_Catalog_Stats -- catalog counts, aggregate health, pipeline
 *
 * @package MyBookShowroom
 * @since   1.1.0
 */

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

class MBS_Admin_Dashboard {

	private static ?self                      $instance      = null;
	private static ?MBS_Dashboard_Feed_Fetcher  $feed_fetcher  = null;  // R1-002: shared instance
	private static ?MBS_Dashboard_Catalog_Stats $catalog_stats = null;  // R1-002: shared instance

	/** Returns the shared singleton instance. */
	public static function get_instance(): self {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	private function __construct() {}

	/**
	 * Wire admin hooks. Instantiates MBS_Dashboard_Feed_Fetcher so it can
	 * register its own wp_ajax_ hooks in its constructor.
	 *
	 * Called once from MBS_Plugin::init() inside the is_admin() guard, before
	 * MBS_Admin is instantiated so the render callback exists when
	 * add_menu_page() runs on admin_menu.
	 */
	public static function init(): void {
		$dashboard = self::get_instance();
		add_action( 'admin_enqueue_scripts', array( $dashboard, 'enqueue_assets' ) );
		// Feed fetcher self-registers its wp_ajax_ hooks in its constructor (R1-002).
		self::$feed_fetcher = new MBS_Dashboard_Feed_Fetcher();
	}

	/**
	 * Enqueue dashboard-specific assets -- loaded only on the MBS dashboard page.
	 *
	 * @param string $hook_suffix Current admin page hook suffix.
	 */
	public function enqueue_assets( string $hook_suffix ): void {
		if ( 'toplevel_page_my-book-showroom' !== $hook_suffix ) {
			return;
		}
		wp_enqueue_style(
			'mbs-admin-dashboard',
			MBS_ASSETS_URL . 'css/mbs-admin-dashboard.css',
			array( 'dashicons' ),
			MBS_VERSION
		);
		foreach ( array( 'layout', 'hub', 'health', 'widgets' ) as $component ) {
			wp_enqueue_style(
				'mbs-dashboard-' . $component,
				plugins_url( 'assets/css/admin/dashboard/dashboard-' . $component . '.css', MBS_DIR . 'bookshowroom.php' ),
				array( 'mbs-admin-dashboard' ),
				MBS_VERSION
			);
		}

		// License hero card -- same stylesheet used by Settings > Dashboard tab.
		wp_enqueue_style(
			'mbs-admin-settings-license',
			plugins_url( 'assets/css/mbs-admin-settings-license.css', MBS_DIR . 'bookshowroom.php' ),
			array( 'mbs-admin-dashboard' ),
			MBS_VERSION
		);
		wp_enqueue_script(
			'mbs-admin-dashboard',
			MBS_ASSETS_URL . 'js/mbs-admin-dashboard.js',
			array( 'jquery', 'wp-i18n' ),
			MBS_VERSION,
			true
		);
		wp_set_script_translations( 'mbs-admin-dashboard', 'my-book-showroom', MBS_DIR . 'languages' );
		wp_localize_script(
			'mbs-admin-dashboard',
			'mbsDashboard',
			array(
				'ajaxUrl'    => admin_url( 'admin-ajax.php' ),
				'refreshNewsNonce' => wp_create_nonce( 'mbs_refresh_news_feed' ),
				'brandNonce' => wp_create_nonce( 'mbs_refresh_brand_monitor' ),
			)
		);
	}

	/**
	 * Render the dashboard page.
	 * Registered as the add_menu_page() callback in MBS_Admin::add_menu().
	 */
	public function render(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to view this page.', 'my-book-showroom' ) );
		}
		mbs_get_template_part( 'admin/dashboard' );
	}

	// ── Template delegation wrappers ──────────────────────────────────────────
	// Templates call these on MBS_Admin_Dashboard::get_instance() or as static
	// calls. Kept here for backward compatibility; implementation lives in the
	// service classes above.

	/**
	 * Catalog counts. Delegates to MBS_Dashboard_Catalog_Stats.
	 *
	 * @return array{total:int, published:int, drafts:int, featured:int}
	 */
	public function get_catalog_stats(): array {
		if ( null === self::$catalog_stats ) {
			self::$catalog_stats = new MBS_Dashboard_Catalog_Stats();
		}
		return self::$catalog_stats->get_catalog_stats();
	}

	/**
	 * Aggregate health score. Delegates to MBS_Dashboard_Catalog_Stats.
	 *
	 * @return array{score:float, scored:int}
	 */
	public function get_aggregate_health(): array {
		if ( null === self::$catalog_stats ) {
			self::$catalog_stats = new MBS_Dashboard_Catalog_Stats();
		}
		return self::$catalog_stats->get_aggregate_health();
	}

	/**
	 * Fetch MBS news feed. Delegates to MBS_Dashboard_Feed_Fetcher.
	 * Called statically from dashboard-news.php template.
	 *
	 * @return array<int,array{title:string,url:string,date:string}>
	 */
	public static function fetch_news_feed(): array {
		if ( null === self::$feed_fetcher ) {
			self::$feed_fetcher = new MBS_Dashboard_Feed_Fetcher();
		}
		return self::$feed_fetcher->fetch_news_feed();
	}

	/**
	 * Fetch Brand Monitor feed. Delegates to MBS_Dashboard_Feed_Fetcher.
	 * Called statically from dashboard-brand.php template.
	 *
	 * @return array<int,array{title:string,url:string,date:string}>
	 */
	public static function fetch_brand_feed(): array {
		if ( null === self::$feed_fetcher ) {
			self::$feed_fetcher = new MBS_Dashboard_Feed_Fetcher();
		}
		return self::$feed_fetcher->fetch_brand_feed();
	}
}
