import 'dart:math';
import 'package:flutter/material.dart';

class FavButton extends StatefulWidget {
  final bool initialValue;
  final ValueChanged<bool>? onChanged;
  final double size;

  const FavButton({
    super.key,
    this.initialValue = false,
    this.onChanged,
    this.size = 40,
  });

  @override
  State<FavButton> createState() => _FavButtonState();
}

class _FavButtonState extends State<FavButton>
    with SingleTickerProviderStateMixin {
  late bool _isFav;
  late AnimationController _ctrl;
  late Animation<double> _scale;
  late Animation<double> _particleProgress;

  @override
  void initState() {
    super.initState();
    _isFav = widget.initialValue;
    _ctrl = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 450),
    );
    _scale = TweenSequence([
      TweenSequenceItem(
        tween: Tween(begin: 1.0, end: 1.4)
            .chain(CurveTween(curve: Curves.easeOut)),
        weight: 40,
      ),
      TweenSequenceItem(
        tween: Tween(begin: 1.4, end: 1.0)
            .chain(CurveTween(curve: Curves.elasticOut)),
        weight: 60,
      ),
    ]).animate(_ctrl);
    _particleProgress =
        CurvedAnimation(parent: _ctrl, curve: Curves.easeOut);
  }

  @override
  void dispose() {
    _ctrl.dispose();
    super.dispose();
  }

  void _toggle() {
    setState(() => _isFav = !_isFav);
    widget.onChanged?.call(_isFav);
    if (_isFav) _ctrl.forward(from: 0);
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _toggle,
      child: AnimatedBuilder(
        animation: _ctrl,
        builder: (context, child) => CustomPaint(
          painter: _isFav ? _BurstPainter(_particleProgress.value) : null,
          child: Transform.scale(
            scale: _isFav ? _scale.value : 1.0,
            child: Container(
              width: widget.size,
              height: widget.size,
              decoration: BoxDecoration(
                color: _isFav
                    ? Colors.red.withOpacity(0.1)
                    : Colors.transparent,
                shape: BoxShape.circle,
              ),
              child: Icon(
                _isFav
                    ? Icons.favorite_rounded
                    : Icons.favorite_border_rounded,
                size: widget.size * 0.5,
                color: _isFav ? Colors.redAccent : Colors.grey,
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class _BurstPainter extends CustomPainter {
  final double progress;
  _BurstPainter(this.progress);

  @override
  void paint(Canvas canvas, Size size) {
    if (progress == 0) return;
    final center = Offset(size.width / 2, size.height / 2);
    final paint = Paint()
      ..color = Colors.redAccent.withOpacity(1 - progress);
    const count = 7;
    for (int i = 0; i < count; i++) {
      final angle = (i / count) * 2 * pi;
      final dist = progress * 24;
      final pos = center + Offset(dist * cos(angle), dist * sin(angle));
      canvas.drawCircle(pos, 3 * (1 - progress * 0.5), paint);
    }
  }

  @override
  bool shouldRepaint(_BurstPainter old) => old.progress != progress;
}