import 'package:commons_core/commons_core.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tane/data/export_import/import_reconciler.dart';

void main() {
  const reconciler = ImportReconciler();

  String stamp(int millis, {int counter = 0, String node = 'node-a'}) =>
      Hlc(millis: millis, counter: counter, nodeId: node).pack();

  group('reconcileMutable (LWW by packed HLC)', () {
    test('unknown id inserts', () {
      expect(
        reconciler.reconcileMutable(
          existingUpdatedAt: null,
          incomingUpdatedAt: stamp(1000),
        ),
        ReconcileAction.insert,
      );
    });

    test('newer incoming stamp updates', () {
      expect(
        reconciler.reconcileMutable(
          existingUpdatedAt: stamp(1000),
          incomingUpdatedAt: stamp(2000),
        ),
        ReconcileAction.update,
      );
    });

    test('older incoming stamp skips', () {
      expect(
        reconciler.reconcileMutable(
          existingUpdatedAt: stamp(2000),
          incomingUpdatedAt: stamp(1000),
        ),
        ReconcileAction.skip,
      );
    });

    test('identical stamp skips (re-import is a no-op)', () {
      expect(
        reconciler.reconcileMutable(
          existingUpdatedAt: stamp(1000),
          incomingUpdatedAt: stamp(1000),
        ),
        ReconcileAction.skip,
      );
    });

    test('same millis resolves by counter then node id', () {
      expect(
        reconciler.reconcileMutable(
          existingUpdatedAt: stamp(1000, counter: 1),
          incomingUpdatedAt: stamp(1000, counter: 2),
        ),
        ReconcileAction.update,
      );
      expect(
        reconciler.reconcileMutable(
          existingUpdatedAt: stamp(1000, node: 'node-a'),
          incomingUpdatedAt: stamp(1000, node: 'node-b'),
        ),
        ReconcileAction.update,
      );
    });
  });

  group('reconcileAppendOnly', () {
    test('unknown id inserts, known id skips (never updates)', () {
      expect(
        reconciler.reconcileAppendOnly(exists: false),
        ReconcileAction.insert,
      );
      expect(
        reconciler.reconcileAppendOnly(exists: true),
        ReconcileAction.skip,
      );
    });
  });

  group('maxHlc', () {
    test('returns the newest stamp', () {
      final max = reconciler.maxHlc([
        stamp(1000),
        stamp(3000, counter: 2),
        stamp(3000, counter: 1),
        stamp(2000),
      ]);
      expect(max, Hlc(millis: 3000, counter: 2, nodeId: 'node-a'));
    });

    test('returns null when empty', () {
      expect(reconciler.maxHlc(const []), isNull);
    });
  });
}
