package handlers import ( "encoding/json" "net/http" "os" "sync" ) // SettingsHandler manages system configuration type SettingsHandler struct { mu sync.RWMutex settings map[string]interface{} path string } func NewSettingsHandler() *SettingsHandler { h := &SettingsHandler{ settings: make(map[string]interface{}), path: "/app/config/system.json", } h.load() return h } func (h *SettingsHandler) load() { data, err := os.ReadFile(h.path) if err != nil { // Use defaults h.settings = h.defaultSettings() return } json.Unmarshal(data, &h.settings) } func (h *SettingsHandler) save() error { data, err := json.MarshalIndent(h.settings, "", " ") if err != nil { return err } return os.WriteFile(h.path, data, 0644) } func (h *SettingsHandler) defaultSettings() map[string]interface{} { return map[string]interface{}{ "appearance": map[string]interface{}{ "theme": "light", "density": "comfortable", "sidebar_width": 240, "animations": true, }, "dashboard": map[string]interface{}{ "greeting_enabled": true, "kpi_refresh": 300, "activity_max": 10, }, "notifications": map[string]interface{}{ "in_app": true, "email": false, "slack": false, }, "advanced": map[string]interface{}{ "api_rate_limit": 1000, "cache_ttl": 300, "log_level": "info", "export_max_rows": 10000, }, } } // GetSettings returns all settings func (h *SettingsHandler) GetSettings(w http.ResponseWriter, r *http.Request) { h.mu.RLock() defer h.mu.RUnlock() w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(h.settings) } // UpdateSettings updates settings func (h *SettingsHandler) UpdateSettings(w http.ResponseWriter, r *http.Request) { var updates map[string]interface{} if err := json.NewDecoder(r.Body).Decode(&updates); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } h.mu.Lock() defer h.mu.Unlock() // Merge updates for key, value := range updates { h.settings[key] = value } if err := h.save(); err != nil { writeError(w, http.StatusInternalServerError, "failed to save settings") return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(h.settings) } // GetModuleConfig returns module configuration func (h *SettingsHandler) GetModuleConfig(w http.ResponseWriter, r *http.Request) { module := r.URL.Query().Get("module") if module == "" { writeError(w, http.StatusBadRequest, "module required") return } h.mu.RLock() defer h.mu.RUnlock() modules, ok := h.settings["modules"].(map[string]interface{}) if !ok { writeError(w, http.StatusNotFound, "modules not configured") return } config, ok := modules[module] if !ok { writeError(w, http.StatusNotFound, "module not found") return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(config) } // ToggleModule enables/disables a module func (h *SettingsHandler) ToggleModule(w http.ResponseWriter, r *http.Request) { module := r.URL.Query().Get("module") if module == "" { writeError(w, http.StatusBadRequest, "module required") return } h.mu.Lock() defer h.mu.Unlock() modules, ok := h.settings["modules"].(map[string]interface{}) if !ok { modules = make(map[string]interface{}) h.settings["modules"] = modules } config, ok := modules[module].(map[string]interface{}) if !ok { config = map[string]interface{}{"enabled": false} } // Toggle enabled state if enabled, ok := config["enabled"].(bool); ok { config["enabled"] = !enabled } else { config["enabled"] = true } modules[module] = config if err := h.save(); err != nil { writeError(w, http.StatusInternalServerError, "failed to save") return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(config) } func (h *SettingsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: h.GetSettings(w, r) case http.MethodPut: h.UpdateSettings(w, r) default: writeError(w, http.StatusMethodNotAllowed, "method not allowed") } }