import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:vbvs_app/common/color/appConstants.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';

class BarData {
  final int st; // 起始时间（毫秒）
  final int et; // 结束时间（毫秒）
  final double value; // 柱子高度
  final int id;
  final String name;
  final Color color;

  BarData({
    required this.st,
    required this.et,
    required this.value,
    required this.id,
    required this.name,
    required this.color,
  });
}

class BarChartWidget extends StatefulWidget {
  final List<BarData> data;
  final int startTime; // 毫秒时间戳
  final int endTime; // 毫秒时间戳
  final double maxYValue; // Y轴最大值
  final int yStepCount; // Y轴分段数

  const BarChartWidget({
    super.key,
    required this.data,
    required this.startTime,
    required this.endTime,
    required this.maxYValue,
    this.yStepCount = 5,
  });

  @override
  State<BarChartWidget> createState() => _BarChartWidgetState();
}

class _BarChartWidgetState extends State<BarChartWidget> {
  BarData? selectedBar;

  void _handleTapOrDrag(Offset localPosition, Size size) {
    final chartWidth = size.width - 30.rpx;
    final totalDuration = widget.endTime - widget.startTime;

    for (final d in widget.data) {
      final left =
          ((d.st - widget.startTime) / totalDuration) * chartWidth + 30.rpx;
      final right =
          ((d.et - widget.startTime) / totalDuration) * chartWidth + 30.rpx;
      if (localPosition.dx >= left && localPosition.dx <= right) {
        setState(() {
          selectedBar = d;
        });
        return;
      }
    }

    setState(() {
      selectedBar = null;
    });
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constraints) {
      return GestureDetector(
        behavior: HitTestBehavior.opaque,
        onPanDown: (details) =>
            _handleTapOrDrag(details.localPosition, constraints.biggest),
        onPanUpdate: (details) =>
            _handleTapOrDrag(details.localPosition, constraints.biggest),
        onTapDown: (details) =>
            _handleTapOrDrag(details.localPosition, constraints.biggest),
        child: CustomPaint(
          size: Size(double.infinity, 500.rpx),
          painter: BarChartPainter(
            widget.data,
            widget.startTime,
            widget.endTime,
            maxYValue: widget.maxYValue,
            yStepCount: widget.yStepCount,
            selectedBar: selectedBar,
          ),
        ),
      );
    });
  }
}

class BarChartPainter extends CustomPainter {
  final List<BarData> data;
  final int startTime;
  final int endTime;
  final double maxYValue;
  final int yStepCount;
  final BarData? selectedBar;

  final double topPadding = 0;
  final double bottomPadding = 0;
  final double leftPadding = 30.rpx;

