<?php
/**
 * Shared support for module-contributed WP-CLI commands.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChanges\WpCli;

/** Provides permission, confirmation, and output helpers. */
abstract class ModuleCommand {
	private ?CommandFormatter $formatter = null;

	/**
	 * Returns the current CLI actor or exits with a stable error.
	 */
	protected function actorId(): int {
		$actor_id = get_current_user_id();

		if ( $actor_id <= 0 || ! get_userdata( $actor_id ) instanceof \WP_User ) {
			\WP_CLI::error( 'A valid WordPress user is required. Run the command with --user=<login>.' );
		}

		return $actor_id;
	}

	/** Requires an explicit WordPress actor with one capability. */
	protected function requireCapability( string $capability ): int {
		$actor_id = $this->actorId();

		if ( ! user_can( $actor_id, $capability ) ) {
			\WP_CLI::error( 'The current WordPress user does not have the required JJ\'s Post Scheduler permission.' );
		}

		return $actor_id;
	}

	/**
	 * Requires the mutating command confirmation flag.
	 *
	 * @param array<string,mixed> $assoc_args Command options.
	 */
	protected function requireYes( array $assoc_args, string $message ): void {
		if ( ! isset( $assoc_args['yes'] ) ) {
			\WP_CLI::error( $message . ' Re-run with --yes to confirm.' );
		}
	}

	/**
	 * Prints associative output in the requested format.
	 *
	 * @param array<string,mixed> $data Output data.
	 * @param array<string,mixed> $assoc_args Command options.
	 */
	protected function formatAssoc( array $data, array $assoc_args ): void {
		$this->formatter()->formatAssoc( $data, $assoc_args );
	}

	/**
	 * Prints row output in the requested format.
	 *
	 * @param array<int,array<string,mixed>> $rows Output rows.
	 * @param string[]                       $fields Output fields.
	 * @param array<string,mixed>            $assoc_args Command options.
	 */
	protected function formatRows( array $rows, array $fields, array $assoc_args ): void {
		$this->formatter()->formatRows( $rows, $fields, $assoc_args );
	}

	/**
	 * Returns the shared formatter.
	 */
	private function formatter(): CommandFormatter {
		if ( null === $this->formatter ) {
			$this->formatter = new CommandFormatter();
		}

		return $this->formatter;
	}
}
