<?php
/**
 * Speed module.
 *
 * @package MonitorCat\Modules\Speed
 */

declare(strict_types=1);

namespace MonitorCat\Modules\Speed;

defined( 'ABSPATH' ) || exit;

use MonitorCat\Module\AbstractModule;
use MonitorCat\Modules\Speed\Optimizer\EmbedOptimizer;
use MonitorCat\Modules\Speed\Optimizer\FrontendCleanupOptimizer;
use MonitorCat\Modules\Speed\Optimizer\HeartbeatOptimizer;
use MonitorCat\Modules\Speed\Optimizer\LazyMediaOptimizer;
use MonitorCat\Modules\Speed\Optimizer\PreloadOptimizer;
use MonitorCat\Modules\Speed\Optimizer\QueryStringOptimizer;
use MonitorCat\Modules\Speed\Optimizer\ScriptOptimizer;
use MonitorCat\Modules\Speed\Optimizer\WPHeadOptimizer;

/**
 * Speed optimization module — automatic performance improvements.
 */
final class SpeedModule extends AbstractModule {

	/**
	 * Transient key for cached scan results.
	 *
	 * @var string
	 */
	private const TRANSIENT_KEY = 'monitorcat_speed_scan_results';

	/**
	 * Get the module slug.
	 *
	 * @return string
	 */
	public function slug(): string {
		return 'speed';
	}

	/**
	 * Get the module name.
	 *
	 * @return string
	 */
	public function name(): string {
		return __( 'Speed', 'monitor-cat' );
	}

	/**
	 * Get the FontAwesome icon class.
	 *
	 * @return string
	 */
	public function icon(): string {
		return 'fa-gauge-high';
	}

	/**
	 * Get the module description.
	 *
	 * @return string
	 */
	public function description(): string {
		return __( 'Automatic speed optimizations and performance improvements', 'monitor-cat' );
	}

	/**
	 * Boot the module — register admin hooks and frontend optimizers.
	 */
	public function boot(): void {
		parent::boot();

		// Frontend optimizers — run on every page load, not just admin.
		( new WPHeadOptimizer( $this->settings ) )->boot();
		( new ScriptOptimizer( $this->settings ) )->boot();
		( new PreloadOptimizer( $this->settings ) )->boot();
		( new LazyMediaOptimizer( $this->settings ) )->boot();
		( new HeartbeatOptimizer( $this->settings ) )->boot();
		( new QueryStringOptimizer( $this->settings ) )->boot();
		( new EmbedOptimizer( $this->settings ) )->boot();
		( new FrontendCleanupOptimizer( $this->settings ) )->boot();

		// Schedule automatic database cleanup if enabled.
		if ( $this->settings->get( 'speed.db_auto_cleanup', false ) ) {
			if ( ! wp_next_scheduled( 'monitorcat_db_auto_cleanup' ) ) {
				wp_schedule_event( time(), 'weekly', 'monitorcat_db_auto_cleanup' );
			}
			add_action( 'monitorcat_db_auto_cleanup', array( $this, 'run_auto_cleanup' ) );
		}
	}

