<?php
/**
 * WP-CLI commands for AI Alt Text Generator
 *
 * @package AIAltTextGenerator
 * @since 1.2.0
 */

namespace AIAltTextGenerator;

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

/**
 * Manage AI alt text generation and scans.
 *
 * @since 1.2.0
 */
class WP_CLI_Command {

	/**
	 * Generate AI alt text for images.
	 *
	 * ## OPTIONS
	 *
	 * [--ids=<ids>]
	 * : Comma-separated attachment IDs to process.
	 *
	 * [--all]
	 * : Process all images without alt text.
	 *
	 * [--overwrite]
	 * : Overwrite existing alt text.
	 *
	 * [--queue]
	 * : Add images to background queue instead of processing immediately.
	 *
	 * ## EXAMPLES
	 *
	 *     wp alttext generate --ids=1,2,3
	 *     wp alttext generate --all
	 *     wp alttext generate --all --queue --overwrite
	 *
	 * @param array<int, string> $args       Positional args.
	 * @param array<string, string> $assoc_args Associative args.
	 */
	public function generate( array $args, array $assoc_args ): void {
		self::assertModuleReady();

		$settings = Settings::get();
		$ids      = self::resolveAttachmentIds( $assoc_args, $settings );

		if ( $ids === [] ) {
			\WP_CLI::warning( __( 'No images to process. Use --ids=1,2,3 or --all.', 'wppowersuite-lite' ) );
			return;
		}

		$force = ! empty( $assoc_args['overwrite'] );

		if ( ! empty( $assoc_args['queue'] ) || ( ! empty( $settings['queue_enabled'] ) && empty( $assoc_args['ids'] ) ) ) {
			$added = Queue::enqueue( $ids, $force );
			\WP_CLI::success( sprintf(
				/* translators: %d: count */
				__( '%d images added to background queue.', 'wppowersuite-lite' ),
				$added
			) );
			return;
		}

		$progress = \WP_CLI\Utils\make_progress_bar( __( 'Generating alt text', 'wppowersuite-lite' ), count( $ids ) );
		$ok       = 0;
		$fail     = 0;

		foreach ( $ids as $attachment_id ) {
			$result = GenerationService::generateForAttachment( $attachment_id, $force );
			if ( $result['status'] === 'success' ) {
				++$ok;
			} else {
				\WP_CLI::debug( ( $result['message'] ?? 'Failed' ) . " (ID: $attachment_id)" );
				++$fail;
			}
			$progress->tick();
		}

		$progress->finish();
		Scanner::invalidateCache();

		\WP_CLI::success( sprintf(
			/* translators: 1: number, 2: number. */
			__( 'Processed %1$d images successfully, %2$d failed or skipped.', 'wppowersuite-lite' ),
			$ok,
			$fail
		) );
	}

	/**
	 * Show media library scan summary.
	 *
	 * ## OPTIONS
	 *
	 * [--refresh]
	 * : Refresh cached scan results.
	 */
	public function scan( array $args, array $assoc_args ): void {
		self::assertModuleReady();
		$summary = Scanner::getSummary( ! empty( $assoc_args['refresh'] ) );
		\WP_CLI\Utils\format_items( 'table', [ $summary ], array_keys( $summary ) );
	}

	/**
	 * Show combined module status.
	 */
	public function status( array $args, array $assoc_args ): void {
		self::assertModuleReady();

		$data = [
			[
				'key'   => 'library',
				'value' => wp_json_encode( Scanner::getSummary() ),
			],
			[
				'key'   => 'usage',
				'value' => wp_json_encode( Usage::getSummary() ),
			],
			[
				'key'   => 'queue',
				'value' => wp_json_encode( Queue::getStatus() ),
			],
			[
				'key'   => 'content_scan',
				'value' => wp_json_encode( ContentScanner::getSummary() ),
			],
			[
				'key'   => 'settings',
				'value' => wp_json_encode( Settings::getPublic() ),
			],
		];

		\WP_CLI\Utils\format_items( 'table', $data, [ 'key', 'value' ] );
	}

	/**
	 * Scan post content for missing alt attributes.
	 *
	 * ## OPTIONS
	 *
	 * [--refresh]
	 * : Refresh quick scan cache.
	 *
	 * [--full]
	 * : Start a full-site batched scan (Pro).
	 */
	public function content_scan( array $args, array $assoc_args ): void {
		self::assertModuleReady();

		if ( ! empty( $assoc_args['full'] ) ) {
			$result = ContentScanner::startFullScan();
			if ( ( $result['status'] ?? '' ) === 'failed' ) {
				\WP_CLI::error( (string) ( $result['message'] ?? __( 'Scan failed.', 'wppowersuite-lite' ) ) );
			}
			\WP_CLI::success( (string) ( $result['message'] ?? __( 'Full-site scan started.', 'wppowersuite-lite' ) ) );
			return;
		}

		$summary = ContentScanner::getSummary( ! empty( $assoc_args['refresh'] ) );
		\WP_CLI\Utils\format_items( 'table', [ $summary ], array_keys( $summary ) );
	}

	/**
	 * Push library alt text into post content for scanned issues.
	 *
	 * ## OPTIONS
	 *
	 * [--refresh]
	 * : Refresh content scan before syncing.
	 */
	public function sync_content( array $args, array $assoc_args ): void {
		self::assertModuleReady();
		$result = BulkActions::syncLibraryAltToContent( ! empty( $assoc_args['refresh'] ) );
		\WP_CLI::success( (string) ( $result['message'] ?? __( 'Sync complete.', 'wppowersuite-lite' ) ) );
	}

