import 'package:flutter/material.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:xp_models/xp_models.dart';
import '../theme/app_theme.dart';

class XPChart extends StatelessWidget {
  final List<StatsHistory> history;

  const XPChart({super.key, required this.history});

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                const Icon(Icons.trending_up, color: AppTheme.primaryColor),
                const SizedBox(width: 8),
                Text(
                  'XP Progress (7 Days)',
                  style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
                ),
              ],
            ),
            const SizedBox(height: 16),
            _buildLegend(),
            const SizedBox(height: 16),
            SizedBox(
              height: 300,
              child: history.isEmpty ? const Center(child: CircularProgressIndicator()) : LineChart(_buildChartData()),
            ),
          ],
        ),
      ),
    );
  }

  LineChartData _buildChartData() {
    final xpSpots = <FlSpot>[];
    final levelSpots = <FlSpot>[];

    for (int i = 0; i < history.length; i++) {
      xpSpots.add(FlSpot(i.toDouble(), history[i].xp.toDouble()));
      levelSpots.add(FlSpot(i.toDouble(), history[i].level.toDouble()));
    }

    final maxXP = history.map((h) => h.xp).reduce((a, b) => a > b ? a : b).toDouble();
    final maxLevel = history.map((h) => h.level).reduce((a, b) => a > b ? a : b).toDouble();

    return LineChartData(
      gridData: FlGridData(
        show: true,
        drawVerticalLine: true,
        horizontalInterval: maxXP / 5,
        verticalInterval: 1,
        getDrawingHorizontalLine: (value) {
          return FlLine(color: Colors.grey.shade300, strokeWidth: 1);
        },
        getDrawingVerticalLine: (value) {
          return FlLine(color: Colors.grey.shade300, strokeWidth: 1);
        },
      ),
      titlesData: FlTitlesData(
        show: true,
        rightTitles: AxisTitles(
          sideTitles: SideTitles(
            showTitles: true,
            reservedSize: 40,
            // interval: 4,
            getTitlesWidget: (value, meta) {
              return Text(
                'L${value.toInt() / 100}',
                style: const TextStyle(color: AppTheme.secondaryColor, fontWeight: FontWeight.bold, fontSize: 12),
              );
            },
          ),
        ),
        topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
        bottomTitles: AxisTitles(
          sideTitles: SideTitles(
            showTitles: true,
            reservedSize: 30,
            interval: 1,
            getTitlesWidget: (value, meta) {
              final index = value.toInt();
              if (index >= 0 && index < history.length) {
                final date = DateTime.parse(history[index].date);
                return Padding(
                  padding: const EdgeInsets.only(top: 8.0),
                  child: Text(
                    '${date.month}/${date.day}',
                    style: const TextStyle(color: Colors.grey, fontWeight: FontWeight.bold, fontSize: 12),
                  ),
                );
              }
              return const Text('');
            },
          ),
        ),
        leftTitles: AxisTitles(
          sideTitles: SideTitles(
            showTitles: true,
            // interval: maxXP / 4,
            reservedSize: 50,
            getTitlesWidget: (value, meta) {
              return Text(
                _formatXP(value.toInt()),
                style: const TextStyle(color: AppTheme.primaryColor, fontWeight: FontWeight.bold, fontSize: 12),
              );
            },
          ),
        ),
      ),
      borderData: FlBorderData(show: true, border: Border.all(color: Colors.grey.shade300)),
      minX: 0,
      maxX: (history.length - 1).toDouble(),
      minY: 0,
      maxY: maxXP * 1.1,
      lineBarsData: [
        // XP Line
        LineChartBarData(
          spots: xpSpots,
          isCurved: true,
          gradient: const LinearGradient(colors: [AppTheme.primaryColor, AppTheme.accentColor]),
          barWidth: 3,
          isStrokeCapRound: true,
          dotData: FlDotData(
            show: true,
            getDotPainter: (spot, percent, barData, index) {
              return FlDotCirclePainter(
                radius: 4,
                color: AppTheme.primaryColor,
                strokeWidth: 2,
                strokeColor: Colors.white,
              );
            },
          ),
          belowBarData: BarAreaData(
            show: true,
            gradient: LinearGradient(
              colors: [AppTheme.primaryColor.withOpacity(0.3), AppTheme.primaryColor.withOpacity(0.1)],
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
            ),
          ),
        ),
        // Level Line (scaled to fit)
        LineChartBarData(
          spots: levelSpots.map((spot) => FlSpot(spot.x, spot.y * (maxXP / maxLevel))).toList(),
          isCurved: true,
          color: AppTheme.secondaryColor,
          barWidth: 2,
          isStrokeCapRound: true,
          dotData: FlDotData(
            show: true,
            getDotPainter: (spot, percent, barData, index) {
              return FlDotCirclePainter(
                radius: 3,
                color: AppTheme.secondaryColor,
                strokeWidth: 2,
                strokeColor: Colors.white,
              );
            },
          ),
          dashArray: [5, 5],
        ),
      ],
      lineTouchData: LineTouchData(
        enabled: true,
        touchTooltipData: LineTouchTooltipData(
          tooltipBgColor: Colors.blueGrey.withOpacity(0.8),
          getTooltipItems: (List<LineBarSpot> touchedBarSpots) {
            return touchedBarSpots.map((barSpot) {
              final flSpot = barSpot;
              final index = flSpot.x.toInt();
              if (index >= 0 && index < history.length) {
                final historyItem = history[index];
                final date = DateTime.parse(historyItem.date);

                if (barSpot.barIndex == 0) {
                  // XP line
                  return LineTooltipItem(
                    '${date.month}/${date.day}\nXP: ${historyItem.xp}',
                    const TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
                  );
                } else {
                  // Level line
                  return LineTooltipItem(
                    'Level: ${historyItem.level}',
                    const TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
                  );
                }
              }
              return null;
            }).toList();
          },
        ),
      ),
    );
  }

  Widget _buildLegend() {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
      decoration: BoxDecoration(
        color: Colors.grey.shade50,
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: Colors.grey.shade200),
      ),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          _buildLegendItem(
            color: AppTheme.primaryColor,
            label: 'Experience Points',
            isDashed: false,
            hasGradient: true,
          ),
          const SizedBox(width: 24),
          _buildLegendItem(color: AppTheme.secondaryColor, label: 'Level', isDashed: true, hasGradient: false),
        ],
      ),
    );
  }

  Widget _buildLegendItem({
    required Color color,
    required String label,
    required bool isDashed,
    required bool hasGradient,
  }) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        Container(
          width: 24,
          height: 3,
          decoration: BoxDecoration(
            gradient: hasGradient ? const LinearGradient(colors: [AppTheme.primaryColor, AppTheme.accentColor]) : null,
            color: hasGradient ? null : color,
            borderRadius: BorderRadius.circular(2),
          ),
          child: isDashed
              ? CustomPaint(
                  painter: DashedLinePainter(color: color),
                  size: const Size(24, 3),
                )
              : null,
        ),
        const SizedBox(width: 8),
        Text(
          label,
          style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Colors.black87),
        ),
      ],
    );
  }

  String _formatXP(int xp) {
    if (xp >= 1000000) {
      return '${(xp / 1000000).toStringAsFixed(1)}M';
    } else if (xp >= 1000) {
      return '${(xp / 1000).toStringAsFixed(1)}K';
    }
    return xp.toString();
  }
}

class DashedLinePainter extends CustomPainter {
  final Color color;

  DashedLinePainter({required this.color});

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = color
      ..strokeWidth = 2
      ..style = PaintingStyle.stroke;

    const dashWidth = 3.0;
    const dashSpace = 2.0;
    double startX = 0;

    while (startX < size.width) {
      canvas.drawLine(Offset(startX, size.height / 2), Offset(startX + dashWidth, size.height / 2), paint);
      startX += dashWidth + dashSpace;
    }
  }

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