import 'package:flutter/material.dart';
import '../constants/design_system.dart';

/// Transitions de page personnalisées pour une navigation fluide
///
/// Utilisez ces transitions au lieu de MaterialPageRoute standard
/// pour une meilleure expérience utilisateur.
///
/// **Types de transitions:**
/// - Fade: Fondu simple
/// - Slide: Glissement depuis une direction
/// - Scale: Zoom in/out
/// - Rotation: Rotation 3D
/// - SlideFromBottom: Bottom sheet style

/// Énumération des types de transitions
enum PageTransitionType {
  fade,
  slideRight,
  slideLeft,
  slideUp,
  slideDown,
  scale,
  rotation,
  fadeScale,
}

/// Route personnalisée avec transitions fluides
class CustomPageRoute<T> extends PageRoute<T> {
  CustomPageRoute({
    required this.builder,
    this.transitionType = PageTransitionType.slideRight,
    this.duration,
    this.reverseDuration,
    this.curve,
    this.reverseCurve,
    super.settings,
  });

  final WidgetBuilder builder;
  final PageTransitionType transitionType;
  final Duration? duration;
  final Duration? reverseDuration;
  final Curve? curve;
  final Curve? reverseCurve;

  @override
  Color? get barrierColor => null;

  @override
  String? get barrierLabel => null;

  @override
  bool get maintainState => true;

  @override
  Duration get transitionDuration =>
      duration ?? DesignSystem.durationMedium;

  @override
  Duration get reverseTransitionDuration =>
      reverseDuration ?? DesignSystem.durationMedium;

  @override
  Widget buildPage(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
  ) {
    return builder(context);
  }

  @override
  Widget buildTransitions(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
    Widget child,
  ) {
    final effectiveCurve = curve ?? DesignSystem.curveDecelerate;
    final effectiveReverseCurve = reverseCurve ?? DesignSystem.curveDecelerate;

    final curvedAnimation = CurvedAnimation(
      parent: animation,
      curve: effectiveCurve,
      reverseCurve: effectiveReverseCurve,
    );

    switch (transitionType) {
      case PageTransitionType.fade:
        return FadeTransition(
          opacity: curvedAnimation,
          child: child,
        );

      case PageTransitionType.slideRight:
        return SlideTransition(
          position: Tween<Offset>(
            begin: const Offset(1, 0),
            end: Offset.zero,
          ).animate(curvedAnimation),
          child: child,
        );

      case PageTransitionType.slideLeft:
        return SlideTransition(
          position: Tween<Offset>(
            begin: const Offset(-1, 0),
            end: Offset.zero,
          ).animate(curvedAnimation),
          child: child,
        );

      case PageTransitionType.slideUp:
        return SlideTransition(
          position: Tween<Offset>(
            begin: const Offset(0, 1),
            end: Offset.zero,
          ).animate(curvedAnimation),
          child: child,
        );

      case PageTransitionType.slideDown:
        return SlideTransition(
          position: Tween<Offset>(
            begin: const Offset(0, -1),
            end: Offset.zero,
          ).animate(curvedAnimation),
          child: child,
        );

      case PageTransitionType.scale:
        return ScaleTransition(
          scale: Tween<double>(
            begin: 0.0,
            end: 1.0,
          ).animate(curvedAnimation),
          child: FadeTransition(
            opacity: curvedAnimation,
            child: child,
          ),
        );

      case PageTransitionType.rotation:
        return RotationTransition(
          turns: Tween<double>(
            begin: 0.0,
            end: 1.0,
          ).animate(curvedAnimation),
          child: FadeTransition(
            opacity: curvedAnimation,
            child: child,
          ),
        );

      case PageTransitionType.fadeScale:
        return FadeTransition(
          opacity: curvedAnimation,
          child: ScaleTransition(
            scale: Tween<double>(
              begin: 0.95,
              end: 1.0,
            ).animate(curvedAnimation),
            child: child,
          ),
        );
    }
  }
}

/// Extension pour faciliter la navigation avec transitions
extension NavigatorExtensions on BuildContext {
  /// Navigate avec fade transition
  Future<T?> pushFade<T>(Widget page) {
    return Navigator.of(this).push<T>(
      CustomPageRoute(
        builder: (_) => page,
        transitionType: PageTransitionType.fade,
      ),
    );
  }

  /// Navigate avec slide from right
  Future<T?> pushSlideRight<T>(Widget page) {
    return Navigator.of(this).push<T>(
      CustomPageRoute(
        builder: (_) => page,
        transitionType: PageTransitionType.slideRight,
      ),
    );
  }

  /// Navigate avec slide from left
  Future<T?> pushSlideLeft<T>(Widget page) {
    return Navigator.of(this).push<T>(
      CustomPageRoute(
        builder: (_) => page,
        transitionType: PageTransitionType.slideLeft,
      ),
    );
  }

