<?php
/**
 * `wp powersuite backup` commands.
 *
 * @package WP_PowerSuite\CLI
 * @since 1.0.7
 */

namespace WP_PowerSuite\CLI;

use WP_PowerSuite\CLI\Support\Cli;

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

/**
 * Create and list local backups.
 *
 * Restore is intentionally NOT exposed here — it is destructive and is only
 * available through the guarded admin workflow.
 *
 * @since 1.0.7
 */
final class BackupCommand {

	/**
	 * Create a backup synchronously.
	 *
	 * Uses the same pipeline as the scheduled (cron) backup, running to
	 * completion in the current process. On very large sites the module may hand
	 * the remainder off to WP-Cron; the command reports when that happens.
	 *
	 * ## OPTIONS
	 *
	 * [--type=<type>]
	 * : What to back up.
	 * ---
	 * default: full
	 * options:
	 *   - full
	 *   - database
	 *   - files
	 * ---
	 *
	 * [--label=<label>]
	 * : A human-readable label for the backup.
	 *
	 * ## EXAMPLES
	 *
	 *     $ wp powersuite backup create
	 *     $ wp powersuite backup create --type=database --label="pre-deploy"
	 *
	 * @when after_wp_load
	 *
	 * @param array<int, string>   $args       Positional arguments (unused).
	 * @param array<string, mixed> $assoc_args Associative arguments.
	 * @return void
	 */
	public function create( array $args, array $assoc_args ): void {
		$this->ensureModuleReady();

		$type  = (string) \WP_CLI\Utils\get_flag_value( $assoc_args, 'type', 'full' );
		$label = (string) \WP_CLI\Utils\get_flag_value( $assoc_args, 'label', sprintf( 'CLI %s', gmdate( 'Y-m-d H:i:s' ) ) );

		if ( ! in_array( $type, [ 'full', 'database', 'files' ], true ) ) {
			\WP_CLI::error( __( 'Invalid --type. Use full, database, or files.', 'wp-powersuite' ) );
		}

		/* translators: %s: string value. */
		\WP_CLI::log( sprintf( __( 'Starting %s backup...', 'wp-powersuite' ), $type ) );

		$service = new \BackupRestore\Includes\BackupService();
		$result  = $service->run_scheduled_backup( $type, $label );

		if ( empty( $result['success'] ) ) {
			\WP_CLI::error( (string) ( $result['message'] ?? __( 'Backup failed.', 'wp-powersuite' ) ) );
		}

		if ( ! empty( $result['cron_continued'] ) ) {
			\WP_CLI::warning( __( 'Backup exceeded the wall-time budget and will continue via WP-Cron. Check `wp powersuite backup list` shortly.', 'wp-powersuite' ) );
			return;
		}

		if ( empty( $result['done'] ) ) {
			\WP_CLI::warning( __( 'Backup did not finish in this run. Check `wp powersuite backup list`.', 'wp-powersuite' ) );
			return;
		}

		$backup_id = (string) ( $result['backup_id'] ?? '' );
		$size      = 0;
		if ( isset( $result['backup_details']['total_size'] ) ) {
			$size = (int) $result['backup_details']['total_size'];
		}

		\WP_CLI::success(
			sprintf(
				/* translators: 1: backup id, 2: human-readable size */
				__( 'Backup created: %1$s (%2$s).', 'wp-powersuite' ),
				$backup_id,
				size_format( $size )
			)
		);
	}

	/**
	 * List existing backups.
	 *
	 * ## OPTIONS
	 *
	 * [--fields=<fields>]
	 * : Comma-separated list of fields to display.
	 * ---
	 * default: id,label,type,created,components
	 * ---
	 *
	 * [--format=<format>]
	 * : Render output in a particular format.
	 * ---
	 * default: table
	 * options:
	 *   - table
	 *   - csv
	 *   - json
	 *   - yaml
	 *   - count
	 * ---
	 *
	 * ## EXAMPLES
	 *
	 *     $ wp powersuite backup list
	 *
	 * @subcommand list
	 * @when after_wp_load
	 *
	 * @param array<int, string>   $args       Positional arguments (unused).
	 * @param array<string, mixed> $assoc_args Associative arguments.
	 * @return void
	 */
	public function list_( array $args, array $assoc_args ): void {
		$this->ensureModuleReady();

		$history = \BackupRestore\Includes\BackupService::get_history();

		$rows = [];
		foreach ( $history as $id => $entry ) {
			if ( ! is_array( $entry ) ) {
				continue;
			}
			$components = isset( $entry['components'] ) && is_array( $entry['components'] )
				? implode( ', ', array_keys( $entry['components'] ) )
				: '';
			$rows[] = [
				'id'         => (string) ( $entry['id'] ?? $id ),
				'label'      => (string) ( $entry['label'] ?? '' ),
				'type'       => (string) ( $entry['type'] ?? '' ),
				'created'    => isset( $entry['created'] ) ? gmdate( 'Y-m-d H:i:s', (int) $entry['created'] ) : '',
				'components' => $components,
			];
		}

		usort( $rows, static fn( $a, $b ) => strcmp( $b['created'], $a['created'] ) );

		$fields    = [ 'id', 'label', 'type', 'created', 'components' ];
		$formatter = new \WP_CLI\Formatter( $assoc_args, $fields );
		$formatter->display_items( $rows );
	}

	/**
	 * Ensure the Backup & Restore module is enabled, licensed, and loaded.
	 *
	 * @return void
	 */
	private function ensureModuleReady(): void {
		if ( ! Cli::isEnabled( 'backup-restore' ) ) {
			\WP_CLI::error( __( 'The Backup & Restore module is not enabled. Enable it first: wp powersuite module enable backup-restore', 'wp-powersuite' ) );
		}

		if ( function_exists( 'wp_powersuite_is_license_valid' ) && ! wp_powersuite_is_license_valid() ) {
			\WP_CLI::error( __( 'Backup & Restore requires a valid license.', 'wp-powersuite' ) );
		}

		if ( ! class_exists( '\\BackupRestore\\Includes\\BackupService' ) ) {
			$dir = WP_POWERSUITE_MODULES_DIR . 'backup-restore' . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR;
			foreach ( [ 'PrivateStorageResolver.php', 'BackupService.php' ] as $file ) {
				$path = $dir . $file;
				if ( is_readable( $path ) ) {
					require_once $path;
				}
			}
		}

		if ( ! class_exists( '\\BackupRestore\\Includes\\BackupService' ) ) {
			\WP_CLI::error( __( 'Unable to load the Backup & Restore engine.', 'wp-powersuite' ) );
		}
	}
}

