<?php
/**
 * Trigger Definition Builder - Fluent API
 *
 * Provides a fluent interface for building TriggerDefinition objects
 * with category presets for common trigger patterns.
 *
 * @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 TriggerDefinitionBuilder
 *
 * Fluent builder for creating TriggerDefinition objects.
 * Provides static factory methods for common trigger categories.
 */
final class TriggerDefinitionBuilder {

	/**
	 * Trigger type identifier.
	 *
	 * @var string
	 */
	private string $type = '';

	/**
	 * Human-readable label.
	 *
	 * @var string
	 */
	private string $label = '';

	/**
	 * Trigger description.
	 *
	 * @var string
	 */
	private string $description = '';

	/**
	 * Integration slug.
	 *
	 * @var string|null
	 */
	private ?string $integration = null;

	/**
	 * WordPress hook name.
	 *
	 * @var string
	 */
	private string $hook = '';

	/**
	 * Hook priority.
	 *
	 * @var int
	 */
	private int $priority = 10;

	/**
	 * Number of accepted arguments.
	 *
	 * @var int
	 */
	private int $accepted_args = 1;

	/**
	 * Available fields definition.
	 *
	 * @var Closure|array
	 */
	private Closure|array $available_fields = array();

	/**
	 * Context builder closure.
	 *
	 * @var Closure|null
	 */
	private ?Closure $build_context = null;

	/**
	 * Condition check closure.
	 *
	 * @var Closure|null
	 */
	private ?Closure $should_fire = null;

	/**
	 * Additional options.
	 *
	 * @var array
	 */
	private array $options = array();

	/**
	 * Private constructor - use static factory methods.
	 */
	private function __construct() {
	}

	/**
	 * Create a WordPress core trigger builder.
	 *
	 * @return self Builder instance.
	 */
	public static function wordpress(): self {
		$builder              = new self();
		$builder->integration = null; // WordPress core has no integration.
		return $builder;
	}

	/**
	 * Create a generic integration trigger builder.
	 *
	 * @param string $integration Integration slug.
	 * @return self Builder instance.
	 */
	public static function integration( string $integration ): self {
		$builder              = new self();
		$builder->integration = $integration;
		return $builder;
	}

	/**
	 * Set trigger type identifier.
	 *
	 * @param string $type Trigger type (e.g., 'wordpress/user_registration').
	 * @return self Builder instance.
	 */
	public function type( string $type ): self {
		$this->type = $type;
		return $this;
	}

	/**
	 * Set trigger display label.
	 *
	 * @param string $label Human-readable label.
	 * @return self Builder instance.
	 */
	public function label( string $label ): self {
		$this->label = $label;
		return $this;
	}

	/**
	 * Set trigger description.
	 *
	 * @param string $description Description text.
	 * @return self Builder instance.
	 */
	public function description( string $description ): self {
		$this->description = $description;
		return $this;
	}

	/**
	 * Set the WordPress hook to listen on.
	 *
	 * @param string $hook     Hook name.
	 * @param int    $priority Hook priority (default 10).
	 * @param int    $args     Number of accepted arguments (default 1).
	 * @return self Builder instance.
	 */
	public function hook( string $hook, int $priority = 10, int $args = 1 ): self {
		$this->hook          = $hook;
		$this->priority      = $priority;
		$this->accepted_args = $args;
		return $this;
	}

	/**
	 * Set available fields definition.
	 *
	 * @param Closure|array $fields Fields array or closure returning fields.
	 * @return self Builder instance.
	 */
	public function availableFields( Closure|array $fields ): self {
		$this->available_fields = $fields;
		return $this;
	}

	/**
	 * Set context builder closure.
	 *
	 * The closure receives hook arguments and should return an array of context data,
	 * or null to skip workflow execution.
	 *
	 * @param Closure $builder Closure to build context from hook args.
	 * @return self Builder instance.
	 */
	public function buildContext( Closure $builder ): self {
		$this->build_context = $builder;
		return $this;
	}

	/**
	 * Set condition check closure.
	 *
	 * The closure should return true if the trigger should fire.
	 * Common use: checking if a plugin is active.
	 *
	 * @param Closure $condition Closure returning boolean.
	 * @return self Builder instance.
	 */
	public function shouldFire( Closure $condition ): self {
		$this->should_fire = $condition;
		return $this;
	}

	/**
	 * Set additional options.
	 *
	 * @param array $options Options array.
	 * @return self Builder instance.
	 */
	public function options( array $options ): self {
		$this->options = $options;
		return $this;
	}

	/**
	 * Add a single option.
	 *
	 * @param string $key   Option key.
	 * @param mixed  $value Option value.
	 * @return self Builder instance.
	 */
	public function option( string $key, mixed $value ): self {
		$this->options[ $key ] = $value;
		return $this;
	}

	/**
	 * Build the TriggerDefinition object.
	 *
	 * @return TriggerDefinition Immutable trigger definition.
	 * @throws \InvalidArgumentException If required fields are missing.
	 */
	public function build(): TriggerDefinition {
		// Validate required fields.
		if ( empty( $this->type ) ) {
			throw new \InvalidArgumentException( 'Trigger type is required' );
		}
		if ( empty( $this->label ) ) {
			throw new \InvalidArgumentException( 'Trigger label is required' );
		}
		if ( empty( $this->hook ) ) {
			throw new \InvalidArgumentException( 'WordPress hook is required' );
		}
		if ( null === $this->build_context ) {
			throw new \InvalidArgumentException( 'Context builder closure is required' );
		}

		return new TriggerDefinition(
			type: $this->type,
			label: $this->label,
			description: $this->description,
			hook: $this->hook,
			priority: $this->priority,
			accepted_args: $this->accepted_args,
			available_fields: $this->available_fields,
			build_context: $this->build_context,
			integration: $this->integration,
			should_fire: $this->should_fire,
			options: $this->options,
		);
	}
}
