<?php

namespace App\Cache;

namespace App\Cache;

use Illuminate\Support\Facades\Cache;
use App\Cache\Contracts\Cacheable;

abstract class BaseCacheable implements Cacheable
{
    abstract public function key(): string;

    abstract public function ttl(): ?int;

    abstract public function forever(): bool;

    abstract public function resolve(): mixed;

    public function tags(): array
    {
        return [];
    }

    protected function cacheStore()
    {
        $store = Cache::store();
        $supportsTags = in_array(config('cache.default'), ['redis', 'memcached']);

        if (!empty($this->tags()) && $supportsTags) {
            return Cache::tags($this->tags());
        }

        return $store;
    }

    public function get(): mixed
    {
        $store = $this->cacheStore();

        if ($this->forever()) {
            return $store->rememberForever($this->key(), fn() => $this->resolve());
        }

        return $store->remember($this->key(), $this->ttl(), fn() => $this->resolve());
    }

    public function refresh(): mixed
    {
        $data = $this->resolve();
        $store = $this->cacheStore();

        if ($this->forever()) {
            $store->forever($this->key(), $data);
        } else {
            $store->put($this->key(), $data, $this->ttl());
        }

        return $data;
    }

    public function clear(): bool
    {
        return $this->cacheStore()->forget($this->key());
    }
}
