<?php
/**
 * Trigger Definition - Immutable Data Class
 *
 * Holds all configuration for a declaratively-defined trigger.
 *
 * @package Sequensy
 * @since 2.0.0
 */

declare(strict_types=1);

namespace Sequensy\Triggers\Configuration;

use Closure;

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
	die;
}

/**
 * Class TriggerDefinition
 *
 * Immutable data class holding trigger configuration.
 * Supports both array and Closure values for lazy evaluation.
 */
final class TriggerDefinition {

	/**
	 * Constructor with named arguments for all trigger properties.
	 *
	 * @param string        $type            Trigger type identifier (e.g., 'wordpress/user_registration').
	 * @param string        $label           Human-readable label.
	 * @param string        $description     Trigger description.
	 * @param string        $hook            WordPress hook to listen on.
	 * @param int           $priority        Hook priority (default 10).
	 * @param int           $accepted_args   Number of arguments the hook passes.
	 * @param Closure|array $available_fields Available data fields definition.
	 * @param Closure       $build_context   Closure to build context from hook args.
	 * @param string|null   $integration     Integration slug (null for WordPress core).
	 * @param Closure|null  $should_fire     Optional condition check before firing.
	 * @param array         $options         Additional options for specific trigger types.
	 */
	public function __construct(
		public readonly string $type,
		public readonly string $label,
		public readonly string $description,
		public readonly string $hook,
		public readonly int $priority,
		public readonly int $accepted_args,
		public readonly Closure|array $available_fields,
		public readonly Closure $build_context,
		public readonly ?string $integration = null,
		public readonly ?Closure $should_fire = null,
		public readonly array $options = array(),
	) {
	}

	/**
	 * Get available fields, evaluating closure if needed.
	 *
	 * @return array Available fields array.
	 */
	public function get_available_fields(): array {
		if ( $this->available_fields instanceof Closure ) {
			return ( $this->available_fields )();
		}
		return $this->available_fields;
	}

	/**
	 * Build context from hook arguments.
	 *
	 * @param mixed ...$args Hook arguments.
	 * @return array|null Context array or null to skip execution.
	 */
	public function build_context( ...$args ): ?array {
		return ( $this->build_context )( ...$args );
	}

	/**
	 * Check if trigger should fire.
	 *
	 * @return bool True if trigger should fire.
	 */
	public function should_fire(): bool {
		if ( null === $this->should_fire ) {
			return true;
		}
		return ( $this->should_fire )();
	}

	/**
	 * Check if this trigger has a should_fire condition.
	 *
	 * @return bool True if has condition.
	 */
	public function has_condition(): bool {
		return null !== $this->should_fire;
	}
}
