/// Index of remotely available seasons, served as a static JSON next to the
/// pack files. The client compares (seasonId, version) against its cache.
class RemoteManifest {
  const RemoteManifest({
    required this.schemaVersion,
    required this.minAppBuild,
    required this.current,
    required this.seasons,
  });

  static const int supportedSchema = 1;

  factory RemoteManifest.fromJson(Map<String, dynamic> json) {
    final schema = json['schemaVersion'] as int;
    if (schema > supportedSchema) {
      throw FormatException('Unsupported manifest schema: $schema');
    }
    final seasons = [
      for (final s in json['seasons'] as List)
        ManifestSeason.fromJson(s as Map<String, dynamic>),
    ];
    return RemoteManifest(
      schemaVersion: schema,
      minAppBuild: (json['minAppBuild'] as int?) ?? 1,
      current: (json['current'] as String?) ??
          (seasons.isNotEmpty ? seasons.last.seasonId : ''),
      seasons: seasons,
    );
  }

  final int schemaVersion;
  final int minAppBuild;
  final String current;
  final List<ManifestSeason> seasons;

  Map<String, dynamic> toJson() => {
        'schemaVersion': schemaVersion,
        'minAppBuild': minAppBuild,
        'current': current,
        'seasons': [for (final s in seasons) s.toJson()],
      };
}

class ManifestSeason {
  const ManifestSeason({
    required this.seasonId,
    required this.version,
    required this.packUrl,
    required this.sha256,
  });

  factory ManifestSeason.fromJson(Map<String, dynamic> json) =>
      ManifestSeason(
        seasonId: json['seasonId'] as String,
        version: json['version'] as int,
        packUrl: json['packUrl'] as String,
        sha256: json['sha256'] as String,
      );

  final String seasonId;
  final int version;
  final String packUrl;
  final String sha256;

  Map<String, dynamic> toJson() => {
        'seasonId': seasonId,
        'version': version,
        'packUrl': packUrl,
        'sha256': sha256,
      };
}
