<?php

namespace iThemesSecurity\Site_Scanner;

final class Vulnerability_Issue implements Issue {
	use Issue_Trait;

	/** @var array */
	private $vulnerability;

	/** @var array */
	private $issue;

	/** @var array */
	private $firewall_rules;

	/**
	 * Vulnerability constructor.
	 *
	 * @param array  $vulnerability The full vulnerability details for the software item.
	 * @param string $issue_id      The id of this particular issue.
	 * @param string $details_link  The link to more details about the issue.
	 */
	public function __construct( array $vulnerability, $issue_id, $details_link ) {
		$match = wp_list_filter( $vulnerability['issues'], [ 'id' => $issue_id ] );
		$issue = reset( $match );

		$this->id             = $issue_id;
		$this->description    = $issue['title'];
		$this->status         = \ITSEC_Site_Scanner_Util::is_issue_muted( $issue_id ) ? Status::CLEAN : Status::WARN;
		$this->link           = \ITSEC_Core::get_admin_page_url( 'vulnerabilities', '/vulnerability/' . $issue_id );
		$this->issue          = $issue;
		$this->vulnerability  = $vulnerability;
		$this->entry          = 'vulnerabilities';
		$this->firewall_rules = array_filter(
			isset( $vulnerability['firewall_rules'] ) ? $vulnerability['firewall_rules'] : [],
			function ( array $rule ) use ( $issue_id ) {
				return $issue_id === $rule['vulnerability'];
			}
		);
	}

	public function get_meta() {
		$meta = [
			'issue' => $this->issue,
			'type'  => $this->vulnerability['type'],
		];

		if ( isset( $this->vulnerability['software'] ) ) {
			$meta['software'] = $this->vulnerability['software'];
		}

		return $meta;
	}

	/**
	 * Get the version the vulnerability was fixed in.
	 *
	 * @return string|null
	 */
	public function get_fixed_in() {
		return $this->issue['fixed_in'];
	}

	/**
	 * Get the applicable firewall rules for this vulnerability.
	 *
	 * @return array
	 */
	public function get_firewall_rules(): array {
		return $this->firewall_rules;
	}

	/**
	 * Get the severity for the score.
	 *
	 * @return string
	 */
	public function get_severity(): string {
		$score = $this->issue['details']['score'] ?? 0;

		if ( $score < 3 ) {
			return 'low';
		}

		if ( $score < 7 ) {
			return 'medium';
		}

		if ( $score < 9 ) {
			return 'high';
		}

		return 'critical';
	}
}
