<?php
/**
 * Immutable schema-validation issue value object.
 *
 * @package SEOvaultSEO\Schema\Validation
 */

namespace SEOvaultSEO\Schema\Validation;

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

/**
 * Represents one structured, presentation-independent validation issue.
 */
class ValidationIssue {

	/**
	 * Stable issue code.
	 *
	 * @var string
	 */
	private $code;

	/**
	 * Issue severity.
	 *
	 * @var string
	 */
	private $severity;

	/**
	 * Rule category.
	 *
	 * @var string
	 */
	private $category;

	/**
	 * Affected entity type.
	 *
	 * @var string
	 */
	private $entity_type;

	/**
	 * Affected entity identifier.
	 *
	 * @var string
	 */
	private $entity_id;

	/**
	 * Stable property path.
	 *
	 * @var string
	 */
	private $path;

	/**
	 * Input source identifier.
	 *
	 * @var string
	 */
	private $source;

	/**
	 * Whether the issue has a declarative fix action.
	 *
	 * @var bool
	 */
	private $fixable;

	/**
	 * Declarative fix action.
	 *
	 * @var string
	 */
	private $fix_action;

	/**
	 * Internal documentation key.
	 *
	 * @var string
	 */
	private $documentation;

	/**
	 * Untranslated presentation title key.
	 *
	 * @var string
	 */
	private $title_key;

	/**
	 * Untranslated presentation message key.
	 *
	 * @var string
	 */
	private $message_key;

	/**
	 * Values supplied to the message presenter.
	 *
	 * @var array
	 */
	private $message_args;

	/**
	 * Create an issue from stable, already validated rule data.
	 *
	 * Translation happens later through title_key and message_key. Rule code must
	 * never place translated copy in this object.
	 *
	 * @param array $data Issue data.
	 */
	public function __construct( $data = array() ) {
		$this->code          = isset( $data['code'] ) ? (string) $data['code'] : '';
		$this->severity      = isset( $data['severity'] ) && Severity::is_valid( $data['severity'] ) ? $data['severity'] : Severity::INFO;
		$this->category      = isset( $data['category'] ) ? (string) $data['category'] : '';
		$this->entity_type   = isset( $data['entity_type'] ) ? (string) $data['entity_type'] : '';
		$this->entity_id     = isset( $data['entity_id'] ) ? (string) $data['entity_id'] : '';
		$this->path          = isset( $data['path'] ) ? (string) $data['path'] : '';
		$this->source        = isset( $data['source'] ) ? (string) $data['source'] : '';
		$this->fixable       = ! empty( $data['fixable'] );
		$this->fix_action    = isset( $data['fix_action'] ) ? (string) $data['fix_action'] : '';
		$this->documentation = isset( $data['documentation'] ) ? (string) $data['documentation'] : '';
		$this->title_key     = isset( $data['title_key'] ) ? (string) $data['title_key'] : '';
		$this->message_key   = isset( $data['message_key'] ) ? (string) $data['message_key'] : '';
		$this->message_args  = isset( $data['message_args'] ) && is_array( $data['message_args'] ) ? $data['message_args'] : array();
	}

	/**
	 * Get the stable issue code.
	 *
	 * @return string
	 */
	public function get_code() {
		return $this->code;
	}

	/**
	 * Get the issue severity.
	 *
	 * @return string
	 */
	public function get_severity() {
		return $this->severity;
	}

	/**
	 * Get a stable de-duplication signature.
	 *
	 * @return string
	 */
	public function get_signature() {
		return implode(
			'|',
			array(
				$this->code,
				$this->severity,
				$this->category,
				$this->entity_id,
				$this->path,
				$this->source,
			)
		);
	}

	/**
	 * Export the issue for a future presenter, cache, or API response.
	 *
	 * @return array
	 */
	public function to_array() {
		return array(
			'code'          => $this->code,
			'severity'      => $this->severity,
			'category'      => $this->category,
			'entity_type'   => $this->entity_type,
			'entity_id'     => $this->entity_id,
			'path'          => $this->path,
			'source'        => $this->source,
			'fixable'       => $this->fixable,
			'fix_action'    => $this->fix_action,
			'documentation' => $this->documentation,
			'title_key'     => $this->title_key,
			'message_key'   => $this->message_key,
			'message_args'  => $this->message_args,
		);
	}
}
