<?php

namespace App\Services;

use App\Models\Setting;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\File;

class ThemeManager
{
    private const CACHE_KEY = 'theme_active';
    private const CACHE_TTL = 3600;
    private const SETTING_KEY = 'active_theme';
    private const DEFAULT_THEME = 'default';

    private string $themesPath;

    public function __construct()
    {
        $this->themesPath = resource_path('themes');
    }

    /**
     * Get the active theme name.
     * Fallback: settings → 'default' → first available theme
     */
    public function getActive(): string
    {
        return Cache::remember(self::CACHE_KEY, self::CACHE_TTL, function () {
            try {
                $theme = Setting::get(self::SETTING_KEY, self::DEFAULT_THEME);
            } catch (\Exception $e) {
                $theme = self::DEFAULT_THEME;
            }

            // If the configured theme exists, use it
            if ($this->exists($theme)) {
                return $theme;
            }

            // Fallback to default
            if ($theme !== self::DEFAULT_THEME && $this->exists(self::DEFAULT_THEME)) {
                return self::DEFAULT_THEME;
            }

            // Last resort: first available theme
            return $this->getFirstAvailable() ?? self::DEFAULT_THEME;
        });
    }

    /**
     * Get the first available theme name.
     */
    private function getFirstAvailable(): ?string
    {
        if (!File::isDirectory($this->themesPath)) {
            return null;
        }

        foreach (File::directories($this->themesPath) as $path) {
            $name = basename($path);
            if ($this->exists($name)) {
                return $name;
            }
        }

        return null;
    }

    /**
     * Activate a theme.
     */
    public function activate(string $theme): void
    {
        if (!$this->exists($theme)) {
            throw new \InvalidArgumentException("Theme '{$theme}' does not exist.");
        }

        Setting::set(self::SETTING_KEY, $theme);
        Cache::forget(self::CACHE_KEY);
    }

    /**
     * Check if a theme exists.
     */
    public function exists(string $theme): bool
    {
        return File::isDirectory($this->getThemePath($theme))
            && File::exists($this->getThemePath($theme) . '/theme.json');
    }

    /**
     * Get theme directory path.
     */
    public function getThemePath(string $theme): string
    {
        return $this->themesPath . '/' . $theme;
    }

    /**
     * Get theme views path.
     */
    public function getViewsPath(string $theme): string
    {
        return $this->getThemePath($theme) . '/views';
    }

    /**
     * Get theme config from theme.json.
     */
    public function getConfig(string $theme): array
    {
        $path = $this->getThemePath($theme) . '/theme.json';

        if (!File::exists($path)) {
            return [];
        }

        return json_decode(File::get($path), true) ?? [];
    }

    /**
     * Get all available themes.
     */
    public function getThemes(): Collection
    {
        if (!File::isDirectory($this->themesPath)) {
            return collect();
        }

        return collect(File::directories($this->themesPath))
            ->map(function ($path) {
                $name = basename($path);
                $config = $this->getConfig($name);

                if (empty($config)) {
                    return null;
                }

                return array_merge($config, [
                    'name' => $name,
                    'path' => $path,
                    'active' => $this->getActive() === $name,
                    'screenshot_url' => $this->getScreenshotUrl($name, $config),
                ]);
            })
            ->filter()
            ->values();
    }

    /**
     * Get CSS assets for the active theme.
     */
    public function getAssets(?string $theme = null): array
    {
        $theme = $theme ?? $this->getActive();
        $config = $this->getConfig($theme);

        $css = [];
        $js = [];

        foreach ($config['css'] ?? [] as $file) {
            $css[] = '/assets/themes/' . $theme . '/' . $file;
        }

        foreach ($config['js'] ?? [] as $file) {
            $js[] = '/assets/themes/' . $theme . '/' . $file;
        }

        return ['css' => $css, 'js' => $js];
    }

    /**
     * Get the parent theme name (for cascading).
     */
    public function getParent(string $theme): ?string
    {
        $config = $this->getConfig($theme);

        return $config['parent'] ?? null;
    }

    /**
     * Get screenshot URL for a theme.
     */
    private function getScreenshotUrl(string $theme, array $config): ?string
    {
        $screenshot = $config['screenshot'] ?? 'screenshot.png';
        $path = $this->getThemePath($theme) . '/' . $screenshot;

        if (File::exists($path)) {
            return '/assets/themes/' . $theme . '/' . $screenshot;
        }

        return null;
    }
}
