<?php

declare(strict_types=1);

namespace Archive\Archived;


final readonly class CacheCapability
{
    public function __construct(
        public bool $canBeCachedFully,
        public bool $canBeCachedPartially,
        public bool $supportsFragments,
        public CacheComplexity $complexity,
        public array $restrictions = [],
    ) {}

    public static function fromTemplateContent(TemplateContent $content): self
    {
        $canBeCachedFully = !$content->hasDynamicContent();

        $canBeCachedPartially = !$content->hasUserSpecificContent
            && !$content->hasSessionData
            && !$content->hasTimeBasedContent;

        $supportsFragments = count($content->staticBlocks) > 0;

        $complexity = match (true) {
            !$content->hasDynamicContent() => CacheComplexity::LOW,
            $content->hasUserSpecificContent || $content->hasSessionData => CacheComplexity::HIGH,
            $content->hasFormElements || $content->hasTimeBasedContent => CacheComplexity::MEDIUM,
            default => CacheComplexity::EXTREME,
        };

        $restrictions = [];
        if ($content->hasUserSpecificContent) $restrictions[] = 'user_specific';
        if ($content->hasSessionData) $restrictions[] = 'session_dependent';
        if ($content->hasTimeBasedContent) $restrictions[] = 'time_sensitive';
        if ($content->hasCsrfTokens) $restrictions[] = 'csrf_protected';

        return new self(
            canBeCachedFully: $canBeCachedFully,
            canBeCachedPartially: $canBeCachedPartially,
            supportsFragments: $supportsFragments,
            complexity: $complexity,
            restrictions: $restrictions,
        );
    }

    public function isFullyCacheable(): bool
    {
        return $this->canBeCachedFully;
    }

    public function isPartiallyCacheable(): bool
    {
        return $this->canBeCachedPartially;
    }

    public function getComplexity(): CacheComplexity
    {
        return $this->complexity;
    }

    public function hasRestriction(string $restriction): bool
    {
        return in_array($restriction, $this->restrictions, true);
    }
}
