/// One user's report under an aggregated quarantine row.
class AdminQuarantineReport {
  const AdminQuarantineReport({
    required this.userId,
    required this.username,
    required this.reason,
    this.notes,
    required this.createdAt,
  });

  final String userId;
  final String username;
  final String reason;
  final String? notes;
  final String createdAt;

  factory AdminQuarantineReport.fromJson(Map<String, dynamic> j) =>
      AdminQuarantineReport(
        userId: j['user_id'] as String? ?? '',
        username: j['username'] as String? ?? '',
        reason: j['reason'] as String? ?? '',
        notes: j['notes'] as String?,
        createdAt: j['created_at'] as String? ?? '',
      );
}

/// Mirrors `adminQueueRowView` from internal/api/admin_quarantine.go.
/// One row aggregates all reports against a single track, with
/// per-reason counts and the underlying per-user reports nested.
class AdminQuarantineItem {
  const AdminQuarantineItem({
    required this.trackId,
    required this.trackTitle,
    required this.artistName,
    required this.albumTitle,
    required this.albumId,
    this.lidarrAlbumMbid,
    required this.reportCount,
    required this.latestAt,
    required this.reasonCounts,
    required this.reports,
  });

  final String trackId;
  final String trackTitle;
  final String artistName;
  final String albumTitle;
  final String albumId;
  final String? lidarrAlbumMbid;
  final int reportCount;
  final String latestAt;

  /// Map of reason → number of reports citing that reason.
  final Map<String, int> reasonCounts;

  final List<AdminQuarantineReport> reports;

  /// One-line summary of the most-cited reason. Returns just the top
  /// reason when only one reason exists, or `top (+N more)` when there
  /// are additional distinct reasons.
  String get topReasonSummary {
    if (reasonCounts.isEmpty) return '';
    final entries = reasonCounts.entries.toList()
      ..sort((a, b) => b.value.compareTo(a.value));
    final top = entries.first.key;
    return entries.length > 1
        ? '$top (+${entries.length - 1} more)'
        : top;
  }

  factory AdminQuarantineItem.fromJson(Map<String, dynamic> j) {
    final reasonCountsRaw =
        (j['reason_counts'] as Map?)?.cast<String, dynamic>() ?? const {};
    final reportsRaw = (j['reports'] as List?) ?? const [];
    return AdminQuarantineItem(
      trackId: j['track_id'] as String? ?? '',
      trackTitle: j['track_title'] as String? ?? '',
      artistName: j['artist_name'] as String? ?? '',
      albumTitle: j['album_title'] as String? ?? '',
      albumId: j['album_id'] as String? ?? '',
      lidarrAlbumMbid: j['lidarr_album_mbid'] as String?,
      reportCount: (j['report_count'] as int?) ?? 0,
      latestAt: j['latest_at'] as String? ?? '',
      reasonCounts:
          reasonCountsRaw.map((k, v) => MapEntry(k, (v as int?) ?? 0)),
      reports: reportsRaw
          .map((e) =>
              AdminQuarantineReport.fromJson((e as Map).cast<String, dynamic>()))
          .toList(growable: false),
    );
  }
}