  /// Navigate avec slide from bottom
  Future<T?> pushSlideUp<T>(Widget page) {
    return Navigator.of(this).push<T>(
      CustomPageRoute(
        builder: (_) => page,
        transitionType: PageTransitionType.slideUp,
        curve: DesignSystem.curveSharp,
      ),
    );
  }

  /// Navigate avec scale transition
  Future<T?> pushScale<T>(Widget page) {
    return Navigator.of(this).push<T>(
      CustomPageRoute(
        builder: (_) => page,
        transitionType: PageTransitionType.scale,
      ),
    );
  }

  /// Navigate avec fade + scale (élégant)
  Future<T?> pushFadeScale<T>(Widget page) {
    return Navigator.of(this).push<T>(
      CustomPageRoute(
        builder: (_) => page,
        transitionType: PageTransitionType.fadeScale,
      ),
    );
  }

  /// Navigate et remplace avec transition
  Future<T?> pushReplacementFade<T, TO>(Widget page) {
    return Navigator.of(this).pushReplacement<T, TO>(
      CustomPageRoute(
        builder: (_) => page,
        transitionType: PageTransitionType.fade,
      ),
    );
  }
}

/// Transition de Hero personnalisée
///
/// Pour des animations de shared element plus fluides.
class CustomHeroTransition extends RectTween {
  CustomHeroTransition({
    required Rect? begin,
    required Rect? end,
  }) : super(begin: begin, end: end);

  @override
  Rect? lerp(double t) {
    final elasticCurveValue = Curves.easeInOutCubic.transform(t);
    return Rect.fromLTRB(
      lerpDouble(begin!.left, end!.left, elasticCurveValue),
      lerpDouble(begin!.top, end!.top, elasticCurveValue),
      lerpDouble(begin!.right, end!.right, elasticCurveValue),
      lerpDouble(begin!.bottom, end!.bottom, elasticCurveValue),
    );
  }

  double lerpDouble(double a, double b, double t) {
    return a + (b - a) * t;
  }
}

/// Bottom sheet avec animation personnalisée
Future<T?> showCustomBottomSheet<T>({
  required BuildContext context,
  required Widget Function(BuildContext) builder,
  bool isScrollControlled = true,
  bool useRootNavigator = false,
  bool isDismissible = true,
  Color? backgroundColor,
  double? elevation,
}) {
  return showModalBottomSheet<T>(
    context: context,
    builder: builder,
    isScrollControlled: isScrollControlled,
    useRootNavigator: useRootNavigator,
    isDismissible: isDismissible,
    backgroundColor: backgroundColor ?? Colors.transparent,
    elevation: elevation ?? 0,
    shape: const RoundedRectangleBorder(
      borderRadius: BorderRadius.vertical(
        top: Radius.circular(DesignSystem.radiusXl),
      ),
    ),
    transitionAnimationController: _createBottomSheetController(context),
  );
}

AnimationController _createBottomSheetController(BuildContext context) {
  return BottomSheet.createAnimationController(Navigator.of(context))
    ..duration = DesignSystem.durationMedium
    ..reverseDuration = DesignSystem.durationFast;
}

/// Dialog avec animation personnalisée
Future<T?> showCustomDialog<T>({
  required BuildContext context,
  required Widget child,
  bool barrierDismissible = true,
  Color? barrierColor,
  String? barrierLabel,
}) {
  return showGeneralDialog<T>(
    context: context,
    barrierDismissible: barrierDismissible,
    barrierColor: barrierColor ?? Colors.black54,
    barrierLabel: barrierLabel,
    transitionDuration: DesignSystem.durationMedium,
    transitionBuilder: (context, animation, secondaryAnimation, child) {
      return ScaleTransition(
        scale: Tween<double>(
          begin: 0.8,
          end: 1.0,
        ).animate(
          CurvedAnimation(
            parent: animation,
            curve: DesignSystem.curveDecelerate,
          ),
        ),
        child: FadeTransition(
          opacity: animation,
          child: child,
        ),
      );
    },
    pageBuilder: (context, animation, secondaryAnimation) {
      return child;
    },
  );
}

/// Shared Element Transition (Hero avec contrôle fin)
class SharedElementTransition extends StatelessWidget {
  const SharedElementTransition({
    required this.tag,
    required this.child,
    this.transitionOnUserGestures = false,
    super.key,
  });

  final Object tag;
  final Widget child;
  final bool transitionOnUserGestures;

  @override
  Widget build(BuildContext context) {
    return Hero(
      tag: tag,
      transitionOnUserGestures: transitionOnUserGestures,
      flightShuttleBuilder: (
        flightContext,
        animation,
        flightDirection,
        fromHeroContext,
        toHeroContext,
      ) {
        final Hero toHero = toHeroContext.widget as Hero;
        return ScaleTransition(
          scale: Tween<double>(
            begin: 0.95,
            end: 1.0,
          ).animate(
            CurvedAnimation(
              parent: animation,
              curve: DesignSystem.curveDecelerate,
            ),
          ),
          child: toHero.child,
        );
      },
      child: child,
    );
  }
}
