<?php

declare(strict_types=1);

namespace App\Framework\LiveComponents\Cache;

use App\Framework\Cache\CacheKey;
use App\Framework\LiveComponents\ValueObjects\ComponentId;

/**
 * Component Cache Key Value Object
 *
 * Generates cache keys for LiveComponent caching with proper namespacing.
 *
 * Key Format: "livecomponent:{type}:{componentId}:{suffix}"
 *
 * Examples:
 * - "livecomponent:state:comp-123:v1"
 * - "livecomponent:slot:comp-123:header"
 * - "livecomponent:template:card:default"
 */
final readonly class ComponentCacheKey
{
    private const PREFIX = 'livecomponent';

    private function __construct(
        private string $type,
        private string $identifier,
        private string $suffix = ''
    ) {
    }

    /**
     * Create cache key for component state
     */
    public static function forState(ComponentId $componentId, string $stateHash): self
    {
        return new self(
            type: 'state',
            identifier: $componentId->toString(),
            suffix: $stateHash
        );
    }

    /**
     * Create cache key for slot content
     */
    public static function forSlot(ComponentId $componentId, string $slotName): self
    {
        return new self(
            type: 'slot',
            identifier: $componentId->toString(),
            suffix: $slotName
        );
    }

    /**
     * Create cache key for template fragment
     */
    public static function forTemplate(string $componentType, string $variant = 'default'): self
    {
        return new self(
            type: 'template',
            identifier: $componentType,
            suffix: $variant
        );
    }

    /**
     * Create cache key for rendered output
     */
    public static function forRenderedOutput(ComponentId $componentId, string $stateHash): self
    {
        return new self(
            type: 'rendered',
            identifier: $componentId->toString(),
            suffix: $stateHash
        );
    }

    /**
     * Create cache key for component metadata
     */
    public static function forMetadata(string $componentType): self
    {
        return new self(
            type: 'metadata',
            identifier: $componentType,
            suffix: ''
        );
    }

    /**
     * Get cache key as string
     */
    public function toString(): string
    {
        $parts = [self::PREFIX, $this->type, $this->identifier];

        if (! empty($this->suffix)) {
            $parts[] = $this->suffix;
        }

        return implode(':', $parts);
    }

    /**
     * Convert to framework CacheKey
     */
    public function toCacheKey(): CacheKey
    {
        return CacheKey::fromString($this->toString());
    }

    /**
     * Get cache key type
     */
    public function getType(): string
    {
        return $this->type;
    }

    /**
     * Get identifier part
     */
    public function getIdentifier(): string
    {
        return $this->identifier;
    }

    /**
     * Get suffix part
     */
    public function getSuffix(): string
    {
        return $this->suffix;
    }

    /**
     * Check if this key matches a pattern
     */
    public function matches(string $pattern): bool
    {
        return fnmatch($pattern, $this->toString());
    }

    /**
     * Get wildcard pattern for invalidation
     */
    public static function wildcardForComponent(ComponentId $componentId): string
    {
        return self::PREFIX . ':*:' . $componentId->toString() . ':*';
    }

    /**
     * Get wildcard pattern for type
     */
    public static function wildcardForType(string $type): string
    {
        return self::PREFIX . ':' . $type . ':*';
    }
}
