<?php

namespace Lcmigrator\LcMigrator\OptionManager;

use Lcmigrator\LcMigrator\Logger\Logger;

class OptionManager {
    private string $optionName;
    private array $options;
    private static ?OptionManager $instance = null;
    private static array $instances = [];
    private static array $optionChangeListeners = [];
    
    private function __construct(string $optionName = LC_MIGRATOR_OPTION_NAME) {
        $this->optionName = $optionName;
        $this->loadOptions();
        
        // Add hook to WordPress option update action
        add_action("update_option_{$this->optionName}", [$this, 'handleExternalOptionUpdate'], 10, 3);
        add_action("delete_option_{$this->optionName}", [$this, 'handleExternalOptionDelete'], 10, 1);
    }

    public static function getInstance(string $optionName = LC_MIGRATOR_OPTION_NAME): OptionManager {
        if (!isset(self::$instances[$optionName])) {
            self::$instances[$optionName] = new self($optionName);
        }
        return self::$instances[$optionName];
    }

    private function loadOptions(): void {
        // Always get fresh value from database without caching
        $options = get_option($this->optionName, '{}'); 
        $this->options = json_decode($options, true) ?: [];
    }

    private function saveOptions(): bool {
        $result = update_option($this->optionName, json_encode($this->options));
        $this->notifyAllInstances();
        return $result === true;
    }

    private function notifyAllInstances(): void {
        // Refresh all instances that share this option name
        foreach (self::$instances as $instance) {
            if ($instance->optionName === $this->optionName && $instance !== $this) {
                $instance->refresh();
            }
        }
    }

    public function handleExternalOptionUpdate($oldValue, $value, $optionName): void {
        if ($optionName === $this->optionName) {
            $this->refresh();
            $this->notifyAllInstances();
        }
    }

    public function handleExternalOptionDelete($optionName): void {
        if ($optionName === $this->optionName) {
            $this->refresh();
            $this->notifyAllInstances();
        }
    }

    public function get(string $key, $default = null) {
        // Always refresh before getting to ensure latest value
        $this->refresh();
        return $this->options[$key] ?? $default;
    }

    public function set(string $key, $value): bool {
        $this->options[$key] = $value;
        return $this->saveOptions();
    }

    public function setMultiple(array $options): bool {
        foreach ($options as $key => $value) {
            $this->options[$key] = $value;
        }
        return $this->saveOptions();
    }

    public function remove(string $key): bool {
        if (isset($this->options[$key])) {
            unset($this->options[$key]);
            return $this->saveOptions();
        }
        return false;
    }

    public function has(string $key): bool {
        // Always refresh before checking to ensure latest value
        $this->refresh();
        return isset($this->options[$key]);
    }

    public function all(): array {
        // Always refresh before getting all to ensure latest values
        $this->refresh();
        return $this->options;
    }

    public function clear(): bool {
        $result = delete_option($this->optionName);
        $this->notifyAllInstances();
        return $result;
    }

    public function refresh(): void {
        $this->loadOptions();
    }
}
