import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:gametime/application/application.dart';
import 'package:gametime/application/app_bootstrap.dart';
import 'package:gametime/domain/domain.dart';
import 'package:gametime/presentation/home_screen.dart';

void main() {
  testWidgets('l’entrée Progression est présente après Historique', (
    tester,
  ) async {
    await tester.pumpWidget(
      MaterialApp(
        navigatorObservers: [homeRouteObserver],
        home: HomeScreen(
          bootstrap: _FakeBootstrap(_FakeActiveSessionRepository()),
        ),
      ),
    );
    await tester.pump();

    expect(find.text('Historique'), findsOneWidget);
    expect(find.text('Progression'), findsOneWidget);
    expect(
      find.text('Volume, régularité et évolution par exercice'),
      findsOneWidget,
    );
    expect(
      tester.getTopLeft(find.text('Progression')).dy,
      greaterThan(tester.getTopLeft(find.text('Historique')).dy),
    );
  });

  testWidgets('l’entrée Profil est présente sur l’accueil', (tester) async {
    await tester.pumpWidget(
      MaterialApp(
        navigatorObservers: [homeRouteObserver],
        home: HomeScreen(
          bootstrap: _FakeBootstrap(_FakeActiveSessionRepository()),
        ),
      ),
    );
    await tester.pump();

    expect(find.text('Profil'), findsOneWidget);
    expect(find.text('Compte, synchronisation et partages'), findsOneWidget);
  });

  testWidgets('le bandeau de reprise apparaît au retour sur l’accueil', (
    tester,
  ) async {
    final navigatorKey = GlobalKey<NavigatorState>();
    final activeRepository = _FakeActiveSessionRepository();

    await tester.pumpWidget(
      MaterialApp(
        navigatorKey: navigatorKey,
        navigatorObservers: [homeRouteObserver],
        home: HomeScreen(bootstrap: _FakeBootstrap(activeRepository)),
      ),
    );
    await tester.pump();
    await tester.pump();

    expect(find.textContaining('Séance en cours'), findsNothing);

    unawaited(
      navigatorKey.currentState!.push<void>(
        MaterialPageRoute(
          builder: (context) => const Scaffold(body: Text('Séance active')),
        ),
      ),
    );
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 350));

    activeRepository.session = ActiveWorkoutSession(
      metadata: _metadata('session-1'),
      sourceWorkoutTemplateId: 'template-1',
      status: ActiveWorkoutStatus.paused,
      startedAt: DateTime.utc(2026, 7, 17, 12),
      pausedAt: DateTime.utc(2026, 7, 17, 12, 5),
      lastPersistedAt: DateTime.utc(2026, 7, 17, 12, 5),
      elapsedActiveMs: 300000,
      currentProgramIndex: 0,
      currentExerciseIndex: 0,
      currentSetIndex: 1,
      resolvedTemplateSnapshotJson: _sessionSnapshot(),
    );

    navigatorKey.currentState!.pop();
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 350));
    await tester.pump();

    expect(
      find.text('Séance en cours — Reprendre · Squat, série 2/3'),
      findsOneWidget,
    );
  });

  testWidgets('le bandeau de reprise disparaît au retour après abandon', (
    tester,
  ) async {
    final navigatorKey = GlobalKey<NavigatorState>();
    final activeRepository = _FakeActiveSessionRepository()
      ..session = ActiveWorkoutSession(
        metadata: _metadata('session-1'),
        sourceWorkoutTemplateId: 'template-1',
        status: ActiveWorkoutStatus.paused,
        startedAt: DateTime.utc(2026, 7, 17, 12),
        pausedAt: DateTime.utc(2026, 7, 17, 12, 5),
        lastPersistedAt: DateTime.utc(2026, 7, 17, 12, 5),
        elapsedActiveMs: 300000,
        currentProgramIndex: 0,
        currentExerciseIndex: 0,
        currentSetIndex: 1,
        resolvedTemplateSnapshotJson: _sessionSnapshot(),
      );

    await tester.pumpWidget(
      MaterialApp(
        navigatorKey: navigatorKey,
        navigatorObservers: [homeRouteObserver],
        home: HomeScreen(bootstrap: _FakeBootstrap(activeRepository)),
      ),
    );
    await tester.pump();
    await tester.pump();

    expect(find.textContaining('Séance en cours'), findsOneWidget);

    unawaited(
      navigatorKey.currentState!.push<void>(
        MaterialPageRoute(
          builder: (context) => const Scaffold(body: Text('Séance active')),
        ),
      ),
    );
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 350));

    activeRepository.session = null;
    navigatorKey.currentState!.pop();
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 350));
    await tester.pump();

    expect(find.textContaining('Séance en cours'), findsNothing);
  });
}