	/**
	 * Enqueue module assets with i18n strings for JavaScript.
	 *
	 * @param string $hook_suffix The current admin page hook suffix.
	 */
	public function enqueue_assets( string $hook_suffix ): void {
		parent::enqueue_assets( $hook_suffix );

		if ( ! $this->is_own_page( $hook_suffix ) ) {
			return;
		}

		wp_localize_script(
			'monitorcat-module-speed-js',
			'MonitorCatSpeedI18n',
			array(
				// Status labels.
				'statusGood'                => __( 'Passing', 'monitor-cat' ),
				'statusWarning'             => __( 'Needs Work', 'monitor-cat' ),
				'statusCritical'            => __( 'Fix This', 'monitor-cat' ),
				// Score messages.
				'scoreExcellent'            => __( 'Excellent! Your site is well-optimized for speed. This is the Monitor.Cat Speed Score, not a Lighthouse score.', 'monitor-cat' ),
				'scoreGreat'                => __( 'Great performance! A few tweaks below can push you even higher.', 'monitor-cat' ),
				'scoreGood'                 => __( 'Good foundation, but there are important speed improvements to make.', 'monitor-cat' ),
				'scoreNeedsAttention'       => __( 'Your site needs attention. Follow the recommendations below to speed things up.', 'monitor-cat' ),
				'scoreSignificant'          => __( 'Significant improvements needed. Start with the items marked "Fix This" below.', 'monitor-cat' ),
				// Hero badges.
				'badgePassing'              => __( 'Passing', 'monitor-cat' ),
				'badgeNeedsWork'            => __( 'Needs Work', 'monitor-cat' ),
				'badgeFixThis'              => __( 'Fix This', 'monitor-cat' ),
				// Tab labels.
				'tabPerformance'            => __( 'Performance', 'monitor-cat' ),
				'tabInfrastructure'         => __( 'Infrastructure', 'monitor-cat' ),
				'tabDatabase'               => __( 'Database', 'monitor-cat' ),
				// Category labels.
				'labelPageWeight'           => __( 'Page Weight', 'monitor-cat' ),
				'labelImageOptimization'    => __( 'Image Optimization', 'monitor-cat' ),
				'labelCssJavascript'        => __( 'CSS & JavaScript', 'monitor-cat' ),
				'labelCaching'              => __( 'Caching', 'monitor-cat' ),
				'labelCompression'          => __( 'Compression', 'monitor-cat' ),
				'labelResponseTime'         => __( 'Response Time', 'monitor-cat' ),
				'labelDatabaseHealth'       => __( 'Database Health', 'monitor-cat' ),
				// DB cleanup.
				'labelPostRevisions'        => __( 'Post Revisions', 'monitor-cat' ),
				'labelAutoDrafts'           => __( 'Auto-Drafts', 'monitor-cat' ),
				'labelTrashedPosts'         => __( 'Trashed Posts', 'monitor-cat' ),
				'labelSpamComments'         => __( 'Spam Comments', 'monitor-cat' ),
				'labelTrashedComments'      => __( 'Trashed Comments', 'monitor-cat' ),
				'labelExpiredTransients'    => __( 'Expired Transients', 'monitor-cat' ),
				'labelOptimizeTables'       => __( 'Optimize Tables', 'monitor-cat' ),
				// Confirm messages.
				'confirmRevisions'          => __( 'Delete all post revisions? This cannot be undone.', 'monitor-cat' ),
				'confirmAutoDrafts'         => __( 'Delete all auto-drafts? This cannot be undone.', 'monitor-cat' ),
				'confirmTrashedPosts'       => __( 'Permanently delete all trashed posts? This cannot be undone.', 'monitor-cat' ),
				'confirmSpamComments'       => __( 'Delete all spam comments? This cannot be undone.', 'monitor-cat' ),
				'confirmTrashedComments'    => __( 'Permanently delete all trashed comments? This cannot be undone.', 'monitor-cat' ),
				'confirmExpiredTransients'  => __( 'Clean up all expired transients?', 'monitor-cat' ),
				'confirmOptimizeTables'     => __( 'Optimize all WordPress database tables? This is safe but may take a moment.', 'monitor-cat' ),
				'confirmCleanAll'           => __( 'Run all database cleanups? This will remove revisions, drafts, trash, spam, and expired transients. This cannot be undone.', 'monitor-cat' ),
				// Notifications.
				'scanComplete'              => __( 'Speed scan complete!', 'monitor-cat' ),
				'scanFailed'                => __( 'Scan failed. Please try again.', 'monitor-cat' ),
				'failedLoadDbStats'         => __( 'Failed to load database stats.', 'monitor-cat' ),
				'cleanupFailed'             => __( 'Cleanup failed.', 'monitor-cat' ),
				'failedSaveSetting'         => __( 'Failed to save setting.', 'monitor-cat' ),
				'noDataAvailable'           => __( 'No data available for this category.', 'monitor-cat' ),
				'details'                   => __( 'Details', 'monitor-cat' ),
				'optimize'                  => __( 'Optimize', 'monitor-cat' ),
				'clean'                     => __( 'Clean', 'monitor-cat' ),
				'scanning'                  => __( 'Scanning...', 'monitor-cat' ),
				'cleaning'                  => __( 'Cleaning...', 'monitor-cat' ),
				/* translators: %1$d: number of passing checks, %2$d: total checks */
				'checksPassingOf'           => __( '%1$d of %2$d checks passing', 'monitor-cat' ),
				/* translators: %d: average score */
				'avgScore'                  => __( '%d/100 avg', 'monitor-cat' ),
				/* translators: %1$d: number of active optimizations, %2$d: total optimizations */
				'activeOf'                  => __( '%1$d of %2$d active', 'monitor-cat' ),
				/* translators: %s: optimization name */
				'enabledNotice'             => __( '%s enabled. Takes effect on next page load.', 'monitor-cat' ),
				/* translators: %s: optimization name */
				'disabledNotice'            => __( '%s disabled. Takes effect on next page load.', 'monitor-cat' ),
				/* translators: %d: number of items cleaned */
				'cleanedItems'              => __( 'Cleaned %d items.', 'monitor-cat' ),
				/* translators: %d: number of items cleaned */
				'allCleanupsComplete'       => __( 'All cleanups complete! Cleaned %d items and optimized tables.', 'monitor-cat' ),
				// Fix tips.
				'tipHtmlSize'               => __( 'Reduce HTML size by removing unnecessary inline content and using external CSS/JS files.', 'monitor-cat' ),
				'tipInlineScripts'          => __( 'Move inline scripts to external files and use defer loading. Enable Script Defer optimization.', 'monitor-cat' ),
				'tipInlineStyles'           => __( 'Move inline styles to external CSS files to improve caching and reduce page weight.', 'monitor-cat' ),
				'tipResourceHints'          => __( 'Enable Monitor.Cat Resource Hints optimization to automatically add preconnect for external services.', 'monitor-cat' ),
				'tipTotalImages'            => __( 'Consider reducing the number of images or using CSS sprites for decorative elements.', 'monitor-cat' ),
				'tipWebpCoverage'           => __( 'Convert images to WebP format. Install an image optimization plugin like Imagify or ShortPixel.', 'monitor-cat' ),
				'tipLazyLoading'            => __( 'Enable Monitor.Cat Lazy Media optimization for automatic iframe lazy loading and async image decoding.', 'monitor-cat' ),
				'tipOptimizationPlugin'     => __( 'Install an image optimization plugin (Imagify, ShortPixel, EWWW, or Smush) for automatic compression.', 'monitor-cat' ),
				'tipCssFiles'               => __( 'Reduce the number of CSS files by combining stylesheets or removing unused plugins.', 'monitor-cat' ),
				'tipJsFiles'                => __( 'Reduce the number of JavaScript files. Deactivate unused plugins to eliminate unnecessary scripts.', 'monitor-cat' ),
				'tipRenderBlocking'         => __( 'Enable Monitor.Cat Script Defer to automatically add defer attributes to render-blocking scripts.', 'monitor-cat' ),
				'tipJquery'                 => __( 'Consider plugins that don\'t depend on jQuery. Enable jQuery Migrate removal for a lighter footprint.', 'monitor-cat' ),
				'tipTotalAssets'            => __( 'Reduce total assets by deactivating unused plugins and combining where possible.', 'monitor-cat' ),
				'tipObjectCache'            => __( 'Install Redis or Memcached and a persistent object cache plugin for faster database queries.', 'monitor-cat' ),
				'tipPageCache'              => __( 'Install a caching plugin (WP Super Cache, W3 Total Cache, WP Rocket, or LiteSpeed Cache).', 'monitor-cat' ),
				'tipBrowserCache'           => __( 'Add Cache-Control headers via your web server config or .htaccess for static assets.', 'monitor-cat' ),
				'tipHttpCompression'        => __( 'Enable GZIP or Brotli compression on your web server for significantly smaller transfers.', 'monitor-cat' ),
				'tipPhpCompression'         => __( 'Enable zlib.output_compression in php.ini for automatic PHP output compression.', 'monitor-cat' ),
				'tipServerCompression'      => __( 'Add mod_deflate or mod_gzip directives to your .htaccess file for Apache servers.', 'monitor-cat' ),
				'tipTtfb'                   => __( 'Improve Time To First Byte by enabling object cache, page cache, and using a CDN.', 'monitor-cat' ),
				'tipCdn'                    => __( 'Use a CDN (Cloudflare, Fastly, AWS CloudFront) for faster global content delivery.', 'monitor-cat' ),
				'tipPostRevisions'          => __( 'Clean up post revisions using the Database Cleanup tool below.', 'monitor-cat' ),
				'tipAutoDrafts'             => __( 'Remove auto-drafts using the Database Cleanup tool below.', 'monitor-cat' ),
				'tipTrashedPosts'           => __( 'Empty the trash to free up database space.', 'monitor-cat' ),
				'tipSpamComments'           => __( 'Delete spam comments to keep your database lean.', 'monitor-cat' ),
				'tipTrashedComments'        => __( 'Empty trashed comments from the database.', 'monitor-cat' ),
				'tipExpiredTransients'      => __( 'Clean expired transients to remove stale cached data.', 'monitor-cat' ),
				'tipAutoloadedOptions'      => __( 'Review autoloaded options. Plugins with large autoloaded data slow down every page load.', 'monitor-cat' ),
				// Fix action labels.
				'actionEnableHeadCleanup'   => __( 'Enable Head Cleanup', 'monitor-cat' ),
				'actionEnableScriptDefer'   => __( 'Enable Script Defer', 'monitor-cat' ),
				'actionEnableResourceHints' => __( 'Enable Resource Hints', 'monitor-cat' ),
				'actionEnableLazyMedia'     => __( 'Enable Lazy Media', 'monitor-cat' ),
				'actionSettings'            => __( 'Settings', 'monitor-cat' ),
				'actionCleanRevisions'      => __( 'Clean Revisions', 'monitor-cat' ),
				'actionCleanDrafts'         => __( 'Clean Drafts', 'monitor-cat' ),
				'actionCleanTrash'          => __( 'Clean Trash', 'monitor-cat' ),
				'actionCleanSpam'           => __( 'Clean Spam', 'monitor-cat' ),
				'actionCleanTransients'     => __( 'Clean Transients', 'monitor-cat' ),
			)
		);
	}

