<?php
/**
 * Trigger Config Value Object
 *
 * Value object for trigger configuration.
 *
 * @package Sequensy
 * @since 2.0.0
 */

declare(strict_types=1);

namespace Sequensy\ValueObjects;

use WP_Error;

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

/**
 * Class TriggerConfig
 *
 * Value object for trigger configuration.
 */
class TriggerConfig implements \JsonSerializable {

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

	/**
	 * Trigger-specific configuration.
	 *
	 * @var array
	 */
	private array $config;

	/**
	 * Display name.
	 *
	 * @var string|null
	 */
	private ?string $name;

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

	/**
	 * Private constructor.
	 *
	 * @param string      $type        Trigger type.
	 * @param array       $config      Configuration data.
	 * @param string|null $name        Display name.
	 * @param string|null $integration Integration ID.
	 */
	private function __construct( string $type, array $config, ?string $name = null, ?string $integration = null ) {
		$this->type        = $type;
		$this->config      = $config;
		$this->name        = $name;
		$this->integration = $integration;
	}

	/**
	 * Create from array.
	 *
	 * @param array $data Trigger data.
	 * @return self|WP_Error Trigger config or error.
	 */
	public static function from_array( array $data ): self|WP_Error {
		if ( ! isset( $data['type'] ) || ! is_string( $data['type'] ) || empty( $data['type'] ) ) {
			return new WP_Error(
				'invalid_trigger',
				'Trigger must have a type.'
			);
		}

		$config      = isset( $data['config'] ) && is_array( $data['config'] ) ? $data['config'] : array();
		$name        = isset( $data['name'] ) && is_string( $data['name'] ) ? $data['name'] : null;
		$integration = isset( $data['integration'] ) && is_string( $data['integration'] ) ? $data['integration'] : null;

		return new self( $data['type'], $config, $name, $integration );
	}

	/**
	 * Get trigger type.
	 *
	 * @return string Trigger type.
	 */
	public function get_type(): string {
		return $this->type;
	}

	/**
	 * Get configuration data.
	 *
	 * @return array Config data.
	 */
	public function get_config(): array {
		return $this->config;
	}

	/**
	 * Get a specific config value.
	 *
	 * @param string $key           Config key.
	 * @param mixed  $default_value Default value.
	 * @return mixed Config value or default.
	 */
	public function get_config_value( string $key, mixed $default_value = null ): mixed {
		return $this->config[ $key ] ?? $default_value;
	}

	/**
	 * Get display name.
	 *
	 * @return string|null Display name.
	 */
	public function get_name(): ?string {
		return $this->name;
	}

	/**
	 * Get integration identifier.
	 *
	 * @return string|null Integration ID.
	 */
	public function get_integration(): ?string {
		return $this->integration;
	}

	/**
	 * Convert to array.
	 *
	 * @return array Trigger data.
	 */
	public function to_array(): array {
		$data = array(
			'type'   => $this->type,
			'config' => $this->config,
		);

		if ( null !== $this->name ) {
			$data['name'] = $this->name;
		}

		if ( null !== $this->integration ) {
			$data['integration'] = $this->integration;
		}

		return $data;
	}

	/**
	 * Implement JsonSerializable for REST API responses.
	 *
	 * @return array Data to serialize.
	 */
	public function jsonSerialize(): array {
		return $this->to_array();
	}
}
