class CharacterPack {
  const CharacterPack({
    required this.filename,
    required this.name,
    required this.characterType,
    required this.renderType,
    this.live2dModel,
  });

  final String filename;
  final String name;
  final String characterType;
  final String renderType;
  final String? live2dModel;

  bool get isLive2d => renderType.toLowerCase() == 'live2d';

  String get typeLabel {
    switch (characterType.toLowerCase()) {
      case 'human':
        return '数字人';
      case 'singer':
        return '歌姬';
      case 'live2d':
        return 'Live2D';
      case 'pet':
      default:
        return '宠物';
    }
  }

  IconDataLike get iconHint {
    switch (characterType.toLowerCase()) {
      case 'human':
        return IconDataLike.person;
      case 'singer':
        return IconDataLike.mic;
      case 'live2d':
        return IconDataLike.sparkle;
      default:
        return IconDataLike.pets;
    }
  }

  factory CharacterPack.fromJson(Map<String, dynamic> json) {
    final character = json['character'];
    final Map<String, dynamic> charMap = character is Map
        ? Map<String, dynamic>.from(character)
        : const <String, dynamic>{};
    final filename = json['filename']?.toString() ?? '';
    return CharacterPack(
      filename: filename,
      name: charMap['name']?.toString().isNotEmpty == true
          ? charMap['name'].toString()
          : filename,
      characterType: charMap['character_type']?.toString() ?? 'pet',
      renderType: charMap['render_type']?.toString() ?? 'video',
      live2dModel: charMap['live2d_model']?.toString(),
    );
  }
}

/// Avoid importing Flutter material in pure model unit tests.
enum IconDataLike { pets, person, mic, sparkle }

class AvailableConfigs {
  const AvailableConfigs({
    required this.configs,
    required this.active,
  });

  final List<CharacterPack> configs;
  final String active;

  factory AvailableConfigs.fromJson(Map<String, dynamic> json) {
    final raw = json['configs'];
    final list = <CharacterPack>[];
    if (raw is List) {
      for (final item in raw) {
        if (item is Map<String, dynamic>) {
          list.add(CharacterPack.fromJson(item));
        } else if (item is Map) {
          list.add(CharacterPack.fromJson(Map<String, dynamic>.from(item)));
        }
      }
    }
    return AvailableConfigs(
      configs: list,
      active: json['active']?.toString() ?? '',
    );
  }
}
