<?php

namespace CouponsPlus\App\Coupon;

/**
 * Unfortunately a singleton until we migrate to our newer framework with dependency injection
 */
class RequestCache {

    private static $instance;
    private static $enabled = true;
    private $cache = [];

    private function __construct() {
        // Private constructor to prevent direct instantiation
    }

    /**
     * Get the singleton instance
     */
    public static function getInstance(): self
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Enable or disable caching
     */
    public static function setEnabled(bool $enabled): void
    {
        if ($enabled === false) {
            static::getInstance()->clear(); // Clear cache when disabling
        }
        self::$enabled = $enabled;
    }

    /**
     * Check if caching is enabled
     */
    public static function isEnabled(): bool
    {
        return self::$enabled;
    }

    /**
     * Set a value in the cache (only set once)
     */
    public function set($key, $value) {
        if (!self::isEnabled()) {
            // When disabled, always set the value (don't check if it exists)
            $this->cache[$key] = $value;
            return;
        }

        if (!isset($this->cache[$key])) {
            $this->cache[$key] = $value;
        }
    }

    /**
     * Get a value from the cache
     */
    public function get($key) {
        return $this->cache[$key] ?? null;
    }

    /**
     * Get value if exists, otherwise execute callback to get and store the value
     */
    public function getOrSet($key, $callback) {
        if (!self::isEnabled()) {
            // When disabled, always execute callback and store the fresh value
            $this->cache[$key] = $callback();
        } else {
            // it is enabled!
            if (!isset($this->cache[$key])) {
                $this->cache[$key] = $callback();
            }
        }


        return $this->cache[$key];
    }

    /**
     * Check if a key exists in the cache
     */
    public function has($key): bool
    {
        return isset($this->cache[$key]);
    }

    /**
     * Clear all cache or specific key
     */
    public function clear($key = null) {
        if ($key === null) {
            $this->cache = [];
        } else {
            unset($this->cache[$key]);
        }
    }

    // Prevent cloning
    private function __clone() {}

    // Prevent unserialization
    public function __wakeup() {
        throw new \Exception("Cannot unserialize singleton");
    }
}
