/// 小程序复制到剪切板的录制信息。
class ClipboardRecordingModel {
  final String title;
  int? startTimestamp;
  int? endTimestamp;
  final String address;

  /// 录制文件名模板，如「选手名称_选手ID_赛事名称_赛项」。
  final String? filename;

  ClipboardRecordingModel({
    required this.title,
    this.startTimestamp,
    this.endTimestamp,
    required this.address,
    this.filename,
  });

  factory ClipboardRecordingModel.fromJson(Map<String, dynamic> json) {
    return ClipboardRecordingModel(
      title: _readString(json, 'title'),
      startTimestamp: _readOptionalInt(json, 'startTimestamp'),
      endTimestamp: _readOptionalInt(json, 'endTimestamp'),
      address: _readString(json, 'address'),
      filename: _readOptionalString(json, 'filename'),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'title': title,
      'startTimestamp': startTimestamp,
      'endTimestamp': endTimestamp,
      'address': address,
      if (filename != null) 'filename': filename,
    };
  }

  static String? _readOptionalString(Map<String, dynamic> json, String key) {
    final value = json[key];
    if (value == null) return null;
    if (value is String && value.isNotEmpty) return value;
    if (value is! String) {
      throw FormatException('Clipboard field "$key" must be a String.');
    }
    return null;
  }

  static String _readString(Map<String, dynamic> json, String key) {
    final value = json[key];
    if (value is String) return value;
    throw FormatException('Clipboard field "$key" must be a String.');
  }

  static int? _readOptionalInt(Map<String, dynamic> json, String key) {
    final value = json[key];
    if (value == null) return null;
    if (value is int) return value;
    throw FormatException('Clipboard field "$key" must be an int.');
  }
}
