import 'package:flutter/material.dart';

import 'theme.dart';

/// Marks the edges of a horizontal scrollable that have more content beyond
/// them, so it is obvious the row scrolls.
///
/// Wrap directly around a horizontal [SingleChildScrollView] or [ListView].
/// Each overflowing edge gets a soft scrim in the surface colour — the chips
/// appear to slide *under* it — topped by a chevron pointing outward. The
/// scrim only shows while content remains beyond that edge; it disappears once
/// the row reaches that end (or does not overflow at all). Edge state is
/// tracked per logical side (start/end) and mapped to physical left/right via
/// [Directionality], so RTL mirrors correctly.
class EdgeFade extends StatefulWidget {
  const EdgeFade({super.key, required this.child, this.scrimWidth = 40});

  /// The horizontal scrollable to mark.
  final Widget child;

  /// Width of each edge scrim in logical pixels.
  final double scrimWidth;

  @override
  State<EdgeFade> createState() => EdgeFadeState();
}

class EdgeFadeState extends State<EdgeFade> {
  bool _fadeStart = false;
  bool _fadeEnd = false;

  /// Whether the physical left edge currently shows a scroll cue.
  @visibleForTesting
  bool get fadeLeft => _isRtl ? _fadeEnd : _fadeStart;

  /// Whether the physical right edge currently shows a scroll cue.
  @visibleForTesting
  bool get fadeRight => _isRtl ? _fadeStart : _fadeEnd;

  bool get _isRtl => Directionality.of(context) == TextDirection.rtl;

  bool _onMetrics(ScrollMetrics metrics) {
    if (metrics.axis != Axis.horizontal) return false;
    final start = metrics.extentBefore > 0.5;
    final end = metrics.extentAfter > 0.5;
    if (start != _fadeStart || end != _fadeEnd) {
      setState(() {
        _fadeStart = start;
        _fadeEnd = end;
      });
    }
    return false;
  }

  @override
  Widget build(BuildContext context) {
    final surface = Theme.of(context).scaffoldBackgroundColor;
    return NotificationListener<ScrollMetricsNotification>(
      onNotification: (n) => n.depth == 0 ? _onMetrics(n.metrics) : false,
      child: NotificationListener<ScrollNotification>(
        onNotification: (n) => n.depth == 0 ? _onMetrics(n.metrics) : false,
        child: Stack(
          children: [
            widget.child,
            if (fadeLeft)
              _EdgeCue(
                left: true,
                width: widget.scrimWidth,
                surface: surface,
              ),
            if (fadeRight)
              _EdgeCue(
                left: false,
                width: widget.scrimWidth,
                surface: surface,
              ),
          ],
        ),
      ),
    );
  }
}

/// A gradient scrim over one physical edge of the row, opaque at the very edge
/// and fading inward, with a chevron pointing outward toward the hidden chips.
/// Ignores pointers so taps still reach the chip underneath.
class _EdgeCue extends StatelessWidget {
  const _EdgeCue({
    required this.left,
    required this.width,
    required this.surface,
  });

  final bool left;
  final double width;
  final Color surface;

  @override
  Widget build(BuildContext context) {
    return Positioned(
      top: 0,
      bottom: 0,
      left: left ? 0 : null,
      right: left ? null : 0,
      width: width,
      child: IgnorePointer(
        child: Container(
          alignment: left ? Alignment.centerLeft : Alignment.centerRight,
          decoration: BoxDecoration(
            gradient: LinearGradient(
              begin: left ? Alignment.centerLeft : Alignment.centerRight,
              end: left ? Alignment.centerRight : Alignment.centerLeft,
              colors: [surface, surface.withValues(alpha: 0)],
            ),
          ),
          child: Icon(
            left ? Icons.chevron_left : Icons.chevron_right,
            size: 22,
            color: seedMuted,
          ),
        ),
      ),
    );
  }
}
