import '../../core/contracts/library.dart';
import '../../shared/utils/cross_server_search_key.dart';
import '../../shared/utils/emby_ticks.dart';
import '../../shared/utils/format_utils.dart';
import '../../shared/utils/tmdb_key_utils.dart';


class TmdbMediaRef {
  final String id;
  final String mediaType;

  const TmdbMediaRef({required this.id, required this.mediaType});
}

List<String> buildDetailMetaParts(
  EmbyRawItem item, {
  EmbyRawMediaSource? source,
}) {
  final parts = <String>[];
  final seriesName = item.SeriesName;
  if (seriesName != null && seriesName.isNotEmpty) {
    parts.add(seriesName);
  }
  if (item.ProductionYear != null) {
    parts.add('${item.ProductionYear}');
  }
  final episode = episodeLabel(item);
  if (episode != null) {
    parts.add(episode);
  }
  final runtime = item.RunTimeTicks;
  if (runtime != null && runtime > 0) {
    final label = formatRuntimeMinutes(runtime ~/ kTicksPerMinute);
    if (label != null) parts.add(label);
  }
  if (source != null) {
    final videoStream = findVideoStream(source);
    if (videoStream != null) {
      final h = videoStream.extra['Height'] as int? ?? source.Height;
      final range = videoStream.extra['VideoRange'] as String?;
      if (h != null) {
        final label = heightToLabel(h);
        parts.add(range != null && range.isNotEmpty ? '$label $range' : label);
      }
    }
    final size = source.Size;
    if (size != null && size > 0) parts.add(formatFileSize(size));
  }
  return parts;
}

EmbyRawMediaStream? findVideoStream(EmbyRawMediaSource source) {
  final streams = source.MediaStreams;
  if (streams == null) return null;
  for (final s in streams) {
    if (s.Type == 'Video') return s;
  }
  return null;
}

String heightToLabel(int h) {
  if (h >= 2160) return '4K';
  if (h >= 1440) return '2K';
  if (h >= 1080) return '1080P';
  if (h >= 720) return '720P';
  return '${h}P';
}

String? episodeLabel(EmbyRawItem item) {
  final seasonName = item.SeasonName;
  final index = item.IndexNumber;
  if (seasonName == null && index == null) return null;
  if (seasonName != null && seasonName.isNotEmpty && index != null) {
    return '$seasonName ${formatEpisodeNumber(index)}';
  }
  if (seasonName != null && seasonName.isNotEmpty) return seasonName;
  return formatEpisodeNumber(index);
}

String detailNavTitle(EmbyRawItem item, EmbyRawItem? seriesItem) {
  if (item.Type != 'Episode') return item.Name;
  final seriesName = item.SeriesName;
  if (seriesName != null && seriesName.isNotEmpty) return seriesName;
  final loadedSeriesName = seriesItem?.Name;
  if (loadedSeriesName != null && loadedSeriesName.isNotEmpty) {
    return loadedSeriesName;
  }
  return item.Name;
}

String? seriesIdForEpisode(EmbyRawItem item, String routeItemId) {
  if (item.Type != 'Episode') return null;
  final seriesId = item.SeriesId;
  if (seriesId != null && seriesId.isNotEmpty) return seriesId;
  if (routeItemId.isNotEmpty && routeItemId != item.Id) return routeItemId;
  return null;
}


Map<String, String> lowercaseProviderIds(Map<String, String> ids) {
  return {
    for (final e in ids.entries)
      if (e.key.isNotEmpty && e.value.isNotEmpty) e.key.toLowerCase(): e.value,
  };
}

List<String> extractGenres(EmbyRawItem item) {
  final genresRaw = item.extra['Genres'];
  if (genresRaw is List) {
    return genresRaw.whereType<String>().where((g) => g.isNotEmpty).toList();
  }
  return const [];
}

double? detailProgressPercent(EmbyRawItem item) {
  final percent = playbackProgress(item) * 100;
  return percent < 1 ? null : percent;
}

String tmdbIdFromDetailItem(EmbyRawItem item) => tmdbIdFromItem(item);

TmdbMediaRef? tmdbMediaRefFor(EmbyRawItem item, EmbyRawItem? tmdbSeriesItem) {
  final String mediaType;
  final String tmdbId;
  switch (item.Type) {
    case 'Movie':
      mediaType = 'movie';
      tmdbId = tmdbIdFromDetailItem(item);
    case 'Series':
      mediaType = 'tv';
      tmdbId = tmdbIdFromDetailItem(item);
    case 'Episode':
      final seriesItem = tmdbSeriesItem;
      if (seriesItem == null) return null;
      mediaType = 'tv';
      tmdbId = tmdbIdFromDetailItem(seriesItem);
    default:
      return null;
  }
  if (tmdbId.isEmpty) return null;
  return TmdbMediaRef(id: tmdbId, mediaType: mediaType);
}

CrossServerSearchReq? buildCrossServerReqForDetail(
  EmbyRawItem displayItem,
  EmbyRawItem? seriesItem,
) {
  final providerIds = providerIdsOfItem(displayItem);
  if (displayItem.Type == 'Movie') {
    if (providerIds.isEmpty && displayItem.Name.isEmpty) return null;
    return CrossServerSearchReq(
      anchorType: 'Movie',
      itemName: displayItem.Name,
      providerIds: providerIds,
    );
  }
  if (displayItem.Type == 'Episode') {
    return buildEpisodeCrossServerReq(
      episode: displayItem,
      seriesItem: seriesItem,
    );
  }
  return null;
}
