<?php
/**
 * Lead Score assigned Segments
 *
 * @link       https://personalizewp.com/
 * @since      3.2.0 Merged into PWP
 * @since      1.1.0
 *
 * @package    PersonalizeWP
 * @subpackage PersonalizeWP/Segments
 */

namespace PersonalizeWP\Segments;

use PersonalizeWP\Segments\Base;
use PersonalizeWP\Model\Activity;
use PersonalizeWP\Model\Contact;

defined( 'ABSPATH' ) || exit; // Exit if accessed directly.

/**
 * Lead Score Segments
 *
 * Handles changes to Contacts scores
 */
class Lead_Score extends Base {

	/**
	 * Types of Segment to process
	 *
	 * @var array
	 */
	protected $segment_types = array( 'lead_score' );

	/**
	 * Add hooks. Overriden from parent as not hooked into Activities.
	 *
	 * @since 1.1.0
	 *
	 * @return void
	 */
	public function setup() {
		add_action( 'personalizewp_contact_update_score', array( $this, 'process_score_change' ), 10 );
	}

	/**
	 * Do nothing as not called.
	 *
	 * @since 1.1.0
	 *
	 * @param Activity $activity Activity object
	 *
	 * @return void
	 */
	public function process_activity( $activity ) {}

	/**
	 * Do nothing as not called.
	 *
	 * @since 2.3.0
	 *
	 * @param array $args Unused
	 *
	 * @return void
	 */
	protected function condition_has_matched_criteria( $args ) {}

	/**
	 * Process score change on Contact
	 *
	 * Doesn't use condition_has_matched_criteria() as potentially adding and removing from Segment, and no multiple criteria.
	 *
	 * @since 1.1.0
	 *
	 * @param Contact $contact Contact object
	 *
	 * @return void
	 */
	public function process_score_change( $contact = '' ) {

		// Sanity check.
		if ( empty( $contact ) ) {
			return;
		}

		if ( ! isset( $this->segments ) ) {
			$this->segments = $this->get_segments();
		}

		if ( empty( $this->segments ) ) {
			return;
		}

		foreach ( $this->segments as $segment ) {
			// Sanity check.
			if ( empty( $segment['conditions'] ) ) {
				continue;
			}
			list( 'min' => $min, 'max' => $max ) = json_decode( $segment['conditions'], true );

			$min          = (int) $min;
			$max          = (int) $max;
			$maybe_add    = false;
			$maybe_remove = false;

			// Sanity check, minimum not set, or maximum less than minimum
			if ( 0 === $min || ( 0 !== $max && $max < $min ) ) {
				continue;
			}

			if ( 0 === $max && $contact->lead_score >= $min ) {
				// Maximum hasn't been set, Visitor has lead score greater than the minimum.
				$maybe_add = true;
			} elseif ( 0 === $max && $contact->lead_score < $min ) {
				// Maximum hasn't been set, Visitor has lead score smaller than the minimum.
				$maybe_remove = true;
			}

			if ( 0 !== $max && $contact->lead_score >= $min && $contact->lead_score < $max ) {
				// A maximum has been set, and Visitor has lead score inside of the range
				$maybe_add = true;
			} elseif ( 0 !== $max && $contact->lead_score < $min ) {
				// A maximum has been set, and Visitor has lead score less than the minimum (ignoring maximum)
				$maybe_remove = true;
			} elseif ( 0 !== $max && $contact->lead_score >= $max ) {
				// A maximum has been set, and Visitor has lead score greater than the maximum (ignoring minimum)
				$maybe_remove = true;
			}

			if ( $maybe_add && ! $maybe_remove ) {
				// Only add if not also removing.
				$this->assign_contact_to_segment( $segment['ID'], $contact->ID );
			} elseif ( $maybe_remove ) {
				// Removing always takes priority over adding.
				// Check against the Visitors segments, as only remove if already added.
				$visitor_segments = $contact->segments;
				if ( ! empty( $visitor_segments ) ) {
					$visitor_segment_ids = wp_list_pluck( $visitor_segments, 'ID' );
					if ( in_array( $segment['ID'], $visitor_segment_ids, true ) ) {
						$this->remove_contact_from_segment( $segment['ID'], $contact->ID );
					}
				}
			}
		}
	}
}
