import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:geosector_app/presentation/widgets/charts/payment_data.dart';
import 'dart:math' as math;

/// Widget de graphique en camembert pour représenter la répartition des règlements
class PaymentPieChart extends StatefulWidget {
  /// Liste des données de règlement à afficher dans le graphique
  final List<PaymentData> payments;

  /// Taille du graphique
  final double size;

  /// Taille des étiquettes
  final double labelSize;

  /// Afficher les pourcentages
  final bool showPercentage;

  /// Afficher les icônes
  final bool showIcons;

  /// Afficher la légende
  final bool showLegend;

  /// Format donut (anneau)
  final bool isDonut;

  /// Rayon central pour le format donut (en pourcentage)
  final String innerRadius;

  /// Activer l'effet 3D
  final bool enable3DEffect;

  /// Intensité de l'effet 3D (1.0 = normal, 2.0 = fort)
  final double effect3DIntensity;

  /// Activer l'effet d'explosion plus prononcé
  final bool enableEnhancedExplode;

  /// Utiliser un dégradé pour simuler l'effet 3D
  final bool useGradient;

  const PaymentPieChart({
    super.key,
    required this.payments,
    this.size = 300,
    this.labelSize = 12,
    this.showPercentage = true,
    this.showIcons = true,
    this.showLegend = true,
    this.isDonut = false,
    this.innerRadius = '40%',
    this.enable3DEffect = false,
    this.effect3DIntensity = 1.0,
    this.enableEnhancedExplode = false,
    this.useGradient = false,
  });

  @override
  State<PaymentPieChart> createState() => _PaymentPieChartState();
}

