<?php
/**
 * Shared performance budget values loaded from config/performance-budgets.json.
 *
 * Budget pipeline:
 * - **CI static hook scan** ({@see bin/check-module-hook-budgets.php}): counts `add_action` /
 *   `add_filter` calls in each module.php against `max_static_hooks_per_module`.
 * - **Runtime hook deltas** ({@see HookTracker} during module init): compares `$wp_filter`
 *   before/after init against `max_hooks_per_module`; violations are logged via error_log.
 * - **Init time / memory** ({@see PerformanceMonitor}): collected when the monitor is
 *   enabled in Settings ({@see self::isDetailedMetricsEnabled()}).
 * - **Fatal-error shutdown handler** ({@see PerformanceMonitor}): registered only when
 *   the monitor is enabled in Settings.
 *
 * @package WP_PowerSuite\Core
 * @since 1.0.0
 */

namespace WP_PowerSuite\Core;

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

/**
 * Loads and exposes CI/runtime performance budget thresholds.
 */
final class PerformanceBudgetConfig {

	private const CONFIG_FILE = 'config/performance-budgets.json';

	/** @var array<string, mixed>|null */
	private static ?array $config = null;

	/** @var bool|null Request-level cache for Settings → Performance Monitor toggle. */
	private static ?bool $monitor_enabled = null;

	/**
	 * @return array<string, mixed>
	 */
	public static function all(): array {
		if ( self::$config !== null ) {
			return self::$config;
		}

		$defaults = [
			'max_hooks_per_module'              => 40,
			'max_static_hooks_per_module'       => 55,
			'max_init_ms_per_module'            => 100.0,
			'max_total_modules'                 => 200,
			'require_boot_tier_on_all_modules'  => true,
			'require_manifest_module_count_min' => 140,
		];

		$path = self::getConfigPath();
		if ( ! is_readable( $path ) ) {
			self::$config = $defaults;
			return self::$config;
		}

		try {
			/** @var array<string, mixed> $parsed */
			$parsed = json_decode( (string) file_get_contents( $path ), true, 512, JSON_THROW_ON_ERROR );
			self::$config = array_merge( $defaults, $parsed );
		} catch ( \JsonException $e ) {
			self::$config = $defaults;
		}

		return self::$config;
	}

	/**
	 * Runtime hook budget enforced during module init ({@see HookTracker}).
	 */
	public static function maxHooksPerModule(): int {
		return max( 1, (int) ( self::all()['max_hooks_per_module'] ?? 40 ) );
	}

	/**
	 * CI static scan budget for add_action/add_filter calls in module.php.
	 */
	public static function maxStaticHooksPerModule(): int {
		$cfg = self::all();
		return max( 1, (int) ( $cfg['max_static_hooks_per_module'] ?? $cfg['max_hooks_per_module'] ?? 40 ) );
	}

	public static function maxInitMsPerModule(): float {
		return max( 1.0, (float) ( self::all()['max_init_ms_per_module'] ?? 100.0 ) );
	}

	/**
	 * Whether the Performance Monitor feature is present in this install.
	 *
	 * Customer release zips omit the monitor. Developers activate the companion
	 * plugin `wp-powersuite-dev-monitor`, which loads {@see PerformanceMonitor}
	 * and filters this to true.
	 */
	public static function isFeatureAvailable(): bool {
		if ( class_exists( PerformanceMonitor::class, false ) ) {
			return true;
		}

		$path = self::getMonitorClassPath();
		if ( $path !== '' && is_readable( $path ) ) {
			return true;
		}

		/**
		 * Allow a developer companion plugin to ship the Performance Monitor.
		 *
		 * @param bool $available Whether the feature is available.
		 */
		return (bool) apply_filters( 'wp_powersuite_performance_monitor_available', false );
	}

	/**
	 * Whether Performance Monitor tracking is enabled in plugin settings.
	 */
	public static function isPerformanceMonitorEnabled(): bool {
		if ( self::$monitor_enabled !== null ) {
			return self::$monitor_enabled;
		}

		if ( ! self::isFeatureAvailable() ) {
			self::$monitor_enabled = false;
			return false;
		}

		if ( ! class_exists( OptionStore::class, false ) ) {
			self::$monitor_enabled = false;
			return false;
		}

		$enabled = OptionStore::getInstance()->isPerformanceMonitorEnabled();

		/**
		 * @param bool $enabled Default from Settings → Enable Performance Monitor.
		 */
		self::$monitor_enabled = (bool) apply_filters( 'wp_powersuite_performance_monitor_enabled', $enabled );

		return self::$monitor_enabled;
	}

	/**
	 * Whether init time and memory metrics are collected (Performance Monitor enabled).
	 */
	public static function isDetailedMetricsEnabled(): bool {
		return self::isPerformanceMonitorEnabled();
	}

	/**
	 * Whether hook deltas are sampled during module init.
	 *
	 * Requires Performance Monitor to be enabled in Settings.
	 */
	public static function shouldTrackModuleHooks(): bool {
		if ( ! self::isPerformanceMonitorEnabled() ) {
			return false;
		}

		/**
		 * @param bool $track Default true when monitor is enabled.
		 */
		return (bool) apply_filters( 'wp_powersuite_track_module_hooks', true );
	}

	/**
	 * Admin page slug for the Performance dashboard.
	 */
	public const PERFORMANCE_ADMIN_PAGE = 'powersuite-performance';

	/**
	 * Whether the current request is loading the Performance admin screen.
	 */
	public static function isPerformanceAdminRequest(): bool {
		if ( ! self::isPerformanceMonitorEnabled() ) {
			return false;
		}

		if ( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
			return false;
		}

		if ( ! isset( $_GET['page'] ) ) {
			return false;
		}

		return sanitize_key( wp_unslash( $_GET['page'] ) ) === self::PERFORMANCE_ADMIN_PAGE;
	}

	/**
	 * Whether to register the module fatal-error shutdown handler.
	 *
	 * Active when Performance Monitor is enabled in Settings.
	 */
	public static function shouldRegisterFatalErrorHandler(): bool {
		if ( ! self::isPerformanceMonitorEnabled() ) {
			return false;
		}

		/**
		 * @param bool $register Default true when monitor is enabled.
		 */
		return (bool) apply_filters( 'wp_powersuite_register_fatal_error_handler', true );
	}

	private static function getConfigPath(): string {
		if ( defined( 'WP_POWERSUITE_PLUGIN_DIR' ) ) {
			return WP_POWERSUITE_PLUGIN_DIR . self::CONFIG_FILE;
		}

		return dirname( __DIR__, 2 ) . DIRECTORY_SEPARATOR . str_replace( '/', DIRECTORY_SEPARATOR, self::CONFIG_FILE );
	}

	private static function getMonitorClassPath(): string {
		$relative = 'src' . DIRECTORY_SEPARATOR . 'Core' . DIRECTORY_SEPARATOR . 'PerformanceMonitor.php';

		if ( defined( 'WP_POWERSUITE_PLUGIN_DIR' ) ) {
			return WP_POWERSUITE_PLUGIN_DIR . $relative;
		}

		return dirname( __DIR__, 2 ) . DIRECTORY_SEPARATOR . $relative;
	}
}
