<?php
/**
 * Provider health-status cache port.
 *
 * Phase 9 cache surface for {@see \Affilun\Domain\Provider\ProviderHealthStatus}
 * snapshots produced by provider health probes, keyed by the
 * canonical provider-health key produced by
 * {@see \Affilun\Application\Cache\CacheKeyFactory::providerHealthKey()}.
 * Implementations back the cache layer described in
 * `specifications/sync-and-cache-strategy.md` §4 (cache layers)
 * and §6.3 (cache-key forms).
 *
 * Unlike the search / lookup / render layers, this cache stores
 * a typed Domain value object verbatim — callers receive the
 * exact {@see \Affilun\Domain\Provider\ProviderHealthStatus}
 * instance back on hit so downstream surfaces can branch on the
 * §7.10 status tokens without re-parsing an associative array.
 *
 * Eviction is TTL-driven: writes carry an explicit TTL in
 * seconds; reads return null on miss or once the entry's TTL
 * has elapsed. The clock used to apply the TTL is wired into
 * the implementation (typically a
 * {@see \Affilun\Domain\Clock}), not into this
 * port, so consumers do not have to thread "now" through every
 * call.
 *
 * @package Affilun\Application\Cache
 */

declare(strict_types=1);

namespace Affilun\Application\Cache;

use Affilun\Domain\Provider\ProviderHealthStatus;
use InvalidArgumentException;

/**
 * Phase 9 provider health-status cache contract.
 *
 * See the file-level docblock for the spec citations, the
 * typed-value semantics, and the TTL semantics that gate
 * {@see self::get()} hits.
 */
interface ProviderHealthCache {

	/**
	 * Read the {@see ProviderHealthStatus} stored under `$key`.
	 *
	 * Returns null on miss, on expiry, or when the implementation
	 * has had its layer flushed since the entry was written.
	 *
	 * @param string $key Cache key, typically produced by
	 *                    {@see CacheKeyFactory::providerHealthKey()}.
	 */
	public function get( string $key ): ?ProviderHealthStatus;

	/**
	 * Write the {@see ProviderHealthStatus} under `$key` with the
	 * given TTL in seconds.
	 *
	 * Implementations MUST reject `$ttlSeconds <= 0` with
	 * {@see \InvalidArgumentException}; a non-positive TTL has no
	 * meaningful semantics for this layer.
	 *
	 * @param string               $key        Cache key.
	 * @param ProviderHealthStatus $status     Health snapshot to store.
	 * @param int                  $ttlSeconds TTL in seconds; must be > 0.
	 *
	 * @throws InvalidArgumentException When `$ttlSeconds` is non-positive.
	 */
	public function put( string $key, ProviderHealthStatus $status, int $ttlSeconds ): void;

	/**
	 * Remove the entry stored under `$key`.
	 *
	 * Idempotent: a call against an unknown key is a no-op.
	 *
	 * @param string $key Cache key.
	 */
	public function forget( string $key ): void;

	/**
	 * Drop every entry stored in this cache layer.
	 *
	 * Scope is the layer instance, not the underlying store; if
	 * an implementation shares storage with another layer, the
	 * shared backend MUST still partition entries so flushing
	 * one layer does not also drop a sibling layer's entries.
	 */
	public function flush(): void;
}
