@@ -138,11 +138,24 @@ class IncidentRepository {
138138 );
139139 }
140140
141+ int _getIncidentStatePriority (String state) {
142+ switch (state.toUpperCase ()) {
143+ case 'RESOLVED' :
144+ return 3 ;
145+ case 'ASSIGNED' :
146+ return 2 ;
147+ case 'PENDING' :
148+ return 1 ;
149+ default :
150+ return 0 ; // e.g. 'new' or unknown
151+ }
152+ }
153+
141154 /// Handles an incoming P2P incident from the network.
142155 ///
143156 /// Uses the incident_id from the envelope payload as the DB primary key
144157 /// to enable DB-level deduplication. If an incident with the same ID already
145- /// exists, the insert is skipped .
158+ /// exists, the CRDT merge logic is applied .
146159 Future <void > _handleIncomingP2PIncident (domain.IncidentCreateDto dto) async {
147160 // Extract incident_id from envelope metadata (passed through dto.data)
148161 final String incidentId = dto.data? ['incident_id' ] as String ? ??
@@ -154,8 +167,44 @@ class IncidentRepository {
154167 .get ();
155168
156169 if (existing.isNotEmpty) {
157- debugPrint (
158- '[IncidentRepo] Duplicate incident skipped: $incidentId (already in DB)' );
170+ final current = incidentFromDb (existing.first);
171+ final currentPriority = _getIncidentStatePriority (current.status);
172+ final incomingPriority = _getIncidentStatePriority (dto.status);
173+
174+ bool shouldUpdate = false ;
175+ if (incomingPriority > currentPriority) {
176+ shouldUpdate = true ;
177+ } else if (incomingPriority == currentPriority) {
178+ if (dto.sequenceNum > current.sequenceNum) {
179+ shouldUpdate = true ;
180+ }
181+ }
182+
183+ if (shouldUpdate) {
184+ debugPrint (
185+ '[IncidentRepo] CRDT_MERGE_APPLIED: Updating $incidentId state to ${dto .status }' );
186+ debugPrint (
187+ '[IncidentRepo] STATE_UPDATED: $incidentId from ${current .status } to ${dto .status }' );
188+ debugPrint ('[IncidentRepo] CONFLICT_RESOLVED: incoming wins' );
189+
190+ await (_db.update (_db.incidents)..where ((t) => t.id.equals (incidentId)))
191+ .write (
192+ db.IncidentsCompanion (
193+ statusEnum: Value (dto.status),
194+ sequenceNum: Value (dto.sequenceNum),
195+ updatedAt: Value (DateTime .now ()),
196+ lat: Value (dto.lat),
197+ lon: Value (dto.lon),
198+ priority: Value (dto.priority),
199+ type: Value (dto.type),
200+ clientId: Value (dto.clientId),
201+ ),
202+ );
203+ } else {
204+ debugPrint (
205+ '[IncidentRepo] CRDT_MERGE_APPLIED: Local state kept for $incidentId ' );
206+ debugPrint ('[IncidentRepo] CONFLICT_RESOLVED: local wins' );
207+ }
159208 return ;
160209 }
161210
@@ -228,9 +277,9 @@ class IncidentRepository {
228277 lat: (incMap['lat' ] as num ? )? .toDouble () ?? 0.0 ,
229278 lon: (incMap['lon' ] as num ? )? .toDouble () ?? 0.0 ,
230279 priority: incMap['priority' ] as String ? ?? 'medium' ,
231- status: incMap['status' ] as String ? ?? 'new' ,
280+ status: incMap['status' ] as String ? ?? incMap[ 'state' ] as String ? ?? 'new' ,
232281 clientId: incMap['reporter_id' ] as String ? ?? 'synced_peer' ,
233- sequenceNum: 1 ,
282+ sequenceNum: incMap[ 'clock' ] as int ? ?? 1 ,
234283 data: {'incident_id' : incidentId},
235284 );
236285
0 commit comments