import 'dart:ui';

import 'package:flutter/Material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class PieData {
  final String label;
  final double value;
  final Color color;

  PieData(this.label, this.value, this.color);
}

class MultiSegmentCircleIndicator extends StatelessWidget {
  final List<PieData> segments;
  final double radius;
  final double strokeWidth;
  final Duration animationDuration;
  final String Function(double percent)? centerTextBuilder;
  final String? subtitle;
  final double centerValue;

  const MultiSegmentCircleIndicator({
    super.key,
    required this.segments,
    this.radius = 60,
    this.strokeWidth = 12,
    this.animationDuration = const Duration(seconds: 1),
    this.centerTextBuilder,
    required this.centerValue,
    this.subtitle,
  });

  @override
  Widget build(BuildContext context) {
    return TweenAnimationBuilder<double>(
      tween: Tween<double>(begin: 0, end: 1),
      duration: animationDuration,
      builder: (context, value, child) {
        final animatedSegments = segments
            .map((e) => PieData(e.label, e.value * value, e.color))
            .toList();

        return Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            SizedBox(
              width: radius * 2,
              height: radius * 2,
              child: CustomPaint(
                painter: _CirclePainter(
                  segments: animatedSegments,
                  strokeWidth: strokeWidth,
                ),
                child: Center(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    textBaseline: TextBaseline.alphabetic,
                    children: [
                      Text.rich(TextSpan(children: [
                        TextSpan(
                          text: centerTextBuilder?.call(centerValue * value) ??
                              (centerValue * value).toStringAsFixed(0),
                          style: TextStyle(
                            color: Colors.white.withAlpha(229),
                            fontSize: 30.sp,
                            fontWeight: FontWeight.w400,
                          ),
                        ),
                        TextSpan(
                          text: '%',
                          style: TextStyle(
                            color: Colors.white.withAlpha(229),
                            fontSize: 13.03.sp,
                            fontWeight: FontWeight.w500,
                          ),
                        ),
                      ])),
                      if (subtitle != null)
                        Text(
                          subtitle!,
                          style: TextStyle(
                            fontSize: 14,
                            color: Colors.white.withOpacity(0.6),
                          ),
                        ),
                    ],
                  ),
                ),
              ),
            ),
            const SizedBox(height: 12),
          ],
        );
      },
    );
  }
}

class _CirclePainter extends CustomPainter {
  final List<PieData> segments;
  final double strokeWidth;

  _CirclePainter({required this.segments, this.strokeWidth = 16});

  @override
  void paint(Canvas canvas, Size size) {
    final center = size.center(Offset.zero);
    final radius = (size.shortestSide - strokeWidth) / 2;

    final paint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..strokeCap = StrokeCap.round;

    double startAngle = -90.0;

    for (final segment in segments) {
      final sweepAngle = 360 * (segment.value / 100);
      paint.color = segment.color;
      canvas.drawArc(
        Rect.fromCircle(center: center, radius: radius),
        _toRadians(startAngle),
        _toRadians(sweepAngle),
        false,
        paint,
      );
      startAngle += sweepAngle;
    }
  }

  double _toRadians(double degrees) => degrees * 3.1415926 / 180;

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
