import 'dart:async';
import 'dart:ui' show lerpDouble;

import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:kasy_kit/core/haptics/haptic_feedback_notifier.dart';

/// Press-in with slight overshoot-back (same tactility as [KasyAlert] actions).
///
/// No Material ripple. Optional [pressOverlayColor] + [clipBorderRadius]:
/// clarão rápido no tap (véu), não enquanto o dedo apenas descansa em cima.
/// Também expõe semântica para TalkBack/VoiceOver e haptic leve opcional ([hapticFeedbackEnabled]).
class KasyPressableDepth extends ConsumerStatefulWidget {
  final Widget child;
  final VoidCallback onPressed;
  final String semanticLabel;

  /// Breve clarão no tap (véu translúcido); não durante o só pressionar.
  final Color? pressOverlayColor;

  /// Required with [pressOverlayColor] when the surface has rounded clips (pill, etc.).
  final BorderRadius? clipBorderRadius;

  /// Se false, não chama [HapticFeedback.lightImpact] no tap.
  final bool hapticFeedbackEnabled;

  const KasyPressableDepth({
    super.key,
    required this.child,
    required this.onPressed,
    required this.semanticLabel,
    this.pressOverlayColor,
    this.clipBorderRadius,
    this.hapticFeedbackEnabled = true,
  });

  @override
  ConsumerState<KasyPressableDepth> createState() => _KasyPressableDepthState();
}

class _KasyPressableDepthState extends ConsumerState<KasyPressableDepth>
    with SingleTickerProviderStateMixin {
  static const double _pressIn = 0.992;
  static const double _releasePeak = 1.002;
  late final AnimationController _depthController;
  Timer? _veilTimer;
  bool _veilVisible = false;

  bool get _useVeil =>
      widget.pressOverlayColor != null && widget.clipBorderRadius != null;

  @override
  void initState() {
    super.initState();
    _depthController =
        AnimationController(
          vsync: this,
          duration: const Duration(milliseconds: 300),
        )..addListener(() {
          setState(() {});
        });
  }

  @override
  void dispose() {
    _veilTimer?.cancel();
    _depthController.dispose();
    super.dispose();
  }

  double get _depthScale {
    final double t = _depthController.value.clamp(0.0, 1.0);
    if (t <= 0.28) {
      return lerpDouble(1.0, _pressIn, t / 0.28)!;
    }
    if (t <= 0.55) {
      return lerpDouble(_pressIn, _releasePeak, (t - 0.28) / 0.27)!;
    }
    return lerpDouble(_releasePeak, 1.0, (t - 0.55) / 0.45)!;
  }

  void _handleTap() {
    if (widget.hapticFeedbackEnabled && ref.read(hapticFeedbackProvider)) {
      HapticFeedback.lightImpact();
    }
    _flashVeil();
    widget.onPressed();
    _depthController.forward(from: 0).whenComplete(() {
      if (mounted) {
        _depthController.reset();
      }
    });
  }

  void _flashVeil() {
    if (!_useVeil) {
      return;
    }
    _veilTimer?.cancel();
    setState(() => _veilVisible = true);
    _veilTimer = Timer(const Duration(milliseconds: 110), () {
      if (!mounted) {
        return;
      }
      setState(() => _veilVisible = false);
    });
  }

  Widget _wrapScaledChild(Widget rawChild) {
    if (!_useVeil) {
      return Transform.scale(scale: _depthScale, child: rawChild);
    }

    final Widget pressVeil = AnimatedOpacity(
      duration: const Duration(milliseconds: 90),
      curve: Curves.easeOutCubic,
      opacity: _veilVisible ? 1.0 : 0.0,
      child: IgnorePointer(child: ColoredBox(color: widget.pressOverlayColor!)),
    );

    return Transform.scale(
      scale: _depthScale,
      child: ClipRRect(
        borderRadius: widget.clipBorderRadius!,
        child: Stack(
          fit: StackFit.passthrough,
          children: <Widget>[
            rawChild,
            Positioned.fill(child: pressVeil),
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final Widget inner = Semantics(
      button: true,
      enabled: true,
      label: widget.semanticLabel,
      onTap: _handleTap,
      child: GestureDetector(
        behavior: HitTestBehavior.opaque,
        excludeFromSemantics: true,
        onTap: _handleTap,
        child: ConstrainedBox(
          constraints: const BoxConstraints(minWidth: 44, minHeight: 44),
          child: Center(child: _wrapScaledChild(widget.child)),
        ),
      ),
    );

    if (!kIsWeb) return inner;

    // On web: show pointer cursor only — no hover highlight.
    return MouseRegion(cursor: SystemMouseCursors.click, child: inner);
  }
}