	/**
	 * Register REST API routes for the Speed module.
	 */
	public function register_routes(): void {
		$controller = new RestController( $this->settings );
		$controller->register();
	}

	/**
	 * Run automatic database cleanup via WP-Cron.
	 */
	public function run_auto_cleanup(): void {
		$optimizer = new \MonitorCat\Modules\Speed\Optimizer\DatabaseOptimizer();

		if ( $this->settings->get( 'speed.db_cleanup_revisions', true ) ) {
			$optimizer->clean_revisions();
		}

		if ( $this->settings->get( 'speed.db_cleanup_transients', true ) ) {
			$optimizer->clean_expired_transients();
		}

		if ( $this->settings->get( 'speed.db_cleanup_spam', true ) ) {
			$optimizer->clean_spam_comments();
		}

		$optimizer->clean_auto_drafts();
		$optimizer->clean_trashed_posts();
		$optimizer->clean_trashed_comments();
	}

	/**
	 * Get dashboard summary data.
	 *
	 * Returns cached scan results if available, otherwise indicates ready state.
	 *
	 * @return array<string, mixed>
	 */
	public function get_dashboard_summary(): array {
		$cached = get_transient( self::TRANSIENT_KEY );

		if ( false === $cached || ! is_array( $cached ) ) {
			return array(
				'score'  => null,
				'status' => 'ready',
			);
		}

		return array(
			'score'          => $cached['overall_score'] ?? null,
			'status'         => $cached['overall_status'] ?? 'ready',
			'timestamp'      => $cached['timestamp'] ?? null,
			'analyzer_count' => isset( $cached['analyzers'] ) ? count( $cached['analyzers'] ) : 0,
		);
	}
}
