import 'package:flutter/material.dart';
import '../models/chart_model.dart';

class ChartLineWidget extends StatelessWidget {
  final ChartData chartData;

  const ChartLineWidget({super.key, required this.chartData});

  @override
  Widget build(BuildContext context) {
    if (chartData.dataPoints.isEmpty) {
      return Container(
        margin: const EdgeInsets.symmetric(horizontal: 16.0),
        padding: const EdgeInsets.all(16.0),
        decoration: BoxDecoration(
          color: Colors.blueGrey[50],
          borderRadius: BorderRadius.circular(8),
          border: Border.all(color: Colors.blueGrey[200]!),
        ),
        child: const Center(child: Text('Keine Daten verfügbar')),
      );
    }

    final maxLiters = chartData.getMaxLiters();
    final maxPrice = chartData.getMaxPrice();
    final maxPricePerLiter = chartData.getMaxPricePerLiter();

    final maxY = [
      maxLiters,
      maxPrice,
      maxPricePerLiter,
    ].reduce((a, b) => a > b ? a : b);
    final padding = maxY * 0.1;
    final yAxisMax = maxY + padding;

    return Column(
      children: [
        Container(
          margin: const EdgeInsets.symmetric(horizontal: 16.0),
          padding: const EdgeInsets.all(16.0),
          decoration: BoxDecoration(
            color: Colors.blueGrey[50],
            borderRadius: BorderRadius.circular(8),
            border: Border.all(color: Colors.blueGrey[200]!),
          ),
          child: Column(
            children: [
              SizedBox(
                height: 300,
                child: CustomPaint(
                  painter: LineChartPainter(
                    chartData: chartData,
                    yAxisMax: yAxisMax,
                  ),
                  size: Size.infinite,
                ),
              ),
              const SizedBox(height: 20),
              Wrap(
                spacing: 20,
                runSpacing: 10,
                children: [
                  _LegendItem(color: Colors.red, label: 'Liter pro Stop'),
                  _LegendItem(color: Colors.green, label: 'Preis pro Stop (€)'),
                  _LegendItem(
                    color: Colors.amber,
                    label: 'Preis pro Liter (€)',
                  ),
                ],
              ),
            ],
          ),
        ),
      ],
    );
  }
}

class _LegendItem extends StatelessWidget {
  final Color color;
  final String label;

  const _LegendItem({required this.color, required this.label});

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        Container(
          width: 16,
          height: 16,
          decoration: BoxDecoration(color: color, shape: BoxShape.circle),
        ),
        const SizedBox(width: 8),
        Text(
          label,
          style: const TextStyle(fontSize: 12, color: Colors.black87),
        ),
      ],
    );
  }
}

class LineChartPainter extends CustomPainter {
  final ChartData chartData;
  final double yAxisMax;

  LineChartPainter({required this.chartData, required this.yAxisMax});

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

    final paint = Paint()
      ..color = Colors.blueGrey[300]!
      ..strokeWidth = 1;

    final axisPaint = Paint()
      ..color = Colors.blueGrey[600]!
      ..strokeWidth = 2;

    final padding = EdgeInsets.fromLTRB(40, 20, 20, 40);
    final graphWidth = size.width - padding.left - padding.right;
    final graphHeight = size.height - padding.top - padding.bottom;

    // Draw grid and axes
    _drawAxes(canvas, size, padding, axisPaint, paint);

    // Draw lines
    _drawLine(
      canvas,
      chartData,
      padding,
      graphWidth,
      graphHeight,
      Colors.red,
      (point) => point.litersPerStop,
    );

    _drawLine(
      canvas,
      chartData,
      padding,
      graphWidth,
      graphHeight,
      Colors.green,
      (point) => point.pricePerStop,
    );

    _drawLine(
      canvas,
      chartData,
      padding,
      graphWidth,
      graphHeight,
      Colors.amber,
      (point) => point.pricePerLiter,
    );

    // Draw points
    final pointPaint = Paint()
      ..strokeWidth = 3
      ..strokeCap = StrokeCap.round;

    final pointsSize = 4.0;

