<?php

declare(strict_types=1);

namespace App\Support;

use App\Models\SystemSetting;
use Hypervel\Support\Facades\Config;
use Throwable;

/**
 * Helper for checking module enable/disable status.
 *
 * Resolution order (highest priority first):
 *   1. SystemSetting override (key: "module_states_override", JSON map)
 *   2. config/modules.php (env-driven defaults)
 *
 * The DB-backed override allows the Ultimate Console to toggle modules at
 * runtime without redeploying / changing env vars.
 */
class ModuleHelper
{
    /**
     * SystemSetting key that holds the per-module override map.
     */
    public const OVERRIDE_KEY = 'module_states_override';

    public static function isSystemEnabled(): bool
    {
        return (bool) Config::get('modules.system_enabled', true);
    }

    public static function isEnabled(string $moduleKey): bool
    {
        if (!static::isSystemEnabled()) {
            return true;
        }

        $overrides = static::getOverrides();
        if (array_key_exists($moduleKey, $overrides)) {
            return (bool) $overrides[$moduleKey];
        }

        return (bool) Config::get("modules.{$moduleKey}.enabled", true);
    }

    public static function isDisabled(string $moduleKey): bool
    {
        return !static::isEnabled($moduleKey);
    }

    public static function getLabel(string $moduleKey): string
    {
        return Config::get("modules.{$moduleKey}.label", ucfirst($moduleKey));
    }

    /**
     * Get all module statuses including the effective enabled state, the
     * config/env default, and the override value (if any).
     *
     * Returns: ['key' => [
     *     'enabled' => bool,           // effective state
     *     'config_default' => bool,    // env / config value
     *     'override' => bool|null,     // SystemSetting override (null if none)
     *     'label' => string,
     *     'description' => string,
     * ], ...]
     */
    public static function getAllModules(): array
    {
        $modules = Config::get('modules', []);
        $overrides = static::getOverrides();
        $result = [];

        foreach ($modules as $key => $config) {
            if (!is_array($config)) {
                // Skips scalar entries like 'system_enabled'.
                continue;
            }

            $configDefault = (bool) ($config['enabled'] ?? true);
            $hasOverride = array_key_exists($key, $overrides);
            $override = $hasOverride ? (bool) $overrides[$key] : null;

            $result[$key] = [
                'enabled'        => $hasOverride ? $override : $configDefault,
                'config_default' => $configDefault,
                'override'       => $override,
                'label'          => $config['label'] ?? ucfirst($key),
                'description'    => $config['description'] ?? '',
            ];
        }

        return $result;
    }

    /**
     * Get only the effective enabled/disabled states.
     *
     * @return array<string, bool>
     */
    public static function getModuleStates(): array
    {
        $states = [];
        foreach (static::getAllModules() as $key => $info) {
            $states[$key] = (bool) $info['enabled'];
        }
        return $states;
    }

    /**
     * Read the override map from SystemSetting (cached).
     *
     * @return array<string, bool>
     */
    protected static function getOverrides(): array
    {
        try {
            $value = SystemSetting::getValue(static::OVERRIDE_KEY);
        } catch (Throwable $e) {
            return [];
        }

        if (is_string($value) && $value !== '') {
            $decoded = json_decode($value, true);
            $value = is_array($decoded) ? $decoded : [];
        }

        if (!is_array($value)) {
            return [];
        }

        $out = [];
        foreach ($value as $k => $v) {
            $out[(string) $k] = filter_var($v, FILTER_VALIDATE_BOOLEAN);
        }
        return $out;
    }
}
