import 'package:commons_core/commons_core.dart';

/// What to do with one incoming row when importing (data-model §7).
enum ReconcileAction { insert, update, skip }

/// Pure reconciliation rules for the JSON import. No database access — the
/// repository queries existing rows and applies the returned action.
class ImportReconciler {
  const ImportReconciler();

  /// Last-writer-wins for mutable rows, keyed by the packed HLC `updatedAt`
  /// (data-model §4): unknown id → insert; known id → the incoming row wins
  /// only if its stamp is strictly newer, otherwise skip. Re-importing the
  /// same file is therefore a no-op (idempotent).
  ReconcileAction reconcileMutable({
    required String? existingUpdatedAt,
    required String incomingUpdatedAt,
  }) {
    if (existingUpdatedAt == null) return ReconcileAction.insert;
    final incoming = Hlc.parse(incomingUpdatedAt);
    final existing = Hlc.parse(existingUpdatedAt);
    return incoming.compareTo(existing) > 0
        ? ReconcileAction.update
        : ReconcileAction.skip;
  }

  /// Append-only rows (movements): insert when unknown, never update.
  ReconcileAction reconcileAppendOnly({required bool exists}) =>
      exists ? ReconcileAction.skip : ReconcileAction.insert;

  /// The newest stamp among [packedHlcs], or null when empty. After an import
  /// the local clock must `receiveEvent` this so it never falls behind the
  /// imported rows (the next local write must out-stamp all of them).
  Hlc? maxHlc(Iterable<String> packedHlcs) {
    Hlc? max;
    for (final packed in packedHlcs) {
      final hlc = Hlc.parse(packed);
      if (max == null || hlc.compareTo(max) > 0) max = hlc;
    }
    return max;
  }
}
