import 'dart:convert'; import '../utils/app_time.dart'; class TaskActivityLog { TaskActivityLog({ required this.id, required this.taskId, this.actorId, required this.actionType, this.meta, required this.createdAt, }); final String id; final String taskId; final String? actorId; final String actionType; // created, assigned, reassigned, started, completed final Map? meta; final DateTime createdAt; factory TaskActivityLog.fromMap(Map map) { // id and task_id may be returned as int or String depending on DB final rawId = map['id']; final rawTaskId = map['task_id']; String id = rawId == null ? '' : rawId.toString(); String taskId = rawTaskId == null ? '' : rawTaskId.toString(); // actor_id is nullable final actorId = map['actor_id']?.toString(); // action_type fallback final actionType = (map['action_type'] as String?) ?? 'unknown'; // meta may be a Map, Map, JSON-encoded string, List, or null Map? meta; final rawMeta = map['meta']; if (rawMeta is Map) { meta = rawMeta; } else if (rawMeta is Map) { // convert dynamic-key map to Map try { meta = rawMeta.map((k, v) => MapEntry(k.toString(), v)); } catch (_) { meta = null; } } else if (rawMeta is String && rawMeta.isNotEmpty) { try { final decoded = jsonDecode(rawMeta); if (decoded is Map) { meta = decoded; } else if (decoded is Map) { meta = decoded.map((k, v) => MapEntry(k.toString(), v)); } } catch (_) { meta = null; } } else { meta = null; } // created_at may be ISO string, DateTime, or numeric (seconds/millis since epoch) final rawCreated = map['created_at']; DateTime createdAt; if (rawCreated is DateTime) { createdAt = AppTime.toAppTime(rawCreated); } else if (rawCreated is String) { try { createdAt = AppTime.parse(rawCreated); } catch (_) { createdAt = AppTime.now(); } } else if (rawCreated is int) { // assume seconds or milliseconds if (rawCreated > 1e12) { // likely microseconds or nanoseconds - treat as milliseconds createdAt = AppTime.toAppTime( DateTime.fromMillisecondsSinceEpoch(rawCreated), ); } else if (rawCreated > 1e10) { createdAt = AppTime.toAppTime( DateTime.fromMillisecondsSinceEpoch(rawCreated), ); } else { createdAt = AppTime.toAppTime( DateTime.fromMillisecondsSinceEpoch(rawCreated * 1000), ); } } else if (rawCreated is double) { final asInt = rawCreated.toInt(); createdAt = AppTime.toAppTime(DateTime.fromMillisecondsSinceEpoch(asInt)); } else { createdAt = AppTime.now(); } return TaskActivityLog( id: id, taskId: taskId, actorId: actorId, actionType: actionType, meta: meta, createdAt: createdAt, ); } }