import 'dart:convert';
import 'dart:io';

final class VersionedSyncFixture {
  const VersionedSyncFixture({
    required this.resourceType,
    required this.name,
    required this.schemaVersion,
    required this.payload,
  });

  final String resourceType;
  final String name;
  final int schemaVersion;
  final Map<String, Object?> payload;
}

VersionedSyncFixture loadExerciseFixture(String name, {String version = 'v1'}) {
  return _loadFixture(
    resourceType: 'exercise',
    path: 'test/fixtures/exercises/$version/$name.json',
    name: name,
  );
}

VersionedSyncFixture loadProgramFixture(String name, {String version = 'v1'}) {
  return _loadFixture(
    resourceType: 'program',
    path: 'test/fixtures/programs/$version/$name.json',
    name: name,
  );
}

VersionedSyncFixture loadWorkoutTemplateFixture(
  String name, {
  String version = 'v1',
}) {
  return _loadFixture(
    resourceType: 'workoutTemplate',
    path: 'test/fixtures/workout_templates/$version/$name.json',
    name: name,
  );
}

VersionedSyncFixture loadWorkoutHistoryFixture(
  String name, {
  String version = 'v1',
}) {
  return _loadFixture(
    resourceType: 'workoutHistory',
    path: 'test/fixtures/workout_histories/$version/$name.json',
    name: name,
  );
}

List<VersionedSyncFixture> loadExerciseFixtures({
  String version = 'v1',
  List<String> names = const [
    'minimal',
    'with_steps',
    'with_score_chrono',
    'with_timers',
    'full_combo',
  ],
}) {
  return [
    for (final name in names) loadExerciseFixture(name, version: version),
  ];
}

List<VersionedSyncFixture> loadMinimalResourceFixtures({
  String version = 'v1',
}) {
  return [
    loadProgramFixture('minimal', version: version),
    loadWorkoutTemplateFixture('minimal', version: version),
    loadWorkoutHistoryFixture('minimal', version: version),
  ];
}

VersionedSyncFixture _loadFixture({
  required String resourceType,
  required String path,
  required String name,
}) {
  final raw = File(path).readAsStringSync();
  final decoded = jsonDecode(raw);
  if (decoded is! Map<String, Object?>) {
    throw StateError('Fixture $path must contain a JSON object.');
  }
  final schemaVersion = decoded['schemaVersion'];
  if (schemaVersion is! int || schemaVersion <= 0) {
    throw StateError('Fixture $path must contain a positive schemaVersion.');
  }
  return VersionedSyncFixture(
    resourceType: resourceType,
    name: name,
    schemaVersion: schemaVersion,
    payload: decoded,
  );
}
