import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'dart:ui' as ui;

import 'package:vbvs_app/common/util/MyUtils.dart';

class TimeLineChart extends StatelessWidget {
  final List<DataPoint> points;
  final double yMin;
  final double yMax;
  final int startTime;
  final int endTime;
  final double width;
  final double height;

  const TimeLineChart({
    super.key,
    required this.points,
    required this.yMin,
    required this.yMax,
    required this.startTime,
    required this.endTime,
    this.width = 400,
    this.height = 300,
  });

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      size: Size(width, height),
      painter: _TimeLineChartPainter(
        points: points,
        yMin: yMin,
        yMax: yMax,
        startTime: startTime,
        endTime: endTime,
      ),
    );
  }
}

class DataPoint {
  final int timestamp;
  final double value;

  DataPoint(this.timestamp, this.value);
}

class _TimeLineChartPainter extends CustomPainter {
  final List<DataPoint> points;
  final double yMin;
  final double yMax;
  final int startTime;
  final int endTime;

  _TimeLineChartPainter({
    required this.points,
    required this.yMin,
    required this.yMax,
    required this.startTime,
    required this.endTime,
  });

  @override
  void paint(Canvas canvas, Size size) {
    _drawYAxis(canvas, size);
    _drawXAxis(canvas, size);
    _drawLine(canvas, size);
  }

  void _drawXAxis(Canvas canvas, Size size) {
    const margin = 40.0;
    final paint = Paint()..color = Colors.black;
    final textStyle = const TextStyle(color: Colors.black, fontSize: 12);

    // Draw X axis line
    canvas.drawLine(
      Offset(margin, size.height - margin),
      Offset(size.width - margin, size.height - margin),
      paint,
    );

    // Generate time ticks
    final timeFormatStartEnd = DateFormat('HH:mm');
    final timeFormatMiddle = DateFormat('h');
    final startDateTime = DateTime.fromMillisecondsSinceEpoch(startTime);
    final endDateTime = DateTime.fromMillisecondsSinceEpoch(endTime);

    List<DateTime> hourTicks = [];
    DateTime current = DateTime(
      startDateTime.year,
      startDateTime.month,
      startDateTime.day,
      startDateTime.hour,
    ).add(const Duration(hours: 1));

    while (current.isBefore(endDateTime)) {
      if (current.isAfter(startDateTime)) {
        hourTicks.add(current);
      }
      current = current.add(const Duration(hours: 1));
    }

    void drawTick(DateTime time, bool isEdge) {
      final x = margin +
          ((time.millisecondsSinceEpoch - startTime) / (endTime - startTime)) *
              (size.width - 2 * margin);

      final text = isEdge
          ? timeFormatStartEnd.format(time)
          : timeFormatMiddle.format(time);

      _drawText(
        canvas,
        text,
        Offset(x, size.height - margin + 20),
        TextAlign.center,
      );
    }

    drawTick(startDateTime, true);
    drawTick(endDateTime, true);
    for (var tick in hourTicks) {
      drawTick(tick, false);
    }
  }

  void _drawYAxis(Canvas canvas, Size size) {
    const margin = 40.0;
    final midValue = (yMax + yMin) / 2;

    // 计算三条虚线之间的垂直间距
    final lineSpacing = (size.height - 2 * margin) / 3; // 让三条线之间的间距相等

    // 新增的 y=0 实线的垂直位置
    final zeroLinePosition = margin + lineSpacing * 3; // 确保 y=0 位于三条虚线下方

    void drawLine(double value, Color color,
        {bool isDashed = false, bool isSolid = false}) {
      final y =
          (value - yMax) / (yMin - yMax) * (size.height - 2 * margin) + margin;

      final path = Path();
      path.moveTo(margin, y);
      path.lineTo(size.width - margin, y);

      final paint = Paint()
        ..color = color
        ..strokeWidth = (color != Colors.grey) ? 2 : 1
        ..style = PaintingStyle.stroke;

      if (isDashed) {
        Path dashedPath = _createDashedPath(path, dashWidth: 5, dashSpace: 5);
        canvas.drawPath(dashedPath, paint);
      } else if (isSolid) {
        // 对于实线，直接绘制
        canvas.drawPath(path, paint);
      } else {
        // 默认使用虚线绘制
        canvas.drawPath(path, paint);
      }
    }

    // 绘制 y=0 的灰色实线，并将其放置在三条虚线的下方
    if (yMin < 0 && yMax > 0) {
      drawLine(0, Colors.grey, isSolid: true); // 灰色实线绘制 y=0 线
    }

    // 绘制最小值、中间值、最大值的虚线
    drawLine(yMin, themeController.currentColor.sc9, isDashed: true);
    drawLine(midValue, themeController.currentColor.sc4, isDashed: true);
    drawLine(yMax, themeController.currentColor.sc9, isDashed: true);
  }

