<?php

namespace SerpIQ\Cli;

use SerpIQ\Gsc\Backfill;

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

/**
 * WP-CLI commands for robust backfill running on difficult hosting.
 */
final class Backfill_Command {
	/**
	 * Run backfill batches.
	 *
	 * ## OPTIONS
	 *
	 * [--due-now]
	 * : Only run if the next scheduled backfill step is due now (or overdue).
	 *
	 * [--max=<n>]
	 * : Maximum number of batches to run in this invocation. Default: 1.
	 *
	 * ## EXAMPLES
	 *
	 *     wp serpiq backfill run --due-now
	 *     wp serpiq backfill run --max=5
	 *
	 * @when after_wp_load
	 */
	public function run( array $args, array $assoc_args ): void {
		$due_now = isset( $assoc_args['due-now'] );
		$max     = isset( $assoc_args['max'] ) ? (int) $assoc_args['max'] : 1;
		if ( $max <= 0 ) {
			$max = 1;
		}
		if ( $max > 50 ) {
			$max = 50;
		}

		$state  = Backfill::instance()->get_state();
		$status = isset( $state['status'] ) ? (string) $state['status'] : 'idle';
		if ( 'running' !== $status ) {
			\WP_CLI::warning( sprintf( 'Backfill is not running (status=%s).', $status ) );
			return;
		}

		if ( $due_now ) {
			$next = wp_next_scheduled( 'serpiq_backfill_step' );
			if ( $next && (int) $next > time() ) {
				\WP_CLI::log( sprintf( 'Not due yet. Next run: %s (UTC).', gmdate( 'c', (int) $next ) ) );
				return;
			}
		}

		for ( $i = 0; $i < $max; $i++ ) {
			$before = Backfill::instance()->get_state();
			Backfill::instance()->run_next_batch();
			$after = Backfill::instance()->get_state();

			$st = isset( $after['status'] ) ? (string) $after['status'] : 'idle';
			$range = (string) ( $after['last_batch_start'] ?? '' );
			$range .= $after['last_batch_end'] ? ' → ' . (string) $after['last_batch_end'] : '';
			$rows = (int) ( $after['last_batch_rows'] ?? 0 );
			$dur  = (int) ( $after['last_batch_duration'] ?? 0 );

			if ( 'error' === $st ) {
				$msg = (string) ( $after['error_message'] ?? 'Unknown error.' );
				\WP_CLI::error( sprintf( 'Batch failed (%s). %s', $range ? $range : 'unknown range', $msg ), false );
				return;
			}

			\WP_CLI::log( sprintf( 'Batch ok: %s | rows=%d | duration_ms=%d | status=%s', $range ? $range : '(no range)', $rows, $dur, $st ) );

			if ( 'completed' === $st ) {
				\WP_CLI::success( 'Backfill completed.' );
				return;
			}

			// If state didn't advance at all, avoid tight loops.
			if ( $before === $after ) {
				\WP_CLI::warning( 'Backfill state did not change; stopping this run.' );
				return;
			}
		}

		\WP_CLI::success( sprintf( 'Done. Ran up to %d batch(es).', $max ) );
	}
}

