<?php
/**
 * Dismissible admin notice nudging toward a wordpress.org review after the
 * 3rd import applied with no failures (SPEC/L-6: no incentives, no
 * recurrence once dismissed, never blocking). Only rendered on this
 * plugin's own admin screens, never dashboard-wide (wordpress.org
 * guideline 11).
 *
 * @package EmberPrice
 */

namespace EmberPrice\Admin;

use EmberPrice\Core\Jobs;

defined( 'ABSPATH' ) || exit;

/**
 * Registered from the composition root alongside the other Admin pages.
 * Reads job history via Core\Jobs only (per CLAUDE.md's dependency matrix,
 * Admin may import Core but nothing else).
 */
final class ReviewPrompt {

	private const DISMISSED_META_KEY  = 'embp_review_prompt_dismissed';
	private const NONCE_ACTION        = 'embp_dismiss_review_prompt';
	private const MIN_SUCCESSFUL_JOBS = 3;

	/**
	 * Job data access.
	 *
	 * @var Jobs
	 */
	private Jobs $jobs;

	/**
	 * Constructor.
	 *
	 * @param Jobs|null $jobs Defaults to a new instance.
	 */
	public function __construct( ?Jobs $jobs = null ) {
		$this->jobs = $jobs ?? new Jobs();
	}

	/**
	 * Wires this into WordPress. Called once from the composition root.
	 */
	public function register(): void {
		add_action( 'admin_notices', array( $this, 'maybe_render' ) );
		add_action( 'admin_post_' . self::NONCE_ACTION, array( $this, 'handle_dismiss' ) );
	}

	/**
	 * Renders the notice if the current screen is one of this plugin's own
	 * (wizard/history/settings, all `*_page_emberprice*`), this user hasn't
	 * dismissed it, and the gating condition (SPEC/L-6) is met.
	 */
	public function maybe_render(): void {
		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;

		if ( null === $screen || ! str_contains( $screen->id, '_page_emberprice' ) ) {
			return;
		}

		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}

		if ( get_user_meta( get_current_user_id(), self::DISMISSED_META_KEY, true ) ) {
			return;
		}

		if ( ! $this->should_show() ) {
			return;
		}

		$this->render();
	}

	/**
	 * At least MIN_SUCCESSFUL_JOBS jobs have reached `applied`/`rolled_back`
	 * (rolling back doesn't erase that the import itself succeeded), and
	 * none of them had any row-level apply failures -- "no hubo errores
	 * recientes en imports" is read as "every completed import so far was
	 * clean", not just the triggering one.
	 */
	private function should_show(): bool {
		$completed_jobs = array_filter(
			$this->jobs->list_all(),
			static function ( array $job ): bool {
				return in_array( $job['status'], array( 'applied', 'rolled_back' ), true );
			}
		);

		if ( count( $completed_jobs ) < self::MIN_SUCCESSFUL_JOBS ) {
			return false;
		}

		foreach ( $completed_jobs as $job ) {
			$failed = (int) ( $job['totals']['apply']['failed'] ?? 0 );

			if ( $failed > 0 ) {
				return false;
			}
		}

		return true;
	}

	/**
	 * Outputs the notice markup. No incentive offered, no recurrence talk --
	 * just the ask and a way to make it stop.
	 */
	private function render(): void {
		$dismiss_url = wp_nonce_url(
			admin_url( 'admin-post.php?action=' . self::NONCE_ACTION ),
			self::NONCE_ACTION
		);
		?>
		<div class="notice notice-info is-dismissible embp-review-prompt">
			<p>
				<?php
				esc_html_e(
					"You've applied a few price updates with EmberPrice without a hitch. If it's saving you time, a quick review would help other store owners find it.",
					'emberprice'
				);
				?>
			</p>
			<p>
				<a
					href="https://wordpress.org/support/plugin/emberprice/reviews/#new-post"
					target="_blank"
					rel="noopener noreferrer"
					class="button button-primary"
				>
					<?php esc_html_e( 'Leave a review', 'emberprice' ); ?>
				</a>
				<a href="<?php echo esc_url( $dismiss_url ); ?>" class="button">
					<?php esc_html_e( "I already did / Don't show this again", 'emberprice' ); ?>
				</a>
			</p>
		</div>
		<?php
	}

	/**
	 * `admin-post.php?action=embp_dismiss_review_prompt`: permanently turns
	 * the notice off for the current user, then returns to wherever they
	 * clicked it from.
	 */
	public function handle_dismiss(): void {
		check_admin_referer( self::NONCE_ACTION );

		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			wp_die( esc_html__( 'You do not have permission to do this.', 'emberprice' ), 403 );
		}

		update_user_meta( get_current_user_id(), self::DISMISSED_META_KEY, 1 );

		$referer = wp_get_referer();
		wp_safe_redirect( false !== $referer ? $referer : admin_url() );
		exit;
	}
}
