import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../providers/settings_provider.dart';
import '../../game/enums.dart';
import '../../game/config.dart';

class BattleAnimationWidget extends StatefulWidget {
  final Widget child;

  const BattleAnimationWidget({super.key, required this.child});

  @override
  BattleAnimationWidgetState createState() => BattleAnimationWidgetState();
}

class BattleAnimationWidgetState extends State<BattleAnimationWidget>
    with TickerProviderStateMixin {
  late AnimationController _scaleController;
  late AnimationController _translateController;
  late Animation<double> _scaleAnimation;
  late Animation<Offset> _translateAnimation;

  @override
  void initState() {
    super.initState();
    _scaleController = AnimationController(
      vsync: this,
      duration: AnimationConfig.attackRiskyScale,
    );
    _translateController = AnimationController(
      vsync: this,
      duration: AnimationConfig.attackRiskyDash,
    );

    _scaleAnimation = Tween<double>(
      begin: 1.0,
      end: 2.0,
    ).animate(CurvedAnimation(parent: _scaleController, curve: Curves.easeOut));

    // Default translation, will be updated on animateAttack
    _translateAnimation = Tween<Offset>(
      begin: Offset.zero,
      end: Offset.zero,
    ).animate(_translateController);
  }

  @override
  void dispose() {
    _scaleController.dispose();
    _translateController.dispose();
    super.dispose();
  }

  Future<void> animateAttack(
    Offset targetOffset,
    VoidCallback onImpact,
    RiskLevel risk, {
    VoidCallback? onAnimationStart,
    VoidCallback? onAnimationMiddle,
    VoidCallback? onAnimationEnd,
  }) async {
    _resetControllers();
    onAnimationStart?.call();

    if (risk == RiskLevel.safe || risk == RiskLevel.normal) {
      final isSafe = risk == RiskLevel.safe;
      final duration = AnimationConfig.getAttackDuration(risk);
      final offsetFactor = isSafe ? 0.2 : 0.5;
      final curve = isSafe
          ? AnimationConfig.attackSafeCurve
          : AnimationConfig.attackNormalCurve;

      _translateController.duration = duration;
      _translateAnimation = Tween<Offset>(
        begin: Offset.zero,
        end: targetOffset * offsetFactor,
      ).animate(CurvedAnimation(parent: _translateController, curve: curve));

      await _translateController.forward();
      if (!mounted) return;

      onAnimationEnd?.call();
      onImpact();

      await _translateController.reverse();
    } else {
      final attackScale = context.read<SettingsProvider>().attackAnimScale;
      _scaleAnimation = Tween<double>(begin: 1.0, end: attackScale).animate(
        CurvedAnimation(parent: _scaleController, curve: Curves.easeOut),
      );

      _scaleController.duration = AnimationConfig.attackRiskyScale;
      _translateController.duration = AnimationConfig.attackRiskyDash;

      await _scaleController.forward();
      if (!mounted) return;

      onAnimationMiddle?.call();

      final adjustedOffset = targetOffset * 0.5;

      _translateAnimation =
          Tween<Offset>(begin: Offset.zero, end: adjustedOffset).animate(
            CurvedAnimation(
              parent: _translateController,
              curve: AnimationConfig.attackRiskyDashCurve,
            ),
          );

      await _translateController.forward();
      if (!mounted) return;

      onAnimationEnd?.call();
      onImpact();

      await Future.wait([
        _scaleController.reverse(),
        _translateController.reverse(),
      ]);
    }
  }

  Future<void> animateDefense(VoidCallback onImpact) async {
    _resetControllers();
    _translateController.duration = const Duration(milliseconds: 800);

    // Sequence: Left -> Right -> Center
    _translateAnimation =
        TweenSequence<Offset>([
          TweenSequenceItem(
            tween: Tween<Offset>(begin: Offset.zero, end: const Offset(-10, 0)),
            weight: 25,
          ),
          TweenSequenceItem(
            tween: Tween<Offset>(
              begin: const Offset(-10, 0),
              end: const Offset(10, 0),
            ),
            weight: 50,
          ),
          TweenSequenceItem(
            tween: Tween<Offset>(begin: const Offset(10, 0), end: Offset.zero),
            weight: 25,
          ),
        ]).animate(
          CurvedAnimation(
            parent: _translateController,
            curve: Curves.easeInOut,
          ),
        );

    await _translateController.forward();
    if (!mounted) return;
    onImpact();
    _translateController.reset();
  }

  void _resetControllers() {
    if (_scaleController.isAnimating) {
      _scaleController.stop();
    }
    if (_translateController.isAnimating) {
      _translateController.stop();
    }
    _scaleController.reset();
    _translateController.reset();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: Listenable.merge([_scaleController, _translateController]),
      builder: (context, child) {
        return Transform.translate(
          offset: _translateAnimation.value,
          child: Transform.scale(
            scale: _scaleAnimation.value,
            child: widget.child,
          ),
        );
      },
    );
  }
}
