import 'dart:convert'; import 'package:postgres/postgres.dart'; import 'trading_config.dart'; /// Loads and merges [trading_config_templates] with [user_trading_config]. class TradingConfigDb { TradingConfigDb(this._connection); final Connection _connection; Future resolveEffectiveConfig(String firebaseUid) async { final Result result = await _connection.execute( Sql.named( ''' SELECT utc.template_name, utc.config, utc.enabled FROM user_trading_config utc WHERE utc.firebase_uid = @uid ''', ), parameters: {'uid': firebaseUid}, ); if (result.isEmpty) { return null; } final ResultRow row = result.first; final String? templateName = row[0] as String?; final Map userConfig = _readJsonMap(row[1]); final bool userEnabled = row[2]! as bool; Map merged = userConfig; if (templateName != null && templateName.isNotEmpty) { final Map? templateConfig = await _loadTemplateConfig(templateName); if (templateConfig != null) { merged = EffectiveTradingConfig.mergeJson(templateConfig, userConfig); } } return EffectiveTradingConfig.fromJson( merged, templateName: templateName, userEnabled: userEnabled, ); } Future upsertUserConfig({ required String firebaseUid, String? templateName, Map config = const {}, bool enabled = false, }) async { await _connection.execute( Sql.named( ''' INSERT INTO user_trading_config (firebase_uid, template_name, config, enabled) VALUES (@uid, @template_name, @config::jsonb, @enabled) ON CONFLICT (firebase_uid) DO UPDATE SET template_name = EXCLUDED.template_name, config = EXCLUDED.config, enabled = EXCLUDED.enabled, updated_at = now() ''', ), parameters: { 'uid': firebaseUid, 'template_name': templateName, 'config': jsonEncode(config), 'enabled': enabled, }, ); } Future?> _loadTemplateConfig(String name) async { final Result result = await _connection.execute( Sql.named( 'SELECT config FROM trading_config_templates WHERE name = @name', ), parameters: {'name': name}, ); if (result.isEmpty) { return null; } return _readJsonMap(result.first[0]); } Map _readJsonMap(Object? value) { if (value is Map) { return value; } if (value is Map) { return Map.from(value); } if (value == null) { return {}; } return jsonDecode(value.toString()) as Map; } }