class ApiKeyInfo { final String key; final String name; final bool isAdmin; final bool isActive; final DateTime? createdAt; const ApiKeyInfo({ required this.key, required this.name, required this.isAdmin, required this.isActive, this.createdAt, }); String get formattedCreatedAt { final value = createdAt; if (value == null) return ''; String pad(int n) => n.toString().padLeft(2, '0'); return '${pad(value.day)}.${pad(value.month)}.${value.year}'; } static ApiKeyInfo fromApi(Object? data, {String? fallbackKey}) { if (data is! Map) { final key = data?.toString() ?? fallbackKey; if (key == null || key.isEmpty) { throw const FormatException('api key должен быть объектом или токеном'); } return ApiKeyInfo(key: key, name: key, isAdmin: false, isActive: true); } final map = Map.from(data); final key = _stringValue(map, const ['key', 'token', 'api_key']) ?? fallbackKey; if (key == null || key.isEmpty) { throw const FormatException('api key не содержит токен'); } return ApiKeyInfo( key: key, name: _stringValue(map, const ['name', 'label']) ?? 'Без имени', isAdmin: _boolValue(map['is_admin']), isActive: _boolValue(map['is_active'] ?? map['active'], fallback: true), createdAt: DateTime.tryParse(map['created_at']?.toString() ?? ''), ); } static List listFromApi(Object? data) { final values = _collectionValues(data, const ['data', 'keys']); return values.map((value) { if (value.entryKey == null) return ApiKeyInfo.fromApi(value.value); return ApiKeyInfo.fromApi(value.value, fallbackKey: value.entryKey); }).toList(); } } bool _boolValue(Object? value, {bool fallback = false}) { if (value is bool) return value; if (value is num) return value != 0; if (value is String) { final normalized = value.trim().toLowerCase(); if (normalized == 'true' || normalized == '1') return true; if (normalized == 'false' || normalized == '0') return false; } return fallback; } String? _stringValue(Map map, List keys) { for (final key in keys) { final value = map[key]; if (value != null && value.toString().isNotEmpty) { return value.toString(); } } return null; } List<_CollectionValue> _collectionValues(Object? data, List wrappers) { if (data is List) { return data.map((value) => _CollectionValue(value)).toList(); } if (data is Map) { final map = Map.from(data); for (final wrapper in wrappers) { final value = map[wrapper]; if (value is List) { return value.map((item) => _CollectionValue(item)).toList(); } } return map.entries .map((entry) => _CollectionValue(entry.value, entryKey: entry.key)) .toList(); } throw const FormatException('ожидался список или объект'); } class _CollectionValue { final Object? value; final String? entryKey; const _CollectionValue(this.value, {this.entryKey}); }