class _PaymentPieChartState extends State<PaymentPieChart>
    with SingleTickerProviderStateMixin {
  late AnimationController _animationController;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 2000),
    );

    _animationController.forward();
  }

  @override
  void didUpdateWidget(PaymentPieChart oldWidget) {
    super.didUpdateWidget(oldWidget);

    // Relancer l'animation si les données ont changé
    // Utiliser une comparaison plus stricte pour éviter des animations inutiles
    bool shouldResetAnimation = false;

    if (oldWidget.payments.length != widget.payments.length) {
      shouldResetAnimation = true;
    } else {
      // Comparer les éléments importants uniquement
      for (int i = 0; i < oldWidget.payments.length; i++) {
        if (i >= widget.payments.length) break;
        if (oldWidget.payments[i].amount != widget.payments[i].amount ||
            oldWidget.payments[i].title != widget.payments[i].title) {
          shouldResetAnimation = true;
          break;
        }
      }
    }

    if (shouldResetAnimation) {
      _animationController.reset();
      _animationController.forward();
    }
  }

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

  /// Prépare les données pour le graphique en camembert
  List<PaymentData> _prepareChartData() {
    // Filtrer les règlements avec un montant > 0
    return widget.payments.where((payment) => payment.amount > 0).toList();
  }

  @override
  Widget build(BuildContext context) {
    final chartData = _prepareChartData();

    // Si aucune donnée, afficher un message
    if (chartData.isEmpty) {
      return SizedBox(
        width: widget.size,
        height: widget.size,
        child: const Center(
          child: Text('Aucune donnée disponible'),
        ),
      );
    }

    // Créer des animations pour différents aspects du graphique
    final progressAnimation = CurvedAnimation(
      parent: _animationController,
      curve: Curves.easeOutCubic,
    );

    final explodeAnimation = CurvedAnimation(
      parent: _animationController,
      curve: Interval(0.7, 1.0, curve: Curves.elasticOut),
    );

    final opacityAnimation = CurvedAnimation(
      parent: _animationController,
      curve: Interval(0.1, 0.5, curve: Curves.easeIn),
    );

    return AnimatedBuilder(
      animation: _animationController,
      builder: (context, child) {
        return SizedBox(
          width: widget.size,
          height: widget.size,
          child: SfCircularChart(
            margin: EdgeInsets.zero,
            legend: Legend(
              isVisible: widget.showLegend,
              position: LegendPosition.bottom,
              overflowMode: LegendItemOverflowMode.wrap,
              textStyle: TextStyle(fontSize: widget.labelSize),
            ),
            tooltipBehavior: TooltipBehavior(enable: true),
            series: <CircularSeries>[
              widget.isDonut
                  ? DoughnutSeries<PaymentData, String>(
                      dataSource: chartData,
                      xValueMapper: (PaymentData data, _) => data.title,
                      yValueMapper: (PaymentData data, _) => data.amount,
                      pointColorMapper: (PaymentData data, _) {
                        if (widget.enable3DEffect) {
                          // Utiliser un angle différent pour chaque segment pour simuler un effet 3D
                          final index = chartData.indexOf(data);
                          final angle =
                              (index / chartData.length) * 2 * math.pi;
                          return widget.useGradient
                              ? _createEnhanced3DColor(data.color, angle)
                              : _create3DColor(
                                  data.color, widget.effect3DIntensity);
                        }
                        return data.color;
                      },
                      // Note: Le gradient n'est pas directement pris en charge dans cette version de Syncfusion
                      enableTooltip: true,
                      dataLabelMapper: (PaymentData data, _) {
                        if (widget.showPercentage) {
                          // Calculer le pourcentage avec une décimale
                          final total = chartData.fold(
                              0.0, (sum, item) => sum + item.amount);
                          final percentage = (data.amount / total * 100);
                          return '${percentage.toStringAsFixed(1)}%';
                        } else {
                          return data.title;
                        }
                      },
                      dataLabelSettings: DataLabelSettings(
                        isVisible: true,
                        labelPosition: ChartDataLabelPosition
                            .inside, // Afficher les étiquettes à l'intérieur du donut
                        textStyle: TextStyle(
                          fontSize: widget.labelSize,
                          color: Colors
                              .white, // Texte blanc pour meilleure lisibilité
                          fontWeight: FontWeight
                              .bold, // Texte en gras pour meilleure lisibilité
                        ),
                      ),
                      innerRadius: widget.innerRadius,
                      // Effet d'explosion plus prononcé pour donner du relief avec animation
                      explode: true,
                      explodeAll: widget.enableEnhancedExplode,
                      explodeIndex: widget.enableEnhancedExplode ? null : 0,
                      explodeOffset: widget.enableEnhancedExplode
                          ? widget.enable3DEffect
                              ? '${(12 * explodeAnimation.value).toStringAsFixed(1)}%'
                              : '${(8 * explodeAnimation.value).toStringAsFixed(1)}%'
                          : '${(5 * explodeAnimation.value).toStringAsFixed(1)}%',
                      // Effet 3D via l'opacité et les couleurs avec animation
                      opacity: widget.enable3DEffect
                          ? 0.95 * opacityAnimation.value
                          : opacityAnimation.value,
                      // Animation progressive du graphique
                      animationDuration:
                          0, // On désactive l'animation intégrée car nous utilisons notre propre animation
                      startAngle: 270,
                      endAngle: 270 + (360 * progressAnimation.value).toInt(),
                    )
                  : PieSeries<PaymentData, String>(
                      dataSource: chartData,
                      xValueMapper: (PaymentData data, _) => data.title,
                      yValueMapper: (PaymentData data, _) => data.amount,
                      pointColorMapper: (PaymentData data, _) {
                        if (widget.enable3DEffect) {
                          // Utiliser un angle différent pour chaque segment pour simuler un effet 3D
                          final index = chartData.indexOf(data);
                          final angle =
                              (index / chartData.length) * 2 * math.pi;
                          return widget.useGradient
                              ? _createEnhanced3DColor(data.color, angle)
                              : _create3DColor(
                                  data.color, widget.effect3DIntensity);
                        }
                        return data.color;
                      },
                      // Note: Le gradient n'est pas directement pris en charge dans cette version de Syncfusion
                      enableTooltip: true,
                      dataLabelMapper: (PaymentData data, _) {
                        if (widget.showPercentage) {
                          // Calculer le pourcentage avec une décimale
                          final total = chartData.fold(
                              0.0, (sum, item) => sum + item.amount);
                          final percentage = (data.amount / total * 100);
                          return '${percentage.toStringAsFixed(1)}%';
                        } else {
                          return data.title;
                        }
                      },
                      dataLabelSettings: DataLabelSettings(
                        isVisible: true,
                        labelPosition: ChartDataLabelPosition.outside,
                        textStyle: TextStyle(fontSize: widget.labelSize),
                        connectorLineSettings: const ConnectorLineSettings(
                          type: ConnectorType.curve,
                          length: '15%',
                        ),
                      ),
                      // Effet d'explosion plus prononcé pour donner du relief avec animation
                      explode: true,
                      explodeAll: widget.enableEnhancedExplode,
                      explodeIndex: widget.enableEnhancedExplode ? null : 0,
                      explodeOffset: widget.enableEnhancedExplode
                          ? widget.enable3DEffect
                              ? '${(12 * explodeAnimation.value).toStringAsFixed(1)}%'
                              : '${(8 * explodeAnimation.value).toStringAsFixed(1)}%'
                          : '${(5 * explodeAnimation.value).toStringAsFixed(1)}%',
                      // Effet 3D via l'opacité et les couleurs avec animation
                      opacity: widget.enable3DEffect
                          ? 0.95 * opacityAnimation.value
                          : opacityAnimation.value,
                      // Animation progressive du graphique
                      animationDuration:
                          0, // On désactive l'animation intégrée car nous utilisons notre propre animation
                      startAngle: 270,
                      endAngle: 270 + (360 * progressAnimation.value).toInt(),
                    ),
            ],
            annotations:
                widget.showIcons ? _buildIconAnnotations(chartData) : null,
            // Paramètres pour améliorer l'effet 3D
            palette: widget.enable3DEffect ? _create3DPalette(chartData) : null,
            // Ajouter un effet de bordure pour renforcer l'effet 3D
            borderWidth: widget.enable3DEffect ? 0.5 : 0,
            // Note: La rotation n'est pas directement prise en charge dans cette version de Syncfusion
          ),
        );
      },
    );
  }

  /// Crée une couleur avec effet 3D en ajoutant des nuances
  Color _create3DColor(Color baseColor, double intensity) {
    // Ajuster la luminosité et la saturation pour créer un effet 3D plus prononcé
    final hslColor = HSLColor.fromColor(baseColor);

    // Augmenter la luminosité pour simuler un éclairage
    final adjustedLightness =
        (hslColor.lightness + 0.15 * intensity).clamp(0.0, 1.0);

    // Augmenter légèrement la saturation pour des couleurs plus vives
    final adjustedSaturation =
        (hslColor.saturation + 0.05 * intensity).clamp(0.0, 1.0);

    return hslColor
        .withLightness(adjustedLightness)
        .withSaturation(adjustedSaturation)
        .toColor();
  }

  /// Crée une palette de couleurs pour l'effet 3D
  List<Color> _create3DPalette(List<PaymentData> chartData) {
    List<Color> palette = [];

    // Créer des variations de couleurs pour chaque segment
    for (var i = 0; i < chartData.length; i++) {
      var data = chartData[i];

      // Calculer un angle pour chaque segment pour simuler un éclairage directionnel
      final angle = (i / chartData.length) * 2 * math.pi;

      // Créer un effet d'ombre et de lumière en fonction de l'angle
      final hslColor = HSLColor.fromColor(data.color);

      // Ajuster la luminosité en fonction de l'angle
      final lightAdjustment = 0.15 * widget.effect3DIntensity * math.sin(angle);
      final adjustedLightness = (hslColor.lightness -
              0.1 * widget.effect3DIntensity +
              lightAdjustment)
          .clamp(0.0, 1.0);

      // Ajuster la saturation pour plus de profondeur
      final adjustedSaturation =
          (hslColor.saturation + 0.1 * widget.effect3DIntensity)
              .clamp(0.0, 1.0);

      final enhancedColor = hslColor
          .withLightness(adjustedLightness)
          .withSaturation(adjustedSaturation)
          .toColor();

      palette.add(enhancedColor);
    }

    return palette;
  }

  /// Crée une couleur avec effet 3D plus avancé
  Color _createEnhanced3DColor(Color baseColor, double angle) {
    // Simuler un effet de lumière directionnel
    final hslColor = HSLColor.fromColor(baseColor);

    // Ajuster la luminosité en fonction de l'angle pour simuler un éclairage
    final adjustedLightness = hslColor.lightness +
        (0.2 * widget.effect3DIntensity * math.sin(angle)).clamp(-0.3, 0.3);

    return hslColor.withLightness(adjustedLightness.clamp(0.0, 1.0)).toColor();
  }

  /// Crée les annotations d'icônes pour le graphique
  List<CircularChartAnnotation> _buildIconAnnotations(
      List<PaymentData> chartData) {
    final List<CircularChartAnnotation> annotations = [];

    // Calculer le total pour les pourcentages
    double total = chartData.fold(0.0, (sum, item) => sum + item.amount);

    // Position angulaire actuelle (en radians)
    double currentAngle = 0;

    for (int i = 0; i < chartData.length; i++) {
      final data = chartData[i];
      final percentage = data.amount / total;

      // Calculer l'angle central de ce segment
      final segmentAngle = percentage * 2 * 3.14159;
      final midAngle = currentAngle + (segmentAngle / 2);

      // Ajouter une annotation pour l'icône
      annotations.add(
        CircularChartAnnotation(
          widget: Icon(
            data.icon,
            color: Colors.white,
            size: 16,
          ),
          radius: '50%',
          angle: (midAngle * (180 / 3.14159)).toInt(), // Convertir en degrés
        ),
      );

      // Mettre à jour l'angle actuel
      currentAngle += segmentAngle;
    }

    return annotations;
  }
}
