import 'dart:async';
import 'package:flutter/material.dart';
import 'package:infinite_carousel/infinite_carousel.dart';
import '../../voucher/sub_widget/voucher_section_title.dart';
import '../models/banner_model.dart';
import '../models/main_section_config_model.dart';

class BannerCarousel extends StatefulWidget {
  final List<BannerModel> banners;
  final MainSectionConfigModel? sectionConfig;
  final void Function(BannerModel)? onTap;

  const BannerCarousel({super.key, required this.banners, this.sectionConfig, this.onTap});

  @override
  State<BannerCarousel> createState() => _BannerCarouselState();
}

class _BannerCarouselState extends State<BannerCarousel> {
  late InfiniteScrollController _controller;
  int _currentIndex = 0;
  Timer? _autoPlayTimer;
  final bool _isDragging = false;
  bool _isUserScrolling = false;
  double? _firstBannerAspectRatio; // height / width
  String? _aspectRatioSourceUrl;
  static const double _defaultAspectRatio = 535 / 1125;

  @override
  void initState() {
    super.initState();
    _controller = InfiniteScrollController(initialItem: 0);
    _startAutoPlay();
    _resolveFirstBannerAspectRatio();
  }

  void _startAutoPlay() {
    _autoPlayTimer?.cancel();
    _autoPlayTimer = Timer.periodic(const Duration(seconds: 2), (_) {
      if (!_isDragging && !_isUserScrolling) {
        _controller.nextItem(duration: const Duration(milliseconds: 500));
      }
    });
  }

  void _pauseAutoPlayTemporarily() {
    _isUserScrolling = true;
    _autoPlayTimer?.cancel();
    Future.delayed(const Duration(seconds: 1), () {
      _isUserScrolling = false;
      _startAutoPlay();
    });
  }

  @override
  void dispose() {
    _autoPlayTimer?.cancel();
    _controller.dispose();
    super.dispose();
  }

  @override
  void didUpdateWidget(covariant BannerCarousel oldWidget) {
    super.didUpdateWidget(oldWidget);
    final oldUrl = oldWidget.banners.isNotEmpty ? oldWidget.banners.first.itemImage : null;
    final newUrl = widget.banners.isNotEmpty ? widget.banners.first.itemImage : null;
    if (oldUrl != newUrl) {
      _firstBannerAspectRatio = null;
      _aspectRatioSourceUrl = null;
      _resolveFirstBannerAspectRatio();
    }
  }

  void _resolveFirstBannerAspectRatio() {
    if (widget.banners.isEmpty) return;
    final url = widget.banners.first.itemImage;
    if ((url ?? '').isEmpty || url == _aspectRatioSourceUrl) {
      return;
    }
    _aspectRatioSourceUrl = url;
    final provider = NetworkImage(url!);
    final stream = provider.resolve(const ImageConfiguration());
    late ImageStreamListener listener;
    listener = ImageStreamListener(
      (info, _) {
        final ratio = info.image.height / info.image.width;
        if (mounted) {
          setState(() {
            _firstBannerAspectRatio = ratio;
          });
        }
        stream.removeListener(listener);
      },
      onError: (_, _) {
        stream.removeListener(listener);
      },
    );
    stream.addListener(listener);
  }

  void _handleTapRightButton() {
    widget.sectionConfig?.buttonViewAll?.directionalScreen?.begin();
  }

  double _currentBannerAspectRatio() {
    return _firstBannerAspectRatio ?? _defaultAspectRatio;
  }

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.of(context).size.width * 0.9;
    final height = width * _currentBannerAspectRatio() + 16;
    return Column(
      children: [
        if ((widget.sectionConfig?.name ?? "").isNotEmpty)
          HeaderSectionTitle(
            title: widget.sectionConfig?.name ?? "",
            onViewAll: widget.sectionConfig?.buttonViewAll?.directionalScreen != null ? _handleTapRightButton : null,
          ),
        if (widget.banners.isNotEmpty)
          GestureDetector(
            onPanDown: (_) => _pauseAutoPlayTemporarily(),
            child: SizedBox(
              // height: width * 135 / 343 + 16,
              height: height,
              child: Stack(
                alignment: Alignment.bottomCenter,
                children: [
                  InfiniteCarousel.builder(
                    itemCount: widget.banners.length,
                    itemExtent: width,
                    scrollBehavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
                    loop: true,
                    center: true,
                    anchor: 0.0,
                    velocityFactor: 0.1,
                    controller: _controller,
                    onIndexChanged: (index) => setState(() => _currentIndex = index % widget.banners.length),
                    itemBuilder: (context, itemIndex, realIndex) {
                      final bannerIndex = itemIndex % widget.banners.length;
                      final ratio = _currentBannerAspectRatio();
                      return GestureDetector(
                        onTap: () => widget.onTap?.call(widget.banners[bannerIndex]),
                        child: Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 8.0),
                          child: AspectRatio(
                            aspectRatio: ratio <= 0 ? 1125 / 535 : 1 / ratio,
                            child: ClipRRect(
                              borderRadius: BorderRadius.circular(12),
                              child: Image.network(
                                widget.banners[bannerIndex].itemImage ?? "",
                                fit: BoxFit.cover,
                                width: double.infinity,
                              ),
                            ),
                          ),
                        ),
                      );
                    },
                  ),
                  Positioned(
                    bottom: 12,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children:
                          widget.banners.asMap().entries.map((entry) {
                            return GestureDetector(
                              onTap:
                                  () =>
                                      _controller.animateToItem(entry.key, duration: const Duration(milliseconds: 500)),
                              child: Container(
                                width: 8.0,
                                height: 8.0,
                                margin: const EdgeInsets.symmetric(horizontal: 4.0),
                                decoration: BoxDecoration(
                                  shape: BoxShape.circle,
                                  color: _currentIndex == entry.key ? Colors.white : Colors.white.withOpacity(0.4),
                                ),
                              ),
                            );
                          }).toList(),
                    ),
                  ),
                ],
              ),
            ),
          ),
      ],
    );
  }
}
