import 'dart:async';

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

import '../../../core/contracts/library.dart';
import '../../../shared/constants/breakpoints.dart';
import '../../../shared/mappers/media_image_url.dart';
import '../../../shared/widgets/banner_carousel_mixin.dart';
import '../../../shared/widgets/banner_carousel_scaffold.dart';


class HomeBannerCarousel extends StatefulWidget {
  final String baseUrl;
  final String token;
  final List<EmbyRawItem> items;
  final Map<String, String>? imageHeaders;
  final ValueChanged<EmbyRawItem> onItemTap;
  final ValueChanged<EmbyRawItem>? onActiveItemChanged;
  final bool active;

  const HomeBannerCarousel({
    super.key,
    required this.baseUrl,
    required this.token,
    required this.items,
    required this.onItemTap,
    this.imageHeaders,
    this.onActiveItemChanged,
    this.active = true,
  });

  @override
  State<HomeBannerCarousel> createState() => _HomeBannerCarouselState();
}

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

  @override
  bool get isActive => widget.active;

  @override
  void emitActiveItem() {
    if (!mounted || !widget.active) return;
    if (widget.items.isEmpty) return;
    final safeIndex = currentIndex.clamp(0, widget.items.length - 1);
    widget.onActiveItemChanged?.call(widget.items[safeIndex]);
  }

  @override
  void precacheAdjacentSlides() {
    if (!mounted || !widget.active || widget.items.length <= 1) return;
    final next = (currentIndex + 1) % widget.items.length;
    final nextLogo = _logoUrl(widget.items[next]);
    final cacheWidth = bannerCacheWidth();

    void precacheUrl(String url, {int? cacheWidth}) {
      unawaited(
        precacheImage(
          ResizeImage.resizeIfNeeded(
            cacheWidth,
            null,
            CachedNetworkImageProvider(url, headers: widget.imageHeaders),
          ),
          context,
          onError: (_, _) {},
        ),
      );
    }

    precacheUrl(
      EmbyImageUrl.detailBanner(
        baseUrl: widget.baseUrl,
        token: widget.token,
        item: widget.items[next],
      ),
      cacheWidth: cacheWidth,
    );
    if (nextLogo != null) precacheUrl(nextLogo, cacheWidth: 960);
  }

  @override
  void didUpdateWidget(covariant HomeBannerCarousel oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.items != widget.items) {
      resetCarouselItems();
    }
    if (oldWidget.active != widget.active) {
      widget.active ? activateCarousel() : deactivateCarousel();
    }
  }

  BannerSlideData _slideDataFor(EmbyRawItem item) {
    final fallbackItemId = (item.SeriesId?.isNotEmpty ?? false)
        ? item.SeriesId!
        : item.Id;
    final genres =
        (item.extra['Genres'] as List?)?.cast<String>().take(2).toList() ??
        const <String>[];
    return BannerSlideData(
      imageUrl: EmbyImageUrl.detailBanner(
        baseUrl: widget.baseUrl,
        token: widget.token,
        item: item,
      ),
      fallbackImageUrl: EmbyImageUrl.fanart(
        baseUrl: widget.baseUrl,
        token: widget.token,
        itemId: fallbackItemId,
      ),
      imageHeaders: widget.imageHeaders,
      logoUrl: _logoUrl(item),
      title: item.Name,
      overview: item.Overview,
      rating: item.CommunityRating?.toStringAsFixed(1),
      primaryMetaLabels: [
        if (item.ProductionYear != null) item.ProductionYear!.toString(),
      ],
      secondaryMetaLabels: genres,
    );
  }

  String? _logoUrl(EmbyRawItem item) {
    final logoItemId = (item.SeriesId?.isNotEmpty ?? false)
        ? item.SeriesId!
        : item.Id;
    return EmbyImageUrl.logo(
      baseUrl: widget.baseUrl,
      token: widget.token,
      itemId: logoItemId,
      tag: logoItemId == item.Id ? (item.ImageTags?['Logo']) : null,
    );
  }

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


class HomeBannerSkeleton extends StatelessWidget {
  const HomeBannerSkeleton({super.key});

  @override
  Widget build(BuildContext context) {
    final compact = Breakpoints.isCompact(MediaQuery.sizeOf(context).width);
    if (compact) {
      final height = MediaQuery.sizeOf(context).height * 0.55;
      return SizedBox(height: height);
    }
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 24),
      child: LayoutBuilder(
        builder: (context, constraints) {
          final height = (constraints.maxWidth * 7 / 16).clamp(260.0, 500.0);
          return SizedBox(height: height);
        },
      ),
    );
  }
}