final class _FakeBootstrap implements AppDependencies {
  _FakeBootstrap(_FakeActiveSessionRepository activeRepository)
    : authUseCases = AuthUseCases(
        tokenStore: _FakeAuthTokenStore(),
        accountRepository: _FakeOnlineAccountRepository(),
        remoteAuthApi: _FakeRemoteAuthApi(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
        ids: _FakeIds(),
      ),
      syncUseCases = SyncUseCases(
        tokenStore: _FakeAuthTokenStore(),
        remoteSyncApi: _FakeRemoteSyncApi(),
        metadataRepository: _FakeSyncMetadataRepository(),
        mappingRepository: _FakeRemoteResourceMappingRepository(),
        localChanges: _FakeLocalSyncChangeRepository(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
        deviceId: 'device-1',
      ),
      shareUseCases = ShareUseCases(
        tokenStore: _FakeAuthTokenStore(),
        remoteShareApi: _FakeRemoteShareApi(),
        inboxRepository: _FakeShareInboxRepository(),
        pendingActionRepository: _FakePendingShareActionRepository(),
        localChanges: _FakeLocalSyncChangeRepository(),
        programRepository: _FakeProgramRepository(),
        templateRepository: _FakeWorkoutTemplateRepository(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
        ids: _FakeIds(),
        originDeviceId: 'device-1',
      ),
      activeWorkoutSessionUseCases = ActiveWorkoutSessionUseCases(
        sessionRepository: activeRepository,
        templateRepository: _FakeWorkoutTemplateRepository(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
        ids: _FakeIds(),
        originDeviceId: 'device-1',
      ),
      activeExerciseStepUseCases = ActiveExerciseStepUseCases(
        sessionRepository: activeRepository,
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
        ids: _FakeIds(),
        originDeviceId: 'device-1',
      ),
      closeWorkoutSessionUseCase = CloseWorkoutSessionUseCase(
        sessionRepository: activeRepository,
        historyRepository: _FakeWorkoutHistoryRepository(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
        ids: _FakeIds(),
        originDeviceId: 'device-1',
      ),
      exerciseUseCases = ExerciseUseCases(
        repository: _FakeExerciseRepository(),
        programRepository: _FakeProgramRepository(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
        ids: _FakeIds(),
        originDeviceId: 'device-1',
      ),
      mediaUseCases = MediaUseCases(
        mediaRepository: _FakeMediaAssetRepository(),
        exerciseRepository: _FakeExerciseRepository(),
        storage: _FakeMediaStorage(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
        ids: _FakeIds(),
        originDeviceId: 'device-1',
      ),
      programUseCases = ProgramUseCases(
        programRepository: _FakeProgramRepository(),
        exerciseRepository: _FakeExerciseRepository(),
        templateRepository: _FakeWorkoutTemplateRepository(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
        ids: _FakeIds(),
        originDeviceId: 'device-1',
      ),
      workoutTemplateUseCases = WorkoutTemplateUseCases(
        templateRepository: _FakeWorkoutTemplateRepository(),
        programRepository: _FakeProgramRepository(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
        ids: _FakeIds(),
        originDeviceId: 'device-1',
      ),
      workoutHistoryUseCases = WorkoutHistoryUseCases(
        repository: _FakeWorkoutHistoryRepository(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
      ),
      progressionStatsUseCase = ProgressionStatsUseCase(
        repository: _FakeProgressionStatsRepository(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
      ),
      exercisePerformanceReferenceUseCase = ExercisePerformanceReferenceUseCase(
        repository: _FakeExercisePerformanceReferenceRepository(),
      ),
      dataExportUseCase = DataExportUseCase(
        repository: _FakeLocalDataBackupRepository(),
        mediaStore: _FakeLocalBackupMediaStore(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
      ),
      dataImportUseCase = DataImportUseCase(
        repository: _FakeLocalDataBackupRepository(),
        mediaStore: _FakeLocalBackupMediaStore(),
        clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
      );

  @override
  final AuthUseCases authUseCases;

  @override
  final SyncUseCases syncUseCases;

  @override
  final ShareUseCases shareUseCases;

  @override
  final ExerciseUseCases exerciseUseCases;

  @override
  final MediaUseCases mediaUseCases;

  @override
  final ProgramUseCases programUseCases;

  @override
  final WorkoutTemplateUseCases workoutTemplateUseCases;

  @override
  final ActiveWorkoutSessionUseCases activeWorkoutSessionUseCases;

  @override
  final ActiveExerciseStepUseCases activeExerciseStepUseCases;

  @override
  final CloseWorkoutSessionUseCase closeWorkoutSessionUseCase;

  @override
  final WorkoutHistoryUseCases workoutHistoryUseCases;

  @override
  final ProgressionStatsUseCase progressionStatsUseCase;

  @override
  final ExercisePerformanceReferenceUseCase exercisePerformanceReferenceUseCase;

  @override
  final DataExportUseCase dataExportUseCase;

  @override
  final DataImportUseCase dataImportUseCase;
}

String _sessionSnapshot() {
  return jsonEncode({
    'name': 'Séance jambes',
    'programs': [
      {
        'id': 'template-program-1',
        'programNameSnapshot': 'Programme jambes',
        'programSnapshotJson': jsonEncode({
          'exercises': [
            {
              'id': 'exercise-1',
              'exerciseNameSnapshot': 'Squat',
              'setsCount': 3,
              'timeEnabled': true,
              'repsEnabled': false,
              'scoreEnabled': false,
              'restSecondsOverride': 0,
            },
          ],
        }),
      },
    ],
    'overrides': const [],
  });
}

EntityMetadata _metadata(String id) {
  return EntityMetadata(
    id: id,
    createdAt: DateTime.utc(2026, 7, 17),
    updatedAt: DateTime.utc(2026, 7, 17),
    originDeviceId: 'device-1',
  );
}

final class _FakeClock implements Clock {
  const _FakeClock(this.value);

  final DateTime value;

  @override
  DateTime now() => value;
}

final class _FakeIds implements IdGenerator {
  var _next = 0;

  @override
  String newId() {
    _next += 1;
    return 'id-$_next';
  }
}

final class _FakeAuthTokenStore implements AuthTokenStore {
  @override
  Future<void> clearToken() async {}

  @override
  Future<String?> readToken() async => null;

  @override
  Future<void> saveToken(String token, DateTime expiresAt) async {}
}

final class _FakeOnlineAccountRepository implements OnlineAccountRepository {
  @override
  Future<void> clearSession() async {}

  @override
  Future<UserAccountSession?> currentSession() async => null;

  @override
  Future<void> saveSession(UserAccountSession session) async {}
}

final class _FakeRemoteAuthApi implements RemoteAuthApi {
  @override
  Future<RemoteAuthResult> login({
    required String email,
    required String password,
  }) async {
    throw const RemoteAuthException(RemoteAuthFailure.network);
  }

  @override
  Future<void> logout(String token) async {}

  @override
  Future<RemoteAuthResult> register({
    required String email,
    required String password,
    String? displayName,
  }) async {
    throw const RemoteAuthException(RemoteAuthFailure.network);
  }
}

final class _FakeRemoteSyncApi implements RemoteSyncApi {
  @override
  Future<RemoteSyncPullResult> pull({
    required String? since,
    required String token,
  }) async {
    return const RemoteSyncPullResult(serverCursor: null, items: []);
  }

  @override
  Future<RemoteSyncPushResult> push({
    required String deviceId,
    required List<RemoteSyncPushItem> items,
    required String token,
  }) async {
    return const RemoteSyncPushResult(serverCursor: null, results: []);
  }
}

final class _FakeSyncMetadataRepository implements SyncMetadataRepository {
  SyncMetadataSnapshot _metadata = const SyncMetadataSnapshot();

  @override
  Future<SyncMetadataSnapshot> read() async => _metadata;

  @override
  Future<void> save(SyncMetadataSnapshot metadata) async {
    _metadata = metadata;
  }
}

final class _FakeRemoteResourceMappingRepository
    implements RemoteResourceMappingRepository {
  @override
  Future<RemoteResourceMapping?> find({
    required SyncResourceType resourceType,
    required String clientId,
  }) async {
    return null;
  }

  @override
  Future<void> save(RemoteResourceMapping mapping) async {}
}

final class _FakeLocalSyncChangeRepository
    implements LocalSyncChangeRepository {
  @override
  Future<bool> applyRemoteItem(RemoteSyncedItem item) async => false;

  @override
  Future<List<PendingSyncChange>> listPendingChanges() async => const [];

  @override
  Future<void> markChangesSynced(
    List<String> changeLogIds,
    DateTime syncedAt,
  ) async {}
}

final class _FakeRemoteShareApi implements RemoteShareApi {
  @override
  Future<RemoteSyncedItem> acceptShare(String shareId, String token) async {
    throw const RemoteAuthException(RemoteAuthFailure.network);
  }

  @override
  Future<void> declineShare(String shareId, String token) async {}

  @override
  Future<List<ShareInboxItem>> fetchInbox(String token) async => const [];

  @override
  Future<void> revokeShare(String shareId, String token) async {}

  @override
  Future<RemoteShareSendResult> sendShare({
    required ShareResourceType resourceType,
    required Map<String, Object?> payload,
    required List<String> recipientEmails,
    required String token,
  }) async {
    return const RemoteShareSendResult(
      shareId: 'share-1',
      recipientUserIds: [],
      unresolvedEmails: [],
    );
  }
}

final class _FakeShareInboxRepository implements ShareInboxRepository {
  @override
  Future<ShareInboxItem?> findByShareId(String shareId) async => null;

  @override
  Future<List<ShareInboxItem>> listAll() async => const [];

  @override
  Future<void> markStatus(
    String shareId,
    ShareInboxStatus status,
    DateTime respondedAt,
  ) async {}

  @override
  Future<void> upsert(ShareInboxItem item) async {}

  @override
  Future<void> upsertAll(List<ShareInboxItem> items) async {}
}

final class _FakePendingShareActionRepository
    implements PendingShareActionRepository {
  @override
  Future<void> add(PendingShareAction action) async {}

  @override
  Future<List<PendingShareAction>> listPending() async => const [];

  @override
  Future<void> markFailed(String id, DateTime attemptedAt) async {}

  @override
  Future<void> markSucceeded(String id, DateTime attemptedAt) async {}
}

final class _FakeActiveSessionRepository implements ActiveSessionRepository {
  ActiveWorkoutSession? session;
  final restStates = <ActiveRestState>[];
  final setTimerStates = <ActiveSetTimerState>[];
  final scoreStopwatchStates = <ActiveScoreStopwatchState>[];
  final results = <ActiveSetResult>[];

  @override
  Future<ActiveWorkoutSession?> findById(String id) async {
    return session?.metadata.id == id ? session : null;
  }

  @override
  Future<ActiveWorkoutSession?> findOpen() async => session;

  @override
  Future<ActiveRestState?> findRestStateById(String id) async => null;

  @override
  Future<ActiveScoreStopwatchState?> findScoreStopwatchState({
    required String sessionId,
    required int programIndex,
    required int exerciseIndex,
    required int setIndex,
  }) async {
    return null;
  }

  @override
  Future<ActiveSetTimerState?> findSetTimerState({
    required String sessionId,
    required int programIndex,
    required int exerciseIndex,
    required int setIndex,
  }) async {
    return null;
  }

  @override
  Future<ActiveExerciseStepProgressState?> findExerciseStepProgressState({
    required String sessionId,
    required int programIndex,
    required int exerciseIndex,
    required int setIndex,
  }) async {
    return null;
  }

  @override
  Future<List<ActiveRestState>> listRestStates(String sessionId) async {
    return restStates;
  }

  @override
  Future<List<ActiveScoreStopwatchState>> listScoreStopwatchStates(
    String sessionId,
  ) async {
    return scoreStopwatchStates;
  }

  @override
  Future<List<ActiveSetTimerState>> listSetTimerStates(String sessionId) async {
    return setTimerStates;
  }

  @override
  Future<List<ActiveSetResult>> listSetResults(String sessionId) async {
    return results;
  }

  @override
  Future<List<ActiveExerciseStepProgressState>> listExerciseStepProgressStates(
    String sessionId,
  ) async {
    return const [];
  }

  @override
  Future<List<ActiveExerciseStepResult>> listExerciseStepResults(
    String sessionId,
  ) async {
    return const [];
  }

  @override
  Future<void> save(ActiveWorkoutSession session) async {
    this.session = session;
  }

  @override
  Future<void> saveRestState(ActiveRestState restState) async {
    restStates.add(restState);
  }

  @override
  Future<void> saveScoreStopwatchState(ActiveScoreStopwatchState state) async {
    scoreStopwatchStates.add(state);
  }

  @override
  Future<void> saveSetTimerState(ActiveSetTimerState state) async {
    setTimerStates.add(state);
  }

  @override
  Future<void> saveExerciseStepProgressState(
    ActiveExerciseStepProgressState state,
  ) async {}

  @override
  Future<void> saveExerciseStepResult(ActiveExerciseStepResult result) async {}

  @override
  Future<void> deleteScoreStopwatchState({
    required String sessionId,
    required int programIndex,
    required int exerciseIndex,
    required int setIndex,
    required DateTime deletedAt,
  }) async {}

  @override
  Future<void> saveSetResult(ActiveSetResult result) async {
    results.add(result);
  }
}

final class _FakeExerciseRepository implements ExerciseRepository {
  @override
  Future<Exercise?> findById(String id) async => null;

  @override
  Future<bool> isReferencedByProgram(String id) async => false;

  @override
  Future<List<Exercise>> listActive() async => const [];

  @override
  Future<void> save(Exercise exercise) async {}
}

final class _FakeMediaAssetRepository implements MediaAssetRepository {
  @override
  Future<MediaAsset?> findById(String id) async => null;

  @override
  Future<List<MediaAsset>> listActive() async => const [];

  @override
  Future<void> save(MediaAsset mediaAsset) async {}
}

final class _FakeMediaStorage implements LocalMediaStorage {
  @override
  Future<void> deleteByLocalUri(String localUri) async {}

  @override
  Future<StoredMediaFile> importFile({
    required String sourcePath,
    required MediaKind kind,
    required String stableFileName,
  }) async {
    return StoredMediaFile(
      localUri: 'file:///$stableFileName',
      mimeType: 'image/png',
      sizeBytes: 0,
    );
  }

  @override
  Future<Set<String>> listManagedLocalUris() async => const {};
}

final class _FakeLocalDataBackupRepository
    implements LocalDataBackupRepository {
  @override
  Future<LocalBackupImportResult> applyImportSnapshot({
    required LocalDataExportSnapshot snapshot,
    required LocalBackupImportMode mode,
    required DateTime importedAt,
  }) async {
    return const LocalBackupImportResult(
      insertedCount: 0,
      updatedCount: 0,
      ignoredOlderCount: 0,
      deletedByReplaceCount: 0,
      missingMediaCount: 0,
    );
  }

  @override
  Future<bool> hasAnyUserData() async => false;

  @override
  Future<bool> hasOpenActiveWorkoutSession() async => false;

  @override
  Future<LocalDataExportSnapshot> readExportSnapshot(
    DateTime exportedAt,
  ) async {
    return LocalDataExportSnapshot(
      exportedAt: exportedAt,
      appSchemaVersion: 1,
      originDeviceId: 'device-1',
      mediaAssets: const [],
      exercises: const [],
      programs: const [],
      workoutTemplates: const [],
      workoutHistories: const [],
    );
  }
}

final class _FakeLocalBackupMediaStore implements LocalBackupMediaStore {
  @override
  Future<List<EmbeddedBackupMediaFile>> readEmbeddableFiles(
    List<LocalBackupResource> mediaAssets,
  ) async {
    return const [];
  }

  @override
  Future<Map<String, RestoredMediaFile>> restoreEmbeddedFiles(
    List<EmbeddedBackupMediaFile> files,
  ) async {
    return const {};
  }
}

final class _FakeProgramRepository implements ProgramRepository {
  @override
  Future<Program?> findById(String id) async => null;

  @override
  Future<List<Program>> listActive() async => const [];

  @override
  Future<void> replaceExercises(Program program, DateTime deletedAt) async {}

  @override
  Future<void> save(Program program) async {}

  @override
  Future<void> saveExercise(ProgramExercise exercise) async {}
}

final class _FakeWorkoutTemplateRepository
    implements WorkoutTemplateRepository {
  @override
  Future<WorkoutTemplate?> findById(String id) async => null;

  @override
  Future<List<WorkoutTemplate>> listActive() async => const [];

  @override
  Future<void> replaceComposition(
    WorkoutTemplate template,
    DateTime deletedAt,
  ) async {}

  @override
  Future<void> save(WorkoutTemplate template) async {}

  @override
  Future<void> saveOverride(WorkoutTemplateExerciseOverride override) async {}

  @override
  Future<void> saveProgram(WorkoutTemplateProgram program) async {}
}

final class _FakeWorkoutHistoryRepository implements WorkoutHistoryRepository {
  @override
  Future<void> delete(String id, DateTime deletedAt) async {}

  @override
  Future<WorkoutHistory?> findById(String id) async => null;

  @override
  Future<List<WorkoutHistory>> listActive() async => const [];

  @override
  Future<void> save(WorkoutHistory history) async {}

  @override
  Future<void> saveSetResult(WorkoutHistorySetResult result) async {}

  @override
  Future<void> saveStepResult(WorkoutHistoryStepResult result) async {}
}

final class _FakeProgressionStatsRepository
    implements ProgressionStatsRepository {
  @override
  Future<ProgressionGlobalStatsData> readGlobalStats(
    ProgressionDateRange range,
  ) async {
    return const ProgressionGlobalStatsData(
      completedSessionCount: 0,
      totalActiveMs: 0,
      activeWeekStarts: [],
      hasAnyCompletedHistory: false,
    );
  }

  @override
  Future<List<ProgressionExerciseOptionData>> listExerciseOptions(
    ProgressionDateRange range,
  ) async {
    return const [];
  }

  @override
  Future<List<ProgressionMeasureOptionData>> listMeasureOptions({
    required ProgressionDateRange range,
    required String exerciseKey,
  }) async {
    return const [];
  }

  @override
  Future<ProgressionExerciseSeriesData> readExerciseSeries({
    required ProgressionDateRange range,
    required String exerciseKey,
    required ProgressionMeasure measure,
  }) async {
    return ProgressionExerciseSeriesData(
      exerciseKey: exerciseKey,
      exerciseNameSnapshot: exerciseKey,
      measure: ProgressionMeasureOptionData(
        measure: measure,
        label: 'Score',
        lowerIsBetter: false,
      ),
      points: const [],
      hasAnyAllTimeData: false,
      hasAnyCompletedExerciseResult: false,
    );
  }
}

final class _FakeExercisePerformanceReferenceRepository
    implements ExercisePerformanceReferenceRepository {
  @override
  Future<bool> hasAnyCompletedHistoryForExercise(String exerciseId) async {
    return false;
  }

  @override
  Future<WorkoutHistorySetPerformance?> findLatestSetPerformance({
    required String exerciseId,
    required ActivePerformanceMeasures activeMeasures,
    required int currentSetIndex,
  }) async {
    return null;
  }

  @override
  Future<WorkoutHistoryMetricPerformance?> findBestMetricPerformance({
    required String exerciseId,
    required PerformanceMetric metric,
    required ScoreInputMode scoreInputMode,
  }) async {
    return null;
  }
}