	/**
	 * Regenerate alt text for duplicate images.
	 *
	 * ## OPTIONS
	 *
	 * [--queue]
	 * : Queue regeneration instead of processing a small batch immediately.
	 */
	public function regenerate_duplicates( array $args, array $assoc_args ): void {
		self::assertModuleReady();
		$result = BulkActions::regenerateDuplicates();
		if ( (int) ( $result['queued'] ?? 0 ) === 0 && str_contains( (string) ( $result['message'] ?? '' ), 'Pro' ) ) {
			\WP_CLI::error( (string) $result['message'] );
		}
		\WP_CLI::success( (string) ( $result['message'] ?? '' ) );
	}

	/**
	 * Export alt text report as CSV.
	 *
	 * ## OPTIONS
	 *
	 * [--type=<type>]
	 * : Report type: missing, weak, pending, duplicates, all. Default: missing.
	 *
	 * [--file=<path>]
	 * : Write CSV to file instead of stdout.
	 */
	public function export( array $args, array $assoc_args ): void {
		self::assertModuleReady();
		ModuleLoader::importExport();
		if ( ! class_exists( Exporter::class, false ) ) {
			\WP_CLI::error( __( 'CSV export is available in Pro.', 'wppowersuite-lite' ) );
		}

		$type = sanitize_key( (string) ( $assoc_args['type'] ?? 'missing' ) );
		$csv  = Exporter::toCsvString( $type );

		if ( ! empty( $assoc_args['file'] ) ) {
			$written = file_put_contents( $assoc_args['file'], $csv );
			if ( $written === false ) {
				\WP_CLI::error( __( 'Could not write export file.', 'wppowersuite-lite' ) );
			}
			\WP_CLI::success( sprintf(
				/* translators: %s: file path */
				__( 'Exported to %s', 'wppowersuite-lite' ),
				$assoc_args['file']
			) );
			return;
		}

		\WP_CLI::line( $csv );
	}

	/**
	 * Import alt text from a CSV file.
	 *
	 * ## OPTIONS
	 *
	 * <file>
	 * : Path to CSV file.
	 */
	public function import( array $args, array $assoc_args ): void {
		self::assertModuleReady();

		ModuleLoader::importExport();
		if ( ! class_exists( Importer::class, false ) ) {
			\WP_CLI::error( __( 'CSV import is available in Pro.', 'wppowersuite-lite' ) );
		}

		$path = $args[0] ?? '';
		if ( $path === '' ) {
			\WP_CLI::error( __( 'Provide a CSV file path.', 'wppowersuite-lite' ) );
		}

		$result = Importer::importFromPath( $path );
		foreach ( $result['errors'] as $error ) {
			\WP_CLI::warning( $error );
		}

		\WP_CLI::success( sprintf(
			/* translators: 1: number, 2: number. */
			__( 'Imported %1$d rows, skipped %2$d.', 'wppowersuite-lite' ),
			(int) $result['imported'],
			(int) $result['skipped']
		) );
	}

	/**
	 * Show background queue status.
	 */
	public function queue( array $args, array $assoc_args ): void {
		self::assertModuleReady();
		\WP_CLI\Utils\format_items( 'table', [ Queue::getStatus() ], array_keys( Queue::getStatus() ) );
	}

	/**
	 * Show recent performance timings.
	 */
	public function performance( array $args, array $assoc_args ): void {
		self::assertModuleReady();
		$summary = Performance::getSummary();
		\WP_CLI::line( wp_json_encode( $summary, JSON_PRETTY_PRINT ) );
	}

	private static function assertModuleReady(): void {
		$module = new Module();
		if ( ! $module->isEnabled() ) {
			\WP_CLI::error( __( 'AI Alt Text Generator module is not enabled. Enable it in WP PowerSuite.', 'wppowersuite-lite' ) );
		}

		if ( ! Settings::hasApiKey() ) {
			\WP_CLI::error( __( 'API key not configured for the selected provider.', 'wppowersuite-lite' ) );
		}
	}

	/**
	 * @param array<string, string>     $assoc_args
	 * @param array<string, mixed>      $settings
	 * @return list<int>
	 */
	private static function resolveAttachmentIds( array $assoc_args, array $settings ): array {
		if ( ! empty( $assoc_args['ids'] ) ) {
			return array_values( array_filter( array_map( 'intval', explode( ',', (string) $assoc_args['ids'] ) ) ) );
		}

		if ( ! empty( $assoc_args['all'] ) ) {
			return self::getEligibleIds( ! empty( $assoc_args['overwrite'] ) || ! empty( $settings['overwrite_existing'] ) );
		}

		return [];
	}

	/**
	 * @return list<int>
	 */
	private static function getEligibleIds( bool $include_with_alt ): array {
		if ( ! $include_with_alt ) {
			return Scanner::getMissingIds( 10000, 0 );
		}

		global $wpdb;
		$mimes      = AltTextGenerator::getSupportedMimes();
		$mime_place = implode( ',', array_fill( 0, count( $mimes ), '%s' ) );
		$args       = array_merge( [ 'attachment', 'inherit' ], $mimes );

		$ids = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT ID FROM {$wpdb->posts}
				WHERE post_type = %s AND post_status = %s
				AND post_mime_type IN ($mime_place)
				ORDER BY ID ASC",
				...$args
			)
		);

		return array_map( 'intval', $ids ?: [] );
	}
}