  BarChartPainter(
    this.data,
    this.startTime,
    this.endTime, {
    required this.maxYValue,
    this.yStepCount = 5,
    this.selectedBar,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final chartWidth = size.width - leftPadding;
    final chartHeight = size.height - topPadding - bottomPadding;
    final totalDuration = endTime - startTime;

    final textPainter = TextPainter(textDirection: ui.TextDirection.ltr);
    final stepValue = maxYValue / yStepCount;

    // Y轴刻度
    for (int i = 0; i <= yStepCount; i++) {
      final value = stepValue * i;
      final y = topPadding + chartHeight - (value / maxYValue) * chartHeight;

      final dashPaint = Paint()
        ..color = Colors.grey.withOpacity(0.5)
        ..strokeWidth = 0.5;

      drawDashedLine(
          canvas, Offset(leftPadding, y), Offset(size.width, y), dashPaint);

      textPainter.text = TextSpan(
        text: value.toStringAsFixed(0),
        style: TextStyle(
          fontSize: 20.rpx,
          color: themeController.currentColor.sc4,
        ),
      );
      textPainter.layout();
      textPainter.paint(
        canvas,
        Offset(leftPadding - textPainter.width - 4, y - textPainter.height / 2),
      );
    }

    // X轴刻度
    final startDate = DateTime.fromMillisecondsSinceEpoch(startTime);
    final endDate = DateTime.fromMillisecondsSinceEpoch(endTime);
    final hourStep = const Duration(hours: 1);
    final xAxisY = topPadding + chartHeight;

    for (DateTime t = startDate; t.isBefore(endDate); t = t.add(hourStep)) {
      final x = ((t.millisecondsSinceEpoch - startTime) / totalDuration) *
              chartWidth +
          leftPadding;
      final timeLabel = (t == startDate || t == endDate)
          ? DateFormat('HH:mm').format(t)
          : DateFormat('h').format(t);

      textPainter.text = TextSpan(
        text: timeLabel,
        style: TextStyle(
          fontSize: AppConstants().smaller_text_fontSize,
          color: themeController.currentColor.sc4,
        ),
      );
      textPainter.layout();
      textPainter.paint(canvas, Offset(x - textPainter.width / 2, xAxisY + 4));
    }

    // 额外终点标签
    final endX =
        ((endTime - startTime) / totalDuration) * chartWidth + leftPadding;
    final endLabel = DateFormat('HH:mm').format(endDate);
    textPainter.text = TextSpan(
      text: endLabel,
      style: TextStyle(
        fontSize: AppConstants().smaller_text_fontSize,
        color: themeController.currentColor.sc4,
      ),
    );
    textPainter.layout();
    textPainter.paint(canvas, Offset(endX - textPainter.width / 2, xAxisY + 4));

    // 柱子绘制 & 提示信息缓存
    Offset? tipOffset;
    Size? tipSize;
    String? tipText;
    Color tipColor = Colors.black;

    for (final d in data) {
      final left =
          ((d.st - startTime) / totalDuration) * chartWidth + leftPadding;
      final right =
          ((d.et - startTime) / totalDuration) * chartWidth + leftPadding;
      final barHeight = (d.value / maxYValue) * chartHeight;
      final top = topPadding + chartHeight - barHeight;

      final barPaint = Paint()..color = d.color;
      canvas.drawRect(
        Rect.fromLTRB(left, top, right, topPadding + chartHeight),
        barPaint,
      );

      // 缓存 tip 信息
      if (selectedBar == d) {
        tipText =
            '${d.name}\n${d.value.toStringAsFixed(1)}\n${MyUtils.formatToHHmm(d.st)}';

        final tp = TextPainter(
          text: TextSpan(
            text: tipText,
            style: TextStyle(fontSize: 16.rpx, color: Colors.white),
          ),
          textAlign: TextAlign.center,
          textDirection: ui.TextDirection.ltr,
        );
        tp.layout();

        final tipWidth = tp.width + 20.rpx;
        final tipHeight = tp.height + 10.rpx;
        final tipLeft = left + (right - left) / 2 - tipWidth / 2;
        final tipTop = top - tipHeight - 10.rpx;

        tipOffset = Offset(tipLeft, tipTop);
        tipSize = Size(tipWidth, tipHeight);
        tipColor = Colors.black.withOpacity(0.8);
      }
    }

    // 绘制 tip（在柱子之上）
    if (tipText != null && tipOffset != null && tipSize != null) {
      final rect = RRect.fromRectAndRadius(
        Rect.fromLTWH(
            tipOffset.dx, tipOffset.dy, tipSize.width, tipSize.height),
        Radius.circular(8.rpx),
      );
      final tipBgPaint = Paint()..color = tipColor;
      canvas.drawRRect(rect, tipBgPaint);

      final tipTextPainter = TextPainter(
        text: TextSpan(
          text: tipText,
          style: TextStyle(fontSize: 16.rpx, color: Colors.white),
        ),
        textAlign: TextAlign.center,
        textDirection: ui.TextDirection.ltr,
      );
      tipTextPainter.layout();
      tipTextPainter.paint(
        canvas,
        Offset(tipOffset.dx + 10.rpx, tipOffset.dy + 5.rpx),
      );
    }
  }

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

  void drawDashedLine(Canvas canvas, Offset start, Offset end, Paint paint,
      {double dashWidth = 5, double dashSpace = 3}) {
    double totalLength = (end.dx - start.dx).abs();
    double dashCount = (totalLength / (dashWidth + dashSpace)).floorToDouble();

    double dx = start.dx;
    final dy = start.dy;

    for (int i = 0; i < dashCount; i++) {
      final from = Offset(dx, dy);
      final to = Offset(dx + dashWidth, dy);
      canvas.drawLine(from, to, paint);
      dx += dashWidth + dashSpace;
    }
  }
}
