<?php
/**
 * One line of the setup readiness panel.
 *
 * @since   1.2.0
 * @package DonationRouter
 */

declare( strict_types=1 );
namespace DonationRouter;

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

/**
 * The result of a single readiness check.
 *
 * A value object rather than an array: PHPStan level 8 array shapes for six
 * fields across ten producers are unpleasant to keep in step, and this matches
 * how PayPal_Account and Country_Routing are already written.
 *
 * @since 1.2.0
 */
class Setup_Check {

	/**
	 * Nothing to do.
	 *
	 * @since 1.2.0
	 *
	 * @var string
	 */
	public const PASS = 'pass';

	/**
	 * Routing works, but something the plugin promises is not happening.
	 *
	 * @since 1.2.0
	 *
	 * @var string
	 */
	public const WARN = 'warn';

	/**
	 * Routing is broken; donations are not reaching the intended account.
	 *
	 * @since 1.2.0
	 *
	 * @var string
	 */
	public const FAIL = 'fail';

	/**
	 * Construct a check result.
	 *
	 * @since 1.2.0
	 *
	 * @param string $id        Stable identifier, used by tests and filters.
	 * @param string $state     One of PASS, WARN or FAIL.
	 * @param string $label     Short human-readable name.
	 * @param string $detail    One sentence explaining the current state.
	 * @param string $fix_url   Admin URL that resolves it, or ''.
	 * @param string $fix_label Link text for $fix_url, or ''.
	 *
	 * @throws \InvalidArgumentException When $state is not one of the three constants.
	 */
	public function __construct(
		public readonly string $id,
		public readonly string $state,
		public readonly string $label,
		public readonly string $detail = '',
		public readonly string $fix_url = '',
		public readonly string $fix_label = '',
	) {
		if ( ! in_array( $this->state, array( self::PASS, self::WARN, self::FAIL ), true ) ) {
			throw new \InvalidArgumentException( 'state must be pass, warn or fail.' );
		}
	}

	/**
	 * Whether routing is broken by this check.
	 *
	 * @since 1.2.0
	 *
	 * @return bool
	 */
	public function is_fail(): bool {
		return self::FAIL === $this->state;
	}

	/**
	 * Whether this check is a non-blocking warning.
	 *
	 * @since 1.2.0
	 *
	 * @return bool
	 */
	public function is_warn(): bool {
		return self::WARN === $this->state;
	}
}