    for (var point in chartData.dataPoints) {
      final xPos =
          padding.left +
          (point.stopNumber - 1) *
              (graphWidth /
                  (chartData.dataPoints.length - 1 > 0
                      ? chartData.dataPoints.length - 1
                      : 1));

      // Red points (Liters)
      final yLiters =
          padding.top +
          graphHeight -
          (point.litersPerStop / yAxisMax) * graphHeight;
      pointPaint.color = Colors.red;
      canvas.drawCircle(Offset(xPos, yLiters), pointsSize, pointPaint);

      // Green points (Price)
      final yPrice =
          padding.top +
          graphHeight -
          (point.pricePerStop / yAxisMax) * graphHeight;
      pointPaint.color = Colors.green;
      canvas.drawCircle(Offset(xPos, yPrice), pointsSize, pointPaint);

      // Amber points (Price per Liter)
      final yPricePerLiter =
          padding.top +
          graphHeight -
          (point.pricePerLiter / yAxisMax) * graphHeight;
      pointPaint.color = Colors.amber;
      canvas.drawCircle(Offset(xPos, yPricePerLiter), pointsSize, pointPaint);
    }
  }

  void _drawAxes(
    Canvas canvas,
    Size size,
    EdgeInsets padding,
    Paint axisPaint,
    Paint gridPaint,
  ) {
    // Y-axis
    canvas.drawLine(
      Offset(padding.left, padding.top),
      Offset(padding.left, size.height - padding.bottom),
      axisPaint,
    );

    // X-axis
    canvas.drawLine(
      Offset(padding.left, size.height - padding.bottom),
      Offset(size.width - padding.right, size.height - padding.bottom),
      axisPaint,
    );

    final graphHeight = size.height - padding.top - padding.bottom;
    final graphWidth = size.width - padding.left - padding.right;

    // Y-axis labels
    final steps = 5;
    for (int i = 0; i <= steps; i++) {
      final yPos = padding.top + (graphHeight / steps) * i;
      final value = yAxisMax - (yAxisMax / steps) * i;

      // Grid line
      canvas.drawLine(
        Offset(padding.left, yPos),
        Offset(size.width - padding.right, yPos),
        gridPaint..strokeWidth = 0.5,
      );

      // Label
      final textPainter = TextPainter(
        text: TextSpan(
          text: value.toStringAsFixed(1),
          style: const TextStyle(color: Colors.black54, fontSize: 10),
        ),
        textDirection: TextDirection.ltr,
      );
      textPainter.layout();
      textPainter.paint(
        canvas,
        Offset(
          padding.left - textPainter.width - 8,
          yPos - textPainter.height / 2,
        ),
      );
    }

    // X-axis labels
    for (int i = 0; i < chartData.dataPoints.length; i++) {
      final xPos =
          padding.left +
          i *
              (graphWidth /
                  (chartData.dataPoints.length - 1 > 0
                      ? chartData.dataPoints.length - 1
                      : 1));

      final textPainter = TextPainter(
        text: TextSpan(
          text: (i + 1).toString(),
          style: const TextStyle(color: Colors.black54, fontSize: 10),
        ),
        textDirection: TextDirection.ltr,
      );
      textPainter.layout();
      textPainter.paint(
        canvas,
        Offset(xPos - textPainter.width / 2, size.height - padding.bottom + 8),
      );
    }
  }

  void _drawLine(
    Canvas canvas,
    ChartData chartData,
    EdgeInsets padding,
    double graphWidth,
    double graphHeight,
    Color color,
    double Function(ChartDataPoint) getValue,
  ) {
    final paint = Paint()
      ..color = color
      ..strokeWidth = 2
      ..strokeCap = StrokeCap.round
      ..strokeJoin = StrokeJoin.round
      ..style = PaintingStyle.stroke;

    final points = chartData.dataPoints;
    if (points.length < 2) return;

    final path = Path();

    for (int i = 0; i < points.length; i++) {
      final x =
          padding.left +
          i * (graphWidth / (points.length - 1 > 0 ? points.length - 1 : 1));
      final y =
          padding.top +
          graphHeight -
          (getValue(points[i]) / yAxisMax) * graphHeight;

      if (i == 0) {
        path.moveTo(x, y);
      } else {
        path.lineTo(x, y);
      }
    }

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(LineChartPainter oldDelegate) {
    return oldDelegate.chartData != chartData ||
        oldDelegate.yAxisMax != yAxisMax;
  }
}
