<?php

namespace App\Framework\View\Caching\Strategies;

use App\Framework\Cache\Cache;
use App\Framework\View\Caching\TemplateContext;

final readonly class FullPageCacheStrategy implements ViewCacheStrategy
{
    public function __construct(private Cache $cache) {}

    public function shouldCache(TemplateContext $context): bool
    {
        // Keine User-spezifischen Daten
        return !$this->hasUserData($context->data) &&
            !$this->hasVolatileData($context->data);
    }

    public function generateKey(TemplateContext $context): string
    {
        return "page:{$context->template}:" . md5(serialize($this->getNonVolatileData($context->data)));
    }

    public function getTtl(TemplateContext $context): int
    {
        return match($this->getPageType($context->template)) {
            'layout' => 3600,      // 1 hour
            'static' => 7200,      // 2 hours
            'content' => 1800,     // 30 minutes
            default => 900         // 15 minutes
        };
    }

    private function hasUserData(array $data): bool
    {
        $userKeys = ['user', 'auth', 'session', 'current_user'];
        return !empty(array_intersect(array_keys($data), $userKeys));
    }

    private function hasVolatileData(array $data): bool
    {
        $volatileKeys = ['csrf_token', '_token', 'flash', 'errors', 'timestamp', 'now'];
        return !empty(array_intersect(array_keys($data), $volatileKeys));
    }

    private function getNonVolatileData(array $data): array
    {
        $volatileKeys = ['csrf_token', '_token', 'flash', 'errors', 'timestamp', 'now', 'user', 'auth', 'session'];
        return array_diff_key($data, array_flip($volatileKeys));
    }

    private function getPageType(string $template): string
    {
        if (str_contains($template, 'layout')) return 'layout';
        if (str_contains($template, 'static')) return 'static';
        if (str_contains($template, 'page')) return 'content';
        return 'default';
    }

    public function canInvalidate(string $template): bool
    {
        return true;
    }
}
