import 'stage.dart';

/// Visual identity of a season. Colors are int ARGB so this file stays
/// pure Dart (architecture guard forbids Flutter imports here).
class SeasonTheme {
  const SeasonTheme({
    this.tileSet = 'spring',
    this.background = '',
    this.backgroundGradient = defaultGradient,
    this.accentColor = 0xFFFF7EB3,
    this.particleType = 'petals',
    this.tilePalette,
    this.boardTint,
    this.bgm = 'menu',
  });

  factory SeasonTheme.fromJson(Map<String, dynamic> json) => SeasonTheme(
        tileSet: (json['tileSet'] as String?) ?? 'spring',
        background: (json['background'] as String?) ?? '',
        backgroundGradient: json['backgroundGradient'] != null
            ? [for (final c in json['backgroundGradient'] as List) (c as num).toInt()]
            : defaultGradient,
        accentColor: (json['accentColor'] as int?) ?? 0xFFFF7EB3,
        particleType: (json['particleType'] as String?) ?? 'petals',
        tilePalette: json['tilePalette'] != null
            ? [for (final c in json['tilePalette'] as List) (c as num).toInt()]
            : null,
        boardTint: json['boardTint'] as int?,
        bgm: (json['bgm'] as String?) ?? 'menu',
      );

  /// Season 1 "First Bloom": deep navy dusk.
  static const defaultGradient = [0xFF0E1430, 0xFF16204A, 0xFF2A2E5E];

  static const fallback = SeasonTheme();

  final String tileSet;
  final String background;

  /// Top-to-bottom screen gradient, int ARGB.
  final List<int> backgroundGradient;
  final int accentColor;

  /// petals | snow | leaves | none
  final String particleType;

  /// Optional tile color override; null = built-in candy palette.
  final List<int>? tilePalette;

  /// Optional board background override.
  final int? boardTint;

  /// Looping background-music track key, resolved to `assets/audio/bgm/KEY.mp3`.
  /// Remote seasons reuse bundled track keys (no remote audio download).
  final String bgm;

  Map<String, dynamic> toJson() => {
        'tileSet': tileSet,
        'background': background,
        'backgroundGradient': backgroundGradient,
        'accentColor': accentColor,
        'particleType': particleType,
        if (tilePalette != null) 'tilePalette': tilePalette,
        if (boardTint != null) 'boardTint': boardTint,
        'bgm': bgm,
      };
}

/// A season's full content: metadata, theme, and its stages. The unit of
/// remote (or bundled) delivery.
class SeasonPack {
  const SeasonPack({
    required this.schemaVersion,
    required this.seasonId,
    required this.version,
    required this.title,
    required this.theme,
    required this.stages,
  });

  /// Bump when the pack format changes incompatibly; older app builds skip
  /// packs with a newer schema instead of crashing.
  static const int supportedSchema = 1;

  factory SeasonPack.fromJson(Map<String, dynamic> json) {
    final schema = json['schemaVersion'] as int;
    if (schema > supportedSchema) {
      throw FormatException('Unsupported pack schema: $schema');
    }
    return SeasonPack(
      schemaVersion: schema,
      seasonId: json['seasonId'] as String,
      version: json['version'] as int,
      title: (json['title'] as Map<String, dynamic>)
          .map((k, v) => MapEntry(k, v as String)),
      theme: SeasonTheme.fromJson(json['theme'] as Map<String, dynamic>),
      stages: [
        for (final stage in json['stages'] as List)
          StageConfig.fromJson(stage as Map<String, dynamic>),
      ],
    );
  }

  final int schemaVersion;
  final String seasonId;
  final int version;
  final Map<String, String> title;
  final SeasonTheme theme;
  final List<StageConfig> stages;

  String titleFor(String languageCode) =>
      title[languageCode] ?? title['en'] ?? seasonId;

  Map<String, dynamic> toJson() => {
        'schemaVersion': schemaVersion,
        'seasonId': seasonId,
        'version': version,
        'title': title,
        'theme': theme.toJson(),
        'stages': [for (final stage in stages) stage.toJson()],
      };
}
