<?php
/**
 * Detection rule.
 *
 * @package LocalGuardScanner
 */

namespace LocalGuardScanner\Detection\Rules;

use InvalidArgumentException;

/**
 * Validated local rule definition.
 */
final class Rule {
	/** @var array<string,mixed> */
	private $data;

	/**
	 * @param array<string,mixed> $data Rule data.
	 */
	public function __construct( array $data ) {
		foreach ( array( 'id', 'type', 'weight', 'confidence', 'message_key' ) as $required ) {
			if ( ! array_key_exists( $required, $data ) ) {
				throw new InvalidArgumentException( 'Rule is missing a required field.' );
			}
		}
		if ( ! is_string( $data['id'] ) || ! preg_match( '/^[a-z0-9._-]{4,96}$/', $data['id'] ) ) {
			throw new InvalidArgumentException( 'Rule ID is invalid.' );
		}
		if ( ! in_array( $data['type'], array( 'marker', 'token_sequence', 'location' ), true ) ) {
			throw new InvalidArgumentException( 'Rule type is invalid.' );
		}
		if ( ! is_int( $data['weight'] ) || $data['weight'] < 0 || $data['weight'] > 100 ) {
			throw new InvalidArgumentException( 'Rule weight is invalid.' );
		}
		if ( ! is_int( $data['confidence'] ) || $data['confidence'] < 0 || $data['confidence'] > 100 ) {
			throw new InvalidArgumentException( 'Rule confidence is invalid.' );
		}
		$this->data = $data;
	}

	/** @return string */
	public function id() {
		return $this->data['id'];
	}

	/** @return string */
	public function type() {
		return $this->data['type'];
	}

	/** @return int */
	public function weight() {
		return $this->data['weight'];
	}

	/** @return int */
	public function confidence() {
		return $this->data['confidence'];
	}

	/** @return string */
	public function message_key() {
		return $this->data['message_key'];
	}

	/** @return array<string,mixed> */
	public function data() {
		return $this->data;
	}
}
