<?php
/**
 * Per-event-type tracking toggles.
 *
 * @package Carticy\Conversions\Events
 */

declare(strict_types=1);

namespace Carticy\Conversions\Events;

use Carticy\Conversions\Domain\ConversionEventType;

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

/**
 * Option-backed enable/disable switches for the canonical event types the
 * Settings · Events tab exposes (purchase, refund, subscription renewal).
 *
 * The gate sits at canonical-event CREATION in {@see OrderEventService}: a
 * disabled type records no event and queues no dispatch, which also keeps the
 * browser layer silent (order-received hydration replays only stored events).
 * Disabling `renewal` must never reroute renewals into the purchase path - the
 * renewal-order exclusion in the purchase hooks is independent of these toggles.
 */
final class EventToggles {

	/**
	 * Option storing the toggle map.
	 */
	public const OPTION_NAME = 'carticy_conversions_event_toggles';

	/**
	 * Event types the merchant may toggle.
	 */
	public const TOGGLEABLE = array(
		ConversionEventType::PURCHASE,
		ConversionEventType::REFUND,
		ConversionEventType::RENEWAL,
	);

	/**
	 * Whether an event type is enabled (default on - absence never disables).
	 *
	 * @param string $event_type Canonical event type.
	 * @return bool
	 */
	public function enabled( string $event_type ): bool {
		$event_type = sanitize_key( $event_type );
		if ( ! in_array( $event_type, self::TOGGLEABLE, true ) ) {
			return true;
		}

		$map = $this->to_array();

		return ! empty( $map[ $event_type ] );
	}

	/**
	 * Read the normalized toggle map.
	 *
	 * @return array<string, bool>
	 */
	public function to_array(): array {
		$stored = get_option( self::OPTION_NAME, array() );
		$stored = is_array( $stored ) ? $stored : array();

		$map = array();
		foreach ( self::TOGGLEABLE as $type ) {
			$map[ $type ] = array_key_exists( $type, $stored ) ? ! empty( $stored[ $type ] ) : true;
		}

		return $map;
	}

	/**
	 * Persist a partial toggle patch, returning the applied map.
	 *
	 * @param array<string, mixed> $patch Toggle values keyed by event type.
	 * @return array<string, bool>
	 */
	public function apply( array $patch ): array {
		$current = $this->to_array();
		foreach ( self::TOGGLEABLE as $type ) {
			if ( array_key_exists( $type, $patch ) ) {
				$current[ $type ] = ! empty( $patch[ $type ] );
			}
		}

		update_option( self::OPTION_NAME, $current );

		return $current;
	}
}
