import 'package:flutter/material.dart'; import '../../../core/network/api_client.dart'; import '../../../core/theme/app_theme.dart'; import '../../../core/widgets/glass_container.dart'; import '../../../core/widgets/status_badge.dart'; import '../models/service_setting_dto.dart'; import '../repositories/admin_repository.dart'; import '../widgets/live_log_console.dart'; class ServiceDetailScreen extends StatefulWidget { final String serviceName; final ApiClient apiClient; final AdminRepository? repository; const ServiceDetailScreen({ super.key, required this.serviceName, required this.apiClient, this.repository, }); @override State createState() => _ServiceDetailScreenState(); } class _ServiceDetailScreenState extends State { late final AdminRepository _repository; bool _isLoading = true; bool _isSaving = false; String _error = ''; List _settings = []; final Map _controllers = {}; @override void initState() { super.initState(); _repository = widget.repository ?? AdminRepository(apiClient: widget.apiClient); _fetchServiceDetails(); } @override void dispose() { for (var ctrl in _controllers.values) { ctrl.dispose(); } super.dispose(); } Future _fetchServiceDetails() async { try { final groupedSettings = await _repository.fetchSettings(); final serviceSettings = groupedSettings[widget.serviceName] ?? []; setState(() { _settings = serviceSettings; for (var s in _settings) { final key = s.key; final val = s.value; if (!_controllers.containsKey(key)) { _controllers[key] = TextEditingController(text: val); } else { _controllers[key]!.text = val; } } _isLoading = false; }); } catch (e) { setState(() { _error = e.toString(); _isLoading = false; }); } } Future _saveSettings() async { setState(() => _isSaving = true); try { final payload = {}; _controllers.forEach((k, v) { final text = v.text.trim(); if (text.toLowerCase() == 'true') { payload[k] = true; } else if (text.toLowerCase() == 'false') { payload[k] = false; } else if (int.tryParse(text) != null) { payload[k] = int.parse(text); } else if (double.tryParse(text) != null) { payload[k] = double.parse(text); } else { payload[k] = text; } }); await _repository.updateServiceSettings(widget.serviceName, payload); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ const Icon(Icons.check_circle_outline, color: Colors.black), const SizedBox(width: 8), Expanded( child: Text( 'Einstellungen für ${widget.serviceName} gespeichert & via MQTT synchronisiert.', style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w600), ), ), ], ), backgroundColor: AppTheme.primaryEmerald, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), ), ); } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Fehler beim Speichern: $e'), backgroundColor: AppTheme.accentRed, behavior: SnackBarBehavior.floating, ), ); } } finally { if (mounted) setState(() => _isSaving = false); } } String _formatLabel(String key) { return key .replaceAll(RegExp(r'(? setState(() => controller.text = val.toString()), ), ); } final isNumeric = type == 'int' || type == 'double' || type == 'number' || type == 'decimal'; return Padding( padding: const EdgeInsets.only(bottom: 14), child: TextField( controller: controller, keyboardType: isNumeric ? const TextInputType.numberWithOptions(decimal: true) : TextInputType.text, style: const TextStyle(color: Colors.white), decoration: InputDecoration( labelText: _formatLabel(key), helperText: desc.isNotEmpty ? desc : null, helperMaxLines: 2, prefixIcon: Icon( isNumeric ? Icons.numbers_outlined : Icons.tune_outlined, size: 18, color: AppTheme.primaryEmerald, ), ), ), ); }).toList(), const SizedBox(height: 12), if (_settings.isNotEmpty) SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: _isSaving ? null : _saveSettings, icon: _isSaving ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.black)) : const Icon(Icons.save_outlined), label: Text( _isSaving ? 'Speichere & Sende via MQTT...' : 'Einstellungen Speichern', style: const TextStyle(fontWeight: FontWeight.bold), ), style: ElevatedButton.styleFrom( backgroundColor: AppTheme.primaryEmerald, foregroundColor: Colors.black, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), ), ), ], ), ), const SizedBox(height: 24), LiveLogConsole( serviceName: widget.serviceName, apiClient: widget.apiClient, ), const SizedBox(height: 24), GlassContainer( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Statistiken', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(height: 16), const Text('Live-Statistiken werden noch implementiert...', style: TextStyle(fontStyle: FontStyle.italic, color: Colors.white54)), ], ), ), ], ), ), ); } }