  Path _createDashedPath(Path path,
      {required double dashWidth, required double dashSpace}) {
    final Path dashedPath = Path();
    final ui.PathMetrics metrics = path.computeMetrics();

    for (ui.PathMetric metric in metrics) {
      double distance = 0;
      while (distance < metric.length) {
        dashedPath.addPath(
          metric.extractPath(distance, distance + dashWidth),
          Offset.zero,
        );
        distance += dashWidth + dashSpace;
      }
    }

    return dashedPath;
  }

  void _drawLine(Canvas canvas, Size size) {
    const margin = 40.0;
    final sortedPoints = points
      ..sort((a, b) => a.timestamp.compareTo(b.timestamp));

    Path? currentPath;
    Paint currentPaint = _createPaint(Colors.green);

    for (int i = 0; i < sortedPoints.length - 1; i++) {
      final p1 = sortedPoints[i];
      final p2 = sortedPoints[i + 1];

      final x1 = margin +
          ((p1.timestamp - startTime) / (endTime - startTime)) *
              (size.width - 2 * margin);
      final y1 = margin +
          (1 - (p1.value - yMin) / (yMax - yMin)) * (size.height - 2 * margin);

      final x2 = margin +
          ((p2.timestamp - startTime) / (endTime - startTime)) *
              (size.width - 2 * margin);
      final y2 = margin +
          (1 - (p2.value - yMin) / (yMax - yMin)) * (size.height - 2 * margin);

      final shouldBeGreen = p1.value >= yMin &&
          p1.value <= yMax &&
          p2.value >= yMin &&
          p2.value <= yMax;

      // 根据当前线段的状态来决定是否切换颜色和虚线状态
      if (shouldBeGreen != (currentPaint.color == Colors.green)) {
        if (currentPath != null) {
          canvas.drawPath(currentPath, currentPaint);
        }
        currentPath = Path();
        currentPaint = _createPaint(shouldBeGreen ? Colors.green : Colors.red);
      }

      currentPath ??= Path();
      if (i == 0) currentPath.moveTo(x1, y1);
      currentPath.lineTo(x2, y2);
    }

    // 绘制剩余路径
    if (currentPath != null) {
      if (currentPaint.color == Colors.red) {
        // 如果是红色线，绘制虚线
        final dashedPath =
            _createDashedPath(currentPath, dashWidth: 5, dashSpace: 5);
        canvas.drawPath(dashedPath, currentPaint);
      } else {
        canvas.drawPath(currentPath, currentPaint);
      }
    }
  }

  Paint _createPaint(Color color) => Paint()
    ..color = color
    ..strokeWidth = 2
    ..style = PaintingStyle.stroke;

  void _drawText(Canvas canvas, String text, Offset offset, TextAlign align) {
    final textPainter = TextPainter(
      text: TextSpan(
        text: text,
        style: const TextStyle(color: Colors.black, fontSize: 12),
      ),
      textDirection: ui.TextDirection.ltr,
    )..layout();

    final centeredOffset = offset.translate(
      -textPainter.width / 2,
      -textPainter.height / 2,
    );
    textPainter.paint(canvas, centeredOffset);
  }

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