<?php

namespace Sitecake;

/**
 * File-based key/value cache — replaces cache/filesystem-adapter + FilesystemCachePool.
 *
 * Data is serialized to individual files in $cacheDir.
 */
class Cache
{
    protected string $cacheDir;

    public function __construct(string $cacheDir)
    {
        $this->cacheDir = rtrim($cacheDir, '/\\');
    }

    protected function cacheFile(string $key): string
    {
        return $this->cacheDir . DIRECTORY_SEPARATOR . md5($key) . '.cache';
    }

    protected function ensureDir(): void
    {
        if (!is_dir($this->cacheDir)) {
            mkdir($this->cacheDir, 0755, true);
        }
    }

    /**
     * Initialise cache from an array of key => value pairs (used for migration from old cache).
     *
     * @param array $initialData
     */
    public function initCache(array $initialData = []): void
    {
        foreach ($initialData as $key => $value) {
            if (!$this->has($key)) {
                $this->save($key, $value);
            }
        }
    }

    /**
     * Get a cached value; returns $default if not found.
     *
     * @param string $key
     * @param mixed  $default
     * @return mixed
     */
    public function get(string $key, $default = null)
    {
        $file = $this->cacheFile($key);
        if (!file_exists($file)) {
            return $default;
        }
        $raw = file_get_contents($file);
        if ($raw === false) {
            return $default;
        }
        $value = @unserialize($raw);
        return $value === false && $raw !== serialize(false) ? $default : $value;
    }

    /**
     * Check whether a key exists in the cache.
     */
    public function has(string $key): bool
    {
        return file_exists($this->cacheFile($key));
    }

    /**
     * Save a value under $key.
     *
     * @param string $key
     * @param mixed  $value
     * @return bool
     */
    public function save(string $key, $value): bool
    {
        $this->ensureDir();
        return file_put_contents($this->cacheFile($key), serialize($value)) !== false;
    }

    // ------------------------------------------------------------------
    // Convenience helpers (preserve existing public API)
    // ------------------------------------------------------------------

    /** Save the lastPublished timestamp. */
    public function saveLastPublished(): void
    {
        $this->save('lastPublished', time());
    }

    /** Mark a draft path as dirty (unpublished). */
    public function markPathDirty(string $path): void
    {
        $unpublished = $this->get('unpublished', []);
        if (array_search($path, $unpublished) === false) {
            $unpublished[] = $path;
            $this->save('unpublished', $unpublished);
        }
    }

    /** Return all unpublished draft paths. */
    public function getUnpublishedPaths(): array
    {
        return $this->get('unpublished', []);
    }
}
