import 'trakt_ids.dart';


class TraktCalendarEntry {

  final DateTime firstAired;


  final String type;

  final String? showTitle;
  final int? showYear;
  final TraktIds? showIds;
  final int? episodeSeason;
  final int? episodeNumber;
  final String? episodeTitle;
  final TraktIds? episodeIds;

  final String? movieTitle;
  final int? movieYear;
  final TraktIds? movieIds;


  final String? posterUrl;

  const TraktCalendarEntry({
    required this.firstAired,
    required this.type,
    this.showTitle,
    this.showYear,
    this.showIds,
    this.episodeSeason,
    this.episodeNumber,
    this.episodeTitle,
    this.episodeIds,
    this.movieTitle,
    this.movieYear,
    this.movieIds,
    this.posterUrl,
  });

  TraktCalendarEntry withPoster(String? url) => TraktCalendarEntry(
    firstAired: firstAired,
    type: type,
    showTitle: showTitle,
    showYear: showYear,
    showIds: showIds,
    episodeSeason: episodeSeason,
    episodeNumber: episodeNumber,
    episodeTitle: episodeTitle,
    episodeIds: episodeIds,
    movieTitle: movieTitle,
    movieYear: movieYear,
    movieIds: movieIds,
    posterUrl: url,
  );

  TraktCalendarEntry withTitle(String title) => TraktCalendarEntry(
    firstAired: firstAired,
    type: type,
    showTitle: type == 'movie' ? showTitle : title,
    showYear: showYear,
    showIds: showIds,
    episodeSeason: episodeSeason,
    episodeNumber: episodeNumber,
    episodeTitle: episodeTitle,
    episodeIds: episodeIds,
    movieTitle: type == 'movie' ? title : movieTitle,
    movieYear: movieYear,
    movieIds: movieIds,
    posterUrl: posterUrl,
  );


  int? get tmdbId => type == 'movie' ? movieIds?.tmdb : showIds?.tmdb;


  String get mediaType => type == 'movie' ? 'movie' : 'tv';


  String get displayTitle =>
      type == 'movie' ? (movieTitle ?? '') : (showTitle ?? '');


  String get displaySubtitle {
    if (type == 'movie') return movieYear?.toString() ?? '';
    final parts = <String>[];
    if (episodeSeason != null && episodeNumber != null) {
      parts.add(
        'S${episodeSeason.toString().padLeft(2, '0')}'
        'E${episodeNumber.toString().padLeft(2, '0')}',
      );
    }
    if (episodeTitle != null && episodeTitle!.isNotEmpty) {
      parts.add(episodeTitle!);
    }
    return parts.join(' · ');
  }


  static TraktCalendarEntry? fromShowJson(Map<String, dynamic> json) {
    final aired = _parseDate(json['first_aired']);
    if (aired == null) return null;

    final show = json['show'];
    final episode = json['episode'];
    if (show is! Map<String, dynamic>) return null;

    return TraktCalendarEntry(
      firstAired: aired,
      type: 'show',
      showTitle: show['title'] as String?,
      showYear: (show['year'] as num?)?.toInt(),
      showIds: TraktIds.fromJson(show['ids']),
      episodeSeason: episode is Map<String, dynamic>
          ? (episode['season'] as num?)?.toInt()
          : null,
      episodeNumber: episode is Map<String, dynamic>
          ? (episode['number'] as num?)?.toInt()
          : null,
      episodeTitle: episode is Map<String, dynamic>
          ? episode['title'] as String?
          : null,
      episodeIds: episode is Map<String, dynamic>
          ? TraktIds.fromJson(episode['ids'])
          : null,
    );
  }


  static TraktCalendarEntry? fromMovieJson(Map<String, dynamic> json) {
    final releasedStr = json['released'] as String?;
    final aired = releasedStr != null && releasedStr.isNotEmpty
        ? DateTime.tryParse(releasedStr)
        : null;
    if (aired == null) return null;

    final movie = json['movie'];
    if (movie is! Map<String, dynamic>) return null;

    return TraktCalendarEntry(
      firstAired: aired,
      type: 'movie',
      movieTitle: movie['title'] as String?,
      movieYear: (movie['year'] as num?)?.toInt(),
      movieIds: TraktIds.fromJson(movie['ids']),
    );
  }
}

DateTime? _parseDate(Object? raw) {
  if (raw is! String || raw.isEmpty) return null;
  return DateTime.tryParse(raw);
}
