import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';

class TimeSeriesPoint {
  final int timestamp;
  final double value;
  TimeSeriesPoint(this.timestamp, this.value);
}

class TimeSeriesChart extends StatelessWidget {
  final int startTime; // 毫秒时间戳
  final int endTime;
  final double yMin;
  final double yMax;
  final List<TimeSeriesPoint> dataPoints;

  const TimeSeriesChart({
    Key? key,
    required this.startTime,
    required this.endTime,
    required this.yMin,
    required this.yMax,
    required this.dataPoints,
  }) : super(key: key);

  // X轴刻度数据
  List<XLabel> _generateXLabels() {
    final labels = <XLabel>[];
    final startDate = DateTime.fromMillisecondsSinceEpoch(startTime);
    final endDate = DateTime.fromMillisecondsSinceEpoch(endTime);

    // 第一个刻度，原始 startTime，HH:mm格式
    labels.add(XLabel(
      time: startTime,
      label:
          '${startDate.hour.toString().padLeft(2, '0')}:${startDate.minute.toString().padLeft(2, '0')}',
    ));

    // 生成中间整点小时刻度，注意起点向上取整一个小时
    DateTime current = DateTime(
      startDate.year,
      startDate.month,
      startDate.day,
      startDate.hour,
    );
    if (startDate.minute > 0 ||
        startDate.second > 0 ||
        startDate.millisecond > 0) {
      // 如果 startTime 不是整点，跳到下一个整点小时
      current = current.add(Duration(hours: 1));
    }

    while (current.isBefore(endDate)) {
      labels.add(XLabel(
        time: current.millisecondsSinceEpoch,
        label: current.hour.toString(),
      ));
      current = current.add(Duration(hours: 1));
    }

    // 最后一个刻度，原始 endTime，HH:mm格式
    labels.add(XLabel(
      time: endTime,
      label:
          '${endDate.hour.toString().padLeft(2, '0')}:${endDate.minute.toString().padLeft(2, '0')}',
    ));

    return labels;
  }

  // 时间戳映射到0~(labels.length-1)之间
  double _timeToX(double timestamp, List<XLabel> labels) {
    int start = labels.first.time;
    int end = labels.last.time;
    double total = (end - start).toDouble();
    double pos = (timestamp - start).clamp(0, total).toDouble();
    return pos / total * (labels.length - 1);
  }

  @override
  Widget build(BuildContext context) {
    final xLabels = _generateXLabels();
    final midY = (yMin + yMax) / 2;

    List<FlSpot> spots = dataPoints.map((p) {
      return FlSpot(_timeToX(p.timestamp.toDouble(), xLabels), p.value);
    }).toList();

    return AspectRatio(
      aspectRatio: 2,
      child: LineChart(
        LineChartData(
          minX: 0,
          maxX: (xLabels.length - 1).toDouble(),
          minY: yMin < 0 ? yMin : 0,
          maxY: yMax,
          gridData: FlGridData(show: false),
          extraLinesData: ExtraLinesData(
            horizontalLines: [
              HorizontalLine(
                  y: 0,
                  color: themeController.currentColor.sc4,
                  strokeWidth: 1.rpx),
              HorizontalLine(
                  y: yMin,
                  color: themeController.currentColor.sc9,
                  strokeWidth: 1.rpx,
                  dashArray: [5, 5]),
              HorizontalLine(
                  y: yMax,
                  color: themeController.currentColor.sc9,
                  strokeWidth: 1.rpx,
                  dashArray: [5, 5]),
              HorizontalLine(
                  y: midY,
                  color: themeController.currentColor.sc4,
                  strokeWidth: 1.rpx,
                  dashArray: [5, 5]),
            ],
          ),
          titlesData: FlTitlesData(
            bottomTitles: AxisTitles(
              sideTitles: SideTitles(
                showTitles: true,
                reservedSize: 30,
                interval: 1,
                getTitlesWidget: (value, meta) {
                  int index = value.toInt();
                  if (index < 0 || index >= xLabels.length)
                    return const SizedBox.shrink();

                  final dateTime =
                      DateTime.fromMillisecondsSinceEpoch(xLabels[index].time);

                  if (index == 0 || index == xLabels.length - 1) {
                    // 开始和结束显示 HH:mm
                    final formatted =
                        '${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}';
                    return Padding(
                      padding: const EdgeInsets.only(top: 8.0),
                      child: Text(formatted,
                          style: TextStyle(
                              color: themeController.currentColor.sc4,
                              fontSize: 16.rpx)),
                    );
                  } else {
                    // 中间显示小时H，24小时制，不补零
                    final formatted = '${dateTime.hour}';
                    return Padding(
                      padding: const EdgeInsets.only(top: 8.0),
                      child: Text(formatted,
                          style: TextStyle(
                              color: themeController.currentColor.sc4,
                              fontSize: 16.rpx)),
                    );
                  }
                },
              ),
            ),
            leftTitles: AxisTitles(
              sideTitles: SideTitles(
                showTitles: true,
                reservedSize: 40.rpx,
                interval: 1,
                getTitlesWidget: (value, meta) {
                  // 只显示 yMin, midY, yMax, 和 0
                  if ((value - 0).abs() < 0.01) {
                    return Text('0',
                        style: TextStyle(
                            color: themeController.currentColor.sc4,
                            fontSize: 16.rpx));
                  } else if ((value - yMin).abs() < 0.01) {
                    return Text(yMin.toStringAsFixed(0),
                        style: TextStyle(
                            color: themeController.currentColor.sc4,
                            fontSize: 16.rpx));
                  } else if ((value - midY).abs() < 0.01) {
                    return Text(midY.toStringAsFixed(0),
                        style: TextStyle(
                            color: themeController.currentColor.sc4,
                            fontSize: 16.rpx));
                  } else if ((value - yMax).abs() < 0.01) {
                    return Text(yMax.toStringAsFixed(0),
                        style: TextStyle(
                            color: themeController.currentColor.sc4,
                            fontSize: 16.rpx));
                  } else {
                    return const SizedBox.shrink();
                  }
                },
              ),
            ),
            rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
            topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
          ),
          borderData: FlBorderData(
            show: true,
            border: Border(
              bottom: BorderSide(color: Colors.grey.withOpacity(0.3)),
              left: BorderSide.none,
              right: BorderSide.none,
              top: BorderSide.none,
            ),
          ),
          lineBarsData: [
            LineChartBarData(
              spots: spots,
              isCurved: false,
              color: themeController.currentColor.sc2,
              barWidth: 2,
              dotData: FlDotData(show: false),
            )
          ],
        ),
      ),
    );
  }
}

class XLabel {
  final int time;
  final String label;
  XLabel({required this.time, required this.label});
}
