/// Widget de visualisation heat map.
///
/// Affiche une carte de chaleur (brouillard) de la distribution des tirs
/// avec gradient bleu (froid/peu de tirs) à rouge (chaud/beaucoup de tirs).
/// Utilise un effet de brouillard radial pour un rendu fluide.
library;

import 'dart:math' as math;
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import '../../../services/statistics_service.dart';

class HeatMapWidget extends StatelessWidget {
  final HeatMap heatMap;
  final double size;

  const HeatMapWidget({
    super.key,
    required this.heatMap,
    this.size = 250,
  });

  @override
  Widget build(BuildContext context) {
    if (heatMap.zones.isEmpty || heatMap.totalShots == 0) {
      return SizedBox(
        width: size,
        height: size,
        child: const Center(
          child: Text('Aucune donnee'),
        ),
      );
    }

    return Container(
      width: size,
      height: size,
      decoration: BoxDecoration(
        border: Border.all(color: Colors.grey.shade300),
        borderRadius: BorderRadius.circular(8),
      ),
      child: ClipRRect(
        borderRadius: BorderRadius.circular(7),
        child: CustomPaint(
          size: Size(size, size),
          painter: _HeatMapFogPainter(heatMap: heatMap),
        ),
      ),
    );
  }
}

class _HeatMapFogPainter extends CustomPainter {
  final HeatMap heatMap;

  _HeatMapFogPainter({required this.heatMap});

  @override
  void paint(Canvas canvas, Size size) {
    if (heatMap.zones.isEmpty) return;

    // Draw base background (cold blue)
    final bgPaint = Paint()
      ..color = const Color(0xFF1A237E).withValues(alpha: 0.3); // Dark blue base
    canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), bgPaint);

    final cellWidth = size.width / heatMap.gridSize;
    final cellHeight = size.height / heatMap.gridSize;

    // Collect all shot positions with their intensities for fog effect
    final hotSpots = <_HotSpot>[];

    for (int row = 0; row < heatMap.gridSize; row++) {
      for (int col = 0; col < heatMap.gridSize; col++) {
        final zone = heatMap.zones[row][col];
        if (zone.shotCount > 0) {
          hotSpots.add(_HotSpot(
            x: (col + 0.5) * cellWidth,
            y: (row + 0.5) * cellHeight,
            intensity: zone.intensity,
            shotCount: zone.shotCount,
          ));
        }
      }
    }

    // Draw fog effect using radial gradients for each hot spot
    for (final spot in hotSpots) {
      _drawFogSpot(canvas, size, spot, cellWidth, cellHeight);
    }

    // Draw target overlay (concentric circles)
    final center = Offset(size.width / 2, size.height / 2);
    final maxRadius = size.width / 2;
    final circlePaint = Paint()
      ..color = Colors.white.withValues(alpha: 0.5)
      ..style = PaintingStyle.stroke
      ..strokeWidth = 1;

    for (int i = 1; i <= 5; i++) {
      canvas.drawCircle(center, maxRadius * (i / 5), circlePaint);
    }

    // Draw crosshair
    canvas.drawLine(
      Offset(center.dx, 0),
      Offset(center.dx, size.height),
      circlePaint,
    );
    canvas.drawLine(
      Offset(0, center.dy),
      Offset(size.width, center.dy),
      circlePaint,
    );

    // Draw shot counts
    for (final spot in hotSpots) {
      final textPainter = TextPainter(
        text: TextSpan(
          text: '${spot.shotCount}',
          style: TextStyle(
            color: Colors.white,
            fontSize: 14,
            fontWeight: FontWeight.bold,
            shadows: [
              Shadow(color: Colors.black.withValues(alpha: 0.8), blurRadius: 4),
              Shadow(color: Colors.black.withValues(alpha: 0.8), blurRadius: 2),
            ],
          ),
        ),
        textDirection: TextDirection.ltr,
      );
      textPainter.layout();
      textPainter.paint(
        canvas,
        Offset(spot.x - textPainter.width / 2, spot.y - textPainter.height / 2),
      );
    }
  }

  void _drawFogSpot(Canvas canvas, Size size, _HotSpot spot, double cellWidth, double cellHeight) {
    // Calculate fog radius based on intensity and cell size
    final baseRadius = math.max(cellWidth, cellHeight) * 1.5;
    final radius = baseRadius * (0.5 + spot.intensity * 0.5);

    // Create gradient from hot (red/orange) to transparent
    final gradient = ui.Gradient.radial(
      Offset(spot.x, spot.y),
      radius,
      [
        _getHeatColor(spot.intensity).withValues(alpha: 0.7 * spot.intensity + 0.3),
        _getHeatColor(spot.intensity * 0.5).withValues(alpha: 0.3 * spot.intensity),
        Colors.transparent,
      ],
      [0.0, 0.5, 1.0],
    );

    final paint = Paint()
      ..shader = gradient
      ..blendMode = BlendMode.screen; // Additive blending for fog effect

    canvas.drawCircle(Offset(spot.x, spot.y), radius, paint);

    // Add a second layer for more intensity
    if (spot.intensity > 0.3) {
      final innerGradient = ui.Gradient.radial(
        Offset(spot.x, spot.y),
        radius * 0.6,
        [
          _getHeatColor(spot.intensity).withValues(alpha: 0.5 * spot.intensity),
          Colors.transparent,
        ],
        [0.0, 1.0],
      );

      final innerPaint = Paint()
        ..shader = innerGradient
        ..blendMode = BlendMode.screen;

      canvas.drawCircle(Offset(spot.x, spot.y), radius * 0.6, innerPaint);
    }
  }

  Color _getHeatColor(double intensity) {
    // Gradient from blue (cold) to red (hot)
    if (intensity <= 0) return const Color(0xFF2196F3); // Blue
    if (intensity >= 1) return const Color(0xFFFF1744); // Red

    // Interpolate between blue -> cyan -> yellow -> orange -> red
    if (intensity < 0.25) {
      // Blue to Cyan
      return Color.lerp(
        const Color(0xFF2196F3), // Blue
        const Color(0xFF00BCD4), // Cyan
        intensity / 0.25,
      )!;
    } else if (intensity < 0.5) {
      // Cyan to Yellow
      return Color.lerp(
        const Color(0xFF00BCD4), // Cyan
        const Color(0xFFFFEB3B), // Yellow
        (intensity - 0.25) / 0.25,
      )!;
    } else if (intensity < 0.75) {
      // Yellow to Orange
      return Color.lerp(
        const Color(0xFFFFEB3B), // Yellow
        const Color(0xFFFF9800), // Orange
        (intensity - 0.5) / 0.25,
      )!;
    } else {
      // Orange to Red
      return Color.lerp(
        const Color(0xFFFF9800), // Orange
        const Color(0xFFFF1744), // Red
        (intensity - 0.75) / 0.25,
      )!;
    }
  }

  @override
  bool shouldRepaint(covariant _HeatMapFogPainter oldDelegate) {
    return heatMap != oldDelegate.heatMap;
  }
}

class _HotSpot {
  final double x;
  final double y;
  final double intensity;
  final int shotCount;

  _HotSpot({
    required this.x,
    required this.y,
    required this.intensity,
    required this.shotCount,
  });
}
