import 'dart:math';

import 'package:aves/model/entry/entry.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/widgets/common/behaviour/known_extent_scroll_physics.dart';
import 'package:aves/widgets/common/grid/theme.dart';
import 'package:aves/widgets/common/thumbnail/decorated.dart';
import 'package:flutter/material.dart';

// ✅ REMOTE support
import 'package:aves/remote/remote_origin.dart';
import 'package:aves/remote/remote_image_tile.dart';

class ThumbnailScroller extends StatefulWidget {
  final double availableWidth;
  final int entryCount;
  final AvesEntry? Function(int index) entryBuilder;
  final ValueNotifier<int?> indexNotifier;
  final void Function(int index)? onTap;
  final Object? Function(AvesEntry entry)? heroTagger;
  final bool scrollable, highlightable, showLocation;

  const ThumbnailScroller({
    super.key,
    required this.availableWidth,
    required this.entryCount,
    required this.entryBuilder,
    required this.indexNotifier,
    this.onTap,
    this.heroTagger,
    this.highlightable = false,
    this.showLocation = true,
    this.scrollable = true,
  });

  @override
  State<ThumbnailScroller> createState() => _ThumbnailScrollerState();

  static double get preferredHeight => _ThumbnailScrollerState.thumbnailExtent;
}

class _ThumbnailScrollerState extends State<ThumbnailScroller> {
  final ValueNotifier<bool> _cancellableNotifier = ValueNotifier(true);
  late ScrollController _scrollController;
  bool _isAnimating = false, _isScrolling = false;

  static const double thumbnailExtent = 48;
  static const double separatorWidth = 2;
  static const double itemExtent = thumbnailExtent + separatorWidth;

  int get entryCount => widget.entryCount;

  ValueNotifier<int?> get indexNotifier => widget.indexNotifier;

  bool get scrollable => widget.scrollable;

  static double widthFor(int pageCount) =>
      pageCount == 0 ? 0 : pageCount * thumbnailExtent + (pageCount - 1) * separatorWidth;

  @override
  void initState() {
    super.initState();
    _registerWidget(widget);
  }

  @override
  void didUpdateWidget(covariant ThumbnailScroller oldWidget) {
    super.didUpdateWidget(oldWidget);

    if (oldWidget.indexNotifier != widget.indexNotifier) {
      _unregisterWidget(oldWidget);
      _registerWidget(widget);
    }
  }

  @override
  void dispose() {
    _unregisterWidget(widget);
    _cancellableNotifier.dispose();
    super.dispose();
  }

  void _registerWidget(ThumbnailScroller widget) {
    final scrollOffset = indexToScrollOffset(indexNotifier.value ?? 0);
    _scrollController = ScrollController(initialScrollOffset: scrollOffset);
    _scrollController.addListener(_onScrollChanged);
    widget.indexNotifier.addListener(_onIndexChanged);
  }

  void _unregisterWidget(ThumbnailScroller widget) {
    _scrollController.removeListener(_onScrollChanged);
    _scrollController.dispose();
    widget.indexNotifier.removeListener(_onIndexChanged);
  }

  @override
  Widget build(BuildContext context) {
    final marginWidth = max(0.0, (widget.availableWidth - thumbnailExtent) / 2 - separatorWidth);
    final padding = scrollable
        ? EdgeInsets.only(left: marginWidth + separatorWidth, right: marginWidth)
        : EdgeInsets.zero;

    return GridTheme(
      extent: thumbnailExtent,
      showLocation: widget.showLocation,
      showTrash: false,
      child: SizedBox(
        width: scrollable ? null : widthFor(entryCount),
        height: thumbnailExtent,
        child: ListView.builder(
          scrollDirection: Axis.horizontal,
          controller: _scrollController,
          physics: scrollable
              ? KnownExtentScrollPhysics(
                  indexToScrollOffset: indexToScrollOffset,
                  scrollOffsetToIndex: scrollOffsetToIndex,
                )
              : const NeverScrollableScrollPhysics(),
          padding: padding,
          itemExtent: itemExtent,
          itemBuilder: (context, index) => _buildThumbnail(index),
          itemCount: entryCount,
        ),
      ),
    );
  }

  Widget _buildThumbnail(int index) {
    final pageEntry = widget.entryBuilder(index);
    if (pageEntry == null) return const SizedBox();

    return Stack(
      children: [
        GestureDetector(
          onTap: () {
            indexNotifier.value = index;
            widget.onTap?.call(index);
          },
          child: _buildThumbImage(pageEntry),
        ),
        IgnorePointer(
          child: ValueListenableBuilder<int?>(
            valueListenable: indexNotifier,
            builder: (context, currentIndex, child) {
              return AnimatedContainer(
                color: currentIndex == index ? Colors.transparent : Colors.black45,
                width: thumbnailExtent,
                height: thumbnailExtent,
                duration: ADurations.thumbnailScrollerShadeAnimation,
              );
            },
          ),
        ),
      ],
    );
  }

  // ✅ NEW: thumbnail remoto vs locale
  Widget _buildThumbImage(AvesEntry entry) {
    // REMOTE: usa RemoteImageTile (con stessa size della scroller)
    if (entry.origin == RemoteOrigin.value) {
      return SizedBox(
        width: thumbnailExtent,
        height: thumbnailExtent,
        child: RemoteImageTile(
          entry: entry,
          borderRadius: 0,
          fit: BoxFit.cover,
        ),
      );
    }

    // LOCALE: comportamento originale
    return DecoratedThumbnail(
      entry: entry,
      tileExtent: thumbnailExtent,
      cancellableNotifier: _cancellableNotifier,
      selectable: false,
      highlightable: widget.highlightable,
      heroTagger: () => widget.heroTagger?.call(entry),
    );
  }

  Future<void> _goTo(int index) async {
    if (!scrollable) return;

    final targetOffset = indexToScrollOffset(index);
    final offsetDelta = (targetOffset - _scrollController.offset).abs();

    if (offsetDelta > widget.availableWidth * 2) {
      _scrollController.jumpTo(targetOffset);
    } else {
      _isAnimating = true;
      await _scrollController.animateTo(
        targetOffset,
        duration: ADurations.thumbnailScrollerScrollAnimation,
        curve: Curves.easeOutCubic,
      );
      _isAnimating = false;
    }
  }

  void _onScrollChanged() {
    if (!_isAnimating) {
      final index = scrollOffsetToIndex(_scrollController.offset);
      if (indexNotifier.value != index) {
        _isScrolling = true;
        indexNotifier.value = index;
      }
    }
  }

  void _onIndexChanged() {
    if (!_isScrolling && !_isAnimating) {
      final index = indexNotifier.value;
      if (index != null) {
        _goTo(index);
      }
    }
    _isScrolling = false;
  }

  double indexToScrollOffset(int index) => index * itemExtent;

  int scrollOffsetToIndex(double offset) => (offset / itemExtent).round();
}
