<?php

declare(strict_types=1);

class ThemeManager
{
    private static string $activeTheme = 'simply';
    private static array $themeInfo = [];

    public static function boot(): void
    {
        self::$activeTheme = Setting::get('active_theme', 'simply');

         
         
        if (self::$activeTheme !== 'simply' && !LicenseGuard::isAllowed('theme', self::$activeTheme)) {
            self::$activeTheme = 'simply';
        }

        $jsonPath = self::themePath(self::$activeTheme) . '/theme.json';
        if (file_exists($jsonPath)) {
            self::$themeInfo = json_decode(file_get_contents($jsonPath), true) ?? [];
        }

        $functionsPath = self::themePath(self::$activeTheme) . '/functions.php';
        if (file_exists($functionsPath)) {
            require_once $functionsPath;
        }
    }

    public static function active(): string
    {
        return self::$activeTheme;
    }

    public static function info(string $key = '', mixed $default = null): mixed
    {
        if ($key === '') {
            return self::$themeInfo;
        }
        return self::$themeInfo[$key] ?? $default;
    }

    public static function activate(string $slug): bool
    {
        $path = self::themePath($slug);
        if (!is_dir($path) || !file_exists($path . '/theme.json')) {
            return false;
        }

        if (self::$activeTheme !== $slug) {
            HookSystem::doAction('theme.deactivate', self::$activeTheme);
        }

        Setting::set('active_theme', $slug);

        $existing = Database::fetchOne('SELECT id FROM themes WHERE slug = ?', [$slug]);
        if ($existing) {
            Database::query('UPDATE themes SET is_active = 0 WHERE 1');
            Database::update('themes', ['is_active' => 1], 'slug = ?', [$slug]);
        } else {
            Database::query('UPDATE themes SET is_active = 0 WHERE 1');
            Database::insert('themes', ['slug' => $slug, 'is_active' => 1]);
        }

        self::$activeTheme = $slug;
        return true;
    }

    public static function getAll(): array
    {
        $themes = [];
        $dir = APP_ROOT . '/themes';
        if (!is_dir($dir)) {
            return $themes;
        }

        $dirs = scandir($dir);
        foreach ($dirs as $slug) {
            if ($slug === '.' || $slug === '..') {
                continue;
            }

            $jsonPath = $dir . '/' . $slug . '/theme.json';
            if (!file_exists($jsonPath)) {
                continue;
            }

            $info = json_decode(file_get_contents($jsonPath), true) ?? [];
            $info['slug'] = $slug;
            $info['is_active'] = ($slug === self::$activeTheme);

            $themes[] = $info;
        }

        return $themes;
    }

    public static function themePath(string $slug = ''): string
    {
        $slug = $slug ?: self::$activeTheme;
        if (str_contains($slug, '..') || str_contains($slug, "\0") || !preg_match('/^[a-z0-9_-]+$/i', $slug)) {
            return APP_ROOT . '/themes/simply';
        }
        return APP_ROOT . '/themes/' . $slug;
    }

    public static function templatePath(string $template): string
    {
        if (str_contains($template, '..') || str_contains($template, "\0")) {
            return '';
        }
         
        $path = self::themePath() . '/templates/' . $template . '.php';
        if (file_exists($path)) {
            return $path;
        }

         
        $fallback = self::themePath('simply') . '/templates/' . $template . '.php';
        if (file_exists($fallback)) {
            return $fallback;
        }

        return '';
    }

    public static function assetUrl(string $path): string
    {
        return '/themes/' . self::$activeTheme . '/assets/' . ltrim($path, '/');
    }

    private static array $allowedExtensions = ['php', 'css', 'js', 'json', 'html'];

    public static function listFiles(string $slug = ''): array
    {
        $slug = $slug ?: self::$activeTheme;
        $base = self::themePath($slug);
        if (!is_dir($base)) {
            return [];
        }

        $files = [];
        $iterator = new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator($base, \RecursiveDirectoryIterator::SKIP_DOTS),
            \RecursiveIteratorIterator::SELF_FIRST
        );

        foreach ($iterator as $file) {
            if ($file->isDir()) {
                continue;
            }
            $ext = strtolower($file->getExtension());
            if (!in_array($ext, self::$allowedExtensions)) {
                continue;
            }
            $relativePath = substr($file->getPathname(), strlen($base) + 1);
            $files[] = $relativePath;
        }

        sort($files);
        return $files;
    }

    public static function readFile(string $relativePath, string $slug = ''): ?string
    {
        $slug = $slug ?: self::$activeTheme;
        $base = realpath(self::themePath($slug));
        if (!$base) {
            return null;
        }

        $fullPath = realpath($base . '/' . $relativePath);
        if (!$fullPath || !str_starts_with($fullPath, $base . '/')) {
            return null;
        }

        $ext = strtolower(pathinfo($fullPath, PATHINFO_EXTENSION));
        if (!in_array($ext, self::$allowedExtensions)) {
            return null;
        }

        if (!file_exists($fullPath)) {
            return null;
        }

        return file_get_contents($fullPath);
    }

    public static function writeFile(string $relativePath, string $content, string $slug = ''): bool
    {
        $slug = $slug ?: self::$activeTheme;
        $base = realpath(self::themePath($slug));
        if (!$base) {
            return false;
        }

        $fullPath = realpath($base . '/' . $relativePath);
        if (!$fullPath || !str_starts_with($fullPath, $base . '/')) {
            return false;
        }

        $ext = strtolower(pathinfo($fullPath, PATHINFO_EXTENSION));
        if (!in_array($ext, self::$allowedExtensions)) {
            return false;
        }

        if (!file_exists($fullPath)) {
            return false;
        }

         
        $backupDir = APP_ROOT . '/storage/theme_backups/' . $slug;
        if (!is_dir($backupDir)) {
            mkdir($backupDir, 0755, true);
        }
        $backupFile = $backupDir . '/' . str_replace('/', '_', $relativePath) . '.' . date('Y-m-d_His') . '.bak';
        copy($fullPath, $backupFile);

         
        $tmpFile = $fullPath . '.tmp.' . bin2hex(random_bytes(4));
        $written = file_put_contents($tmpFile, $content, LOCK_EX);
        if ($written === false) {
            @unlink($tmpFile);
            return false;
        }
        if (!rename($tmpFile, $fullPath)) {
            @unlink($tmpFile);
            return false;
        }
        return true;
    }
}
