<?php

declare(strict_types=1);

namespace App\Framework\LiveComponents\Contracts;

use App\Framework\Core\ValueObjects\Duration;
use App\Framework\LiveComponents\Caching\VaryBy;

/**
 * Interface for LiveComponents that support caching
 *
 * Components implementing this interface can cache their rendered output
 * and state to improve performance for expensive operations.
 *
 * Advanced Features:
 * - varyBy: Cache key variations based on context (user, locale, etc.)
 * - Stale-While-Revalidate: Serve stale content while refreshing
 * - Tags: Grouped cache invalidation
 */
interface Cacheable
{
    /**
     * Get cache key for this component
     *
     * The cache key should uniquely identify this component's state.
     * Include dynamic data that affects rendering.
     *
     * Note: This is the base key. VaryBy will add context-based suffixes.
     *
     * @return string Unique cache key
     */
    public function getCacheKey(): string;

    /**
     * Get cache TTL (Time To Live)
     *
     * @return Duration How long to cache this component
     */
    public function getCacheTTL(): Duration;

    /**
     * Check if component should be cached
     *
     * Allows dynamic cache control based on state or conditions.
     *
     * @return bool True if component should be cached
     */
    public function shouldCache(): bool;

    /**
     * Get cache tags for invalidation
     *
     * Tags allow invalidating multiple cached components at once.
     *
     * @return array<string> List of cache tags
     */
    public function getCacheTags(): array;

    /**
     * Get varyBy specification for cache key generation
     *
     * Defines which context factors should vary the cache key.
     * Return null for global cache (no context variation).
     *
     * Examples:
     * - VaryBy::userId() - Cache per user
     * - VaryBy::locale() - Cache per language
     * - VaryBy::userAndLocale() - Cache per user and language
     * - VaryBy::custom(['device_type']) - Custom variations
     *
     * @return VaryBy|null VaryBy specification or null for global cache
     */
    public function getVaryBy(): ?VaryBy;

    /**
     * Get Stale-While-Revalidate (SWR) duration
     *
     * If set, stale content will be served while background refresh happens.
     * This improves perceived performance for expensive components.
     *
     * Example: TTL = 5 minutes, SWR = 1 hour
     * - 0-5min: Serve fresh cache
     * - 5min-1h: Serve stale cache + trigger background refresh
     * - >1h: Force fresh render
     *
     * @return Duration|null SWR duration or null to disable
     */
    public function getStaleWhileRevalidate(): ?Duration;
}
