<?php
/**
 * `wp blaminhor cache ...` — Cache & Performance commands (scope: purge + read-only stats).
 *
 * Configuring the dozens of cache toggles via CLI is impractical — the
 * admin UI walks the user through the dependencies. The CLI exposes the
 * three operations that scripts/CI typically need: purge, status, stats.
 *
 * @package BlaminhorEssentials
 */

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

if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
	return;
}

class Blaminhor_Essentials_CLI_Cache extends Blaminhor_Essentials_CLI_Module {

	/**
	 * @var string
	 */
	protected $module_id = 'cache';

	/**
	 * Purge the page cache (or a single URL).
	 *
	 * ## OPTIONS
	 *
	 * [--page=<url>]
	 * : Purge a single URL. Default: purge everything.
	 *
	 * ## EXAMPLES
	 *
	 *     $ wp blaminhor cache purge
	 *     $ wp blaminhor cache purge --page=https://example.com/about/
	 *
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args (unused).
	 * @param array $assoc_args Associative args.
	 */
	public function purge( $args, $assoc_args ) {
		$this->ensure_capabilities();

		if ( isset( $assoc_args['page'] ) && '' !== (string) $assoc_args['page'] ) {
			$url = esc_url_raw( (string) $assoc_args['page'] );
			do_action( 'blaminhor_essentials_cache_purge_url', $url );
			blaminhor_essentials_log( sprintf( 'Cache purge for "%s" via WP-CLI.', $url ), 'info', 'cli', array( 'event' => 'cache_purge_url' ) );
			WP_CLI::success( sprintf(
				/* translators: %s: URL */
				__( 'Purge request dispatched for %s.', 'blaminhor-essentials' ),
				$url
			) );
			return;
		}

		do_action( 'blaminhor_essentials_cache_purge_request' );
		blaminhor_essentials_log( 'Full cache purge via WP-CLI.', 'info', 'cli', array( 'event' => 'cache_purge_all' ) );
		WP_CLI::success( __( 'Full cache purge dispatched.', 'blaminhor-essentials' ) );
	}

	/**
	 * Print cache infrastructure status (drop-in installed, cache dir size…).
	 *
	 * ## OPTIONS
	 *
	 * [--format=<format>]
	 * : Render format. Default: table.
	 *
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args (unused).
	 * @param array $assoc_args Associative args.
	 */
	public function status( $args, $assoc_args ) {
		$dropin_path     = WP_CONTENT_DIR . '/advanced-cache.php';
		$dropin_present  = file_exists( $dropin_path );
		$dropin_is_ours  = false;
		if ( $dropin_present ) {
			$head = @file_get_contents( $dropin_path, false, null, 0, 2048 );
			$dropin_is_ours = $head && false !== strpos( $head, 'BLAMINHOR_ESSENTIALS_DROPIN' );
		}

		$cache_dir   = WP_CONTENT_DIR . '/uploads/blaminhor-essentials/cache/pages';
		$page_count  = 0;
		$cache_bytes = 0;
		if ( is_dir( $cache_dir ) ) {
			try {
				$it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $cache_dir, RecursiveDirectoryIterator::SKIP_DOTS ) );
				foreach ( $it as $entry ) {
					if ( $entry->isFile() ) {
						$ext = strtolower( pathinfo( (string) $entry->getPathname(), PATHINFO_EXTENSION ) );
						if ( 'html' === $ext ) {
							$page_count++;
						}
						$cache_bytes += (int) $entry->getSize();
					}
				}
			} catch ( Exception $e ) {
				// fall through with whatever we collected
			}
		}

		$module   = $this->get_module_instance();
		$settings = (array) $module->get_effective_settings();

		$rows = array(
			array( 'key' => 'dropin_installed',      'value' => $dropin_present ? 'true' : 'false' ),
			array( 'key' => 'dropin_is_blaminhor',   'value' => $dropin_is_ours ? 'true' : 'false' ),
			array( 'key' => 'cache_dir',             'value' => $cache_dir ),
			array( 'key' => 'cached_pages',          'value' => (string) $page_count ),
			array( 'key' => 'cache_dir_size',        'value' => blaminhor_essentials_format_size( $cache_bytes ) ),
			array( 'key' => 'page_cache_enabled',    'value' => ! empty( $settings['page_cache_enabled'] ) ? 'true' : 'false' ),
		);
		$this->format_for_output( $rows, $assoc_args, array( 'key', 'value' ) );
	}

	/**
	 * Print a subset of the module's settings (read-only).
	 *
	 * ## OPTIONS
	 *
	 * [--format=<format>]
	 * : Render format. Default: table.
	 *
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args (unused).
	 * @param array $assoc_args Associative args.
	 */
	public function get( $args, $assoc_args ) {
		$module   = $this->get_module_instance();
		$settings = (array) $module->get_effective_settings();
		$exposed  = array(
			'page_cache_enabled',
			'cache_ttl',
			'minify_html',
			'minify_css',
			'minify_js',
			'defer_js',
			'lazy_load_images',
			'critical_css_enabled',
			'rucss_enabled',
		);

		$rows = array();
		foreach ( $exposed as $key ) {
			if ( ! array_key_exists( $key, $settings ) ) {
				continue;
			}
			$v = $settings[ $key ];
			if ( is_bool( $v ) ) {
				$v = $v ? 'true' : 'false';
			}
			$rows[] = array( 'key' => $key, 'value' => (string) $v );
		}
		$this->format_for_output( $rows, $assoc_args, array( 'key', 'value' ) );
	}
}
