<?php

declare(strict_types=1);

namespace App\Framework\Cache;

use App\Framework\Core\ValueObjects\Duration;

final readonly class CacheItem
{
    private function __construct(
        public CacheKey                                  $key,
        public mixed                                     $value,
        public bool                                      $isHit = false,
        public ?Duration                                 $ttl = null,
    ) {
    }

    public static function miss(CacheKey $key): self
    {
        return new self(key: $key, value: null, isHit: false, ttl: null);
    }

    public static function hit(CacheKey $key, mixed $value, ?Duration $ttl = null): self
    {
        return new self(key: $key, value: $value, isHit: true, ttl: $ttl);
    }

    /**
     * Create a cache item for setting (not from cache retrieval)
     */
    public static function forSet(CacheKey $key, mixed $value, ?Duration $ttl = null): self
    {
        return new self(
            key: $key,
            value: $value,
            ttl: $ttl
        );
    }

    public static function fromValues(string $key, mixed $value, int|Duration|null $ttl = null): self
    {
        return new self(
            key  : CacheKey::fromString($key),
            value: $value,
            ttl  : $ttl instanceof Duration ? $ttl : Duration::fromSeconds($ttl),
        );
    }

    /**
     * Check if this item has a TTL set
     */
    public function hasTtl(): bool
    {
        return $this->ttl !== null;
    }

    /**
     * Create a new cache item with different TTL
     */
    public function withTtl(?Duration $ttl): self
    {
        return new self($this->key, $this->value, $this->isHit, $ttl);
    }

    /**
     * Create a new cache item with different value
     */
    public function withValue(mixed $value): self
    {
        return new self($this->key, $value, $this->isHit, $this->ttl);
    }
}
