<?php

declare(strict_types=1);

namespace App\Modules\Theme;

/**
 * ThemeRegistry -- Scans the /themes directory and returns all valid themes.
 *
 * Responsibilities:
 *   - Scan ROOT_PATH/themes/ for subdirectories.
 *   - Locate theme.json inside each subdirectory.
 *   - Return a map of theme_code => manifest array.
 *
 * No SQL. No caching. Lightweight filesystem scan only.
 *
 * @package Inveetaire
 * @ref     RC-009
 */
class ThemeRegistry
{
    /** @var string Absolute path to the themes root directory. */
    private string $themesPath;

    /** @var ThemeManifest */
    private ThemeManifest $manifest;

    public function __construct()
    {
        $this->themesPath = ROOT_PATH . '/themes';
        $this->manifest   = new ThemeManifest();
    }

    /**
     * Scan the themes directory and return all discovered, valid themes.
     *
     * @return array<string, array> Map of theme_code => manifest data.
     *                              Empty array if no valid themes found.
     */
    public function getAvailableThemes(): array
    {
        $themes = [];

        if (!is_dir($this->themesPath)) {
            return $themes;
        }

        $entries = scandir($this->themesPath);
        if ($entries === false) {
            return $themes;
        }

        foreach ($entries as $entry) {
            if ($entry === '.' || $entry === '..') {
                continue;
            }

            $themeDir = $this->themesPath . DIRECTORY_SEPARATOR . $entry;

            if (!is_dir($themeDir)) {
                continue;
            }

            $manifestPath = $themeDir . DIRECTORY_SEPARATOR . 'theme.json';
            $parsed = $this->manifest->parse($manifestPath);

            if ($parsed === null) {
                continue;
            }

            $themes[$parsed['code']] = $parsed;
        }

        return $themes;
    }

    /**
     * Check if a given theme code exists in the registry.
     *
     * @param string $themeCode
     * @return bool
     */
    public function themeExists(string $themeCode): bool
    {
        $available = $this->getAvailableThemes();
        return isset($available[$themeCode]);
    }

    /**
     * Return the absolute path to a theme folder by its code.
     *
     * @param string $themeCode
     * @return string|null Absolute path or null if not found.
     */
    public function getThemePath(string $themeCode): ?string
    {
        $available = $this->getAvailableThemes();
        if (!isset($available[$themeCode])) {
            return null;
        }
        return $this->themesPath . DIRECTORY_SEPARATOR . $themeCode;
    }
}