import 'dart:async';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';

import '../../../core/contracts/tmdb.dart';
import '../../../shared/mappers/tmdb_image_url.dart';
import '../../../shared/widgets/banner_carousel_mixin.dart';
import '../../../shared/widgets/banner_carousel_scaffold.dart';
import '../discover_helpers.dart';


class TmdbBannerCarousel extends StatefulWidget {
  final List<TmdbRecommendation> items;
  final String imageBaseUrl;
  final ValueChanged<TmdbRecommendation> onItemTap;
  final ValueChanged<TmdbRecommendation>? onActiveItemChanged;

  const TmdbBannerCarousel({
    super.key,
    required this.items,
    required this.imageBaseUrl,
    required this.onItemTap,
    this.onActiveItemChanged,
  });

  @override
  State<TmdbBannerCarousel> createState() => _TmdbBannerCarouselState();
}

class _TmdbBannerCarouselState extends State<TmdbBannerCarousel>
    with WidgetsBindingObserver, BannerCarouselMixin<TmdbBannerCarousel> {
  @override
  int get itemCount => widget.items.length;

  @override
  bool get isActive => true;

  @override
  void emitActiveItem() {
    if (widget.items.isEmpty) return;
    widget.onActiveItemChanged?.call(widget.items[currentIndex]);
  }

  @override
  void precacheAdjacentSlides() {
    if (!mounted || widget.items.length <= 1) return;
    final next = (currentIndex + 1) % widget.items.length;
    final nextUrl = TmdbImageUrl.backdrop(
      widget.imageBaseUrl,
      widget.items[next].backdropPath,
    );
    if (nextUrl == null) return;
    final cacheWidth = bannerCacheWidth();
    unawaited(
      precacheImage(
        ResizeImage.resizeIfNeeded(
          cacheWidth,
          null,
          CachedNetworkImageProvider(nextUrl),
        ),
        context,
        onError: (_, _) {},
      ),
    );
  }

  @override
  void didUpdateWidget(covariant TmdbBannerCarousel oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.items != widget.items) {
      resetCarouselItems();
    }
  }

  BannerSlideData _slideDataFor(TmdbRecommendation item) {
    final typeLabel = _mediaTypeLabel(item.mediaType);
    return BannerSlideData(
      imageUrl: TmdbImageUrl.backdrop(widget.imageBaseUrl, item.backdropPath),
      title: item.title,
      overview: item.overview,
      rating: (item.voteAverage != null && item.voteAverage! > 0)
          ? item.voteAverage!.toStringAsFixed(1)
          : null,
      primaryMetaLabels: [if (typeLabel != null) typeLabel],
    );
  }

  @override
  Widget build(BuildContext context) {
    return BannerCarouselScaffold(
      controller: this,
      slides: [for (final item in widget.items) _slideDataFor(item)],
      onSlideTap: (index) => widget.onItemTap(widget.items[index]),
    );
  }

  static String? _mediaTypeLabel(String? type) => mediaTypeLabel(type);
}
