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

/// 技术指标绘制器（MACD/KDJ/RSI）
class KlineIndicatorPainter extends CustomPainter {
  final int indicatorType; // 0: MACD, 1: KDJ, 2: RSI
  final Map<String, List<double?>>? macdData;
  final Map<String, List<double?>>? kdjData;
  final List<double?>? rsiData;
  final int crossLineIndex;
  final double? candleWidth;

  static const Color _green = Color(0xFF10B981);
  static const Color _red = Color(0xFFEF4444);
  static const Color _gridColor = Color(0xFFE5E7EB);
  static const Color _textColor = Color(0xFF6B7280);
  static const Color _zeroLineColor = Color(0xFF9CA3AF);

  // MACD颜色
  static const Color _difColor = Color(0xFFFF9800);
  static const Color _deaColor = Color(0xFF2196F3);

  // KDJ颜色
  static const Color _kColor = Color(0xFFFF9800);
  static const Color _dColor = Color(0xFF2196F3);
  static const Color _jColor = Color(0xFF9C27B0);

  // RSI颜色
  static const Color _rsiColor = Color(0xFFFF9800);

  KlineIndicatorPainter({
    required this.indicatorType,
    this.macdData,
    this.kdjData,
    this.rsiData,
    this.crossLineIndex = -1,
    this.candleWidth,
  });

  @override
  void paint(Canvas canvas, Size size) {
    const leftPadding = 8.0;
    const rightPadding = 50.0;
    const topPadding = 16.0;
    const bottomPadding = 4.0;

    final chartWidth = size.width - leftPadding - rightPadding;
    final chartHeight = size.height - topPadding - bottomPadding;

    // 绘制分隔线
    final gridPaint = Paint()
      ..color = _gridColor
      ..strokeWidth = 0.5;
    canvas.drawLine(
      Offset(leftPadding, 0),
      Offset(size.width - rightPadding, 0),
      gridPaint,
    );

    switch (indicatorType) {
      case 0:
        _drawMACD(canvas, size, leftPadding, rightPadding, topPadding, bottomPadding, chartWidth, chartHeight);
        break;
      case 1:
        _drawKDJ(canvas, size, leftPadding, rightPadding, topPadding, bottomPadding, chartWidth, chartHeight);
        break;
      case 2:
        _drawRSI(canvas, size, leftPadding, rightPadding, topPadding, bottomPadding, chartWidth, chartHeight);
        break;
    }

    // 绘制十字线
    if (crossLineIndex >= 0) {
      final dataLength = _getDataLength();
      if (dataLength > 0 && crossLineIndex < dataLength) {
        final actualCandleWidth = candleWidth ?? (chartWidth / dataLength);
        final x = leftPadding + crossLineIndex * actualCandleWidth + actualCandleWidth / 2;
        canvas.drawLine(
          Offset(x, 0),
          Offset(x, size.height),
          Paint()
            ..color = const Color(0xFF9CA3AF)
            ..strokeWidth = 0.5,
        );
      }
    }
  }

  int _getDataLength() {
    if (macdData != null && macdData!['dif'] != null) return macdData!['dif']!.length;
    if (kdjData != null && kdjData!['k'] != null) return kdjData!['k']!.length;
    if (rsiData != null) return rsiData!.length;
    return 0;
  }

  void _drawMACD(
    Canvas canvas,
    Size size,
    double leftPadding,
    double rightPadding,
    double topPadding,
    double bottomPadding,
    double chartWidth,
    double chartHeight,
  ) {
    if (macdData == null) return;

    final dif = macdData!['dif'] ?? [];
    final dea = macdData!['dea'] ?? [];
    final macd = macdData!['macd'] ?? [];

    if (dif.isEmpty) return;

    // 计算范围
    double minValue = double.infinity;
    double maxValue = double.negativeInfinity;

    for (final list in [dif, dea, macd]) {
      for (final v in list) {
        if (v != null) {
          if (v < minValue) minValue = v;
          if (v > maxValue) maxValue = v;
        }
      }
    }

    // 确保零线在中间附近
    final absMax = math.max(maxValue.abs(), minValue.abs());
    minValue = -absMax * 1.1;
    maxValue = absMax * 1.1;
    final range = maxValue - minValue;

    if (range == 0) return;

    double valueToY(double value) {
      return topPadding + ((maxValue - value) / range) * chartHeight;
    }

    // 绘制零线
    final zeroY = valueToY(0);
    canvas.drawLine(
      Offset(leftPadding, zeroY),
      Offset(size.width - rightPadding, zeroY),
      Paint()
        ..color = _zeroLineColor
        ..strokeWidth = 0.5,
    );

    // 绘制MACD柱状图
    final actualCandleWidth = candleWidth ?? (chartWidth / macd.length);
    final barWidth = math.max(actualCandleWidth * 0.6, 2.0);

    for (int i = 0; i < macd.length; i++) {
      if (macd[i] == null) continue;

      final value = macd[i]!;
      final x = leftPadding + i * actualCandleWidth + actualCandleWidth / 2;
      final y = valueToY(value);

      final color = value >= 0 ? _red : _green;
      final alpha = (crossLineIndex >= 0 && crossLineIndex != i) ? 0.4 : 1.0;

      if (value >= 0) {
        canvas.drawRect(
          Rect.fromLTRB(x - barWidth / 2, y, x + barWidth / 2, zeroY),
          Paint()..color = color.withOpacity(alpha),
        );
      } else {
        canvas.drawRect(
          Rect.fromLTRB(x - barWidth / 2, zeroY, x + barWidth / 2, y),
          Paint()..color = color.withOpacity(alpha),
        );
      }
    }

    // 绘制DIF线
    _drawIndicatorLine(canvas, dif, _difColor, leftPadding, actualCandleWidth, valueToY);

    // 绘制DEA线
    _drawIndicatorLine(canvas, dea, _deaColor, leftPadding, actualCandleWidth, valueToY);

    // 绘制图例
    _drawMACDLegend(canvas, size, leftPadding, dif, dea, macd);
  }

  void _drawKDJ(
    Canvas canvas,
    Size size,
    double leftPadding,
    double rightPadding,
    double topPadding,
    double bottomPadding,
    double chartWidth,
    double chartHeight,
  ) {
    if (kdjData == null) return;

    final k = kdjData!['k'] ?? [];
    final d = kdjData!['d'] ?? [];
    final j = kdjData!['j'] ?? [];

    if (k.isEmpty) return;

    // KDJ的范围通常是0-100，但J可能超出
    double minValue = 0;
    double maxValue = 100;

    for (final v in j) {
      if (v != null) {
        if (v < minValue) minValue = v;
        if (v > maxValue) maxValue = v;
      }
    }

    final range = maxValue - minValue;
    if (range == 0) return;

    double valueToY(double value) {
      return topPadding + ((maxValue - value) / range) * chartHeight;
    }

    // 绘制参考线（20、50、80）
    final refLinePaint = Paint()
      ..color = _gridColor
      ..strokeWidth = 0.5;

    for (final level in [20.0, 50.0, 80.0]) {
      if (level >= minValue && level <= maxValue) {
        final y = valueToY(level);
        canvas.drawLine(
          Offset(leftPadding, y),
          Offset(size.width - rightPadding, y),
          refLinePaint,
        );
      }
    }

    final actualCandleWidth = candleWidth ?? (chartWidth / k.length);

    // 绘制K线
    _drawIndicatorLine(canvas, k, _kColor, leftPadding, actualCandleWidth, valueToY);

    // 绘制D线
    _drawIndicatorLine(canvas, d, _dColor, leftPadding, actualCandleWidth, valueToY);

    // 绘制J线
    _drawIndicatorLine(canvas, j, _jColor, leftPadding, actualCandleWidth, valueToY);

    // 绘制图例
    _drawKDJLegend(canvas, size, leftPadding, k, d, j);
  }

  void _drawRSI(
    Canvas canvas,
    Size size,
    double leftPadding,
    double rightPadding,
    double topPadding,
    double bottomPadding,
    double chartWidth,
    double chartHeight,
  ) {
    if (rsiData == null || rsiData!.isEmpty) return;

    // RSI范围是0-100
    const minValue = 0.0;
    const maxValue = 100.0;
    const range = maxValue - minValue;

    double valueToY(double value) {
      return topPadding + ((maxValue - value) / range) * chartHeight;
    }

    // 绘制参考线（30、50、70）
    final refLinePaint = Paint()
      ..color = _gridColor
      ..strokeWidth = 0.5;

    for (final level in [30.0, 50.0, 70.0]) {
      final y = valueToY(level);
      canvas.drawLine(
        Offset(leftPadding, y),
        Offset(size.width - rightPadding, y),
        refLinePaint,
      );
    }

    // 绘制超买超卖区域
    final overboughtPaint = Paint()
      ..color = _red.withOpacity(0.1)
      ..style = PaintingStyle.fill;
    canvas.drawRect(
      Rect.fromLTRB(leftPadding, valueToY(100), size.width - rightPadding, valueToY(70)),
      overboughtPaint,
    );

    final oversoldPaint = Paint()
      ..color = _green.withOpacity(0.1)
      ..style = PaintingStyle.fill;
    canvas.drawRect(
      Rect.fromLTRB(leftPadding, valueToY(30), size.width - rightPadding, valueToY(0)),
      oversoldPaint,
    );

    final actualCandleWidth = candleWidth ?? (chartWidth / rsiData!.length);

    // 绘制RSI线
    _drawIndicatorLine(canvas, rsiData!, _rsiColor, leftPadding, actualCandleWidth, valueToY);

    // 绘制图例
    _drawRSILegend(canvas, size, leftPadding, rsiData!);
  }

  void _drawIndicatorLine(
    Canvas canvas,
    List<double?> data,
    Color color,
    double leftPadding,
    double candleWidth,
    double Function(double) valueToY,
  ) {
    final paint = Paint()
      ..color = color
      ..strokeWidth = 1
      ..style = PaintingStyle.stroke;

    final path = Path();
    bool started = false;

    for (int i = 0; i < data.length; i++) {
      if (data[i] != null) {
        final x = leftPadding + i * candleWidth + candleWidth / 2;
        final y = valueToY(data[i]!);

        if (!started) {
          path.moveTo(x, y);
          started = true;
        } else {
          path.lineTo(x, y);
        }
      }
    }

    canvas.drawPath(path, paint);
  }

  void _drawMACDLegend(
    Canvas canvas,
    Size size,
    double leftPadding,
    List<double?> dif,
    List<double?> dea,
    List<double?> macd,
  ) {
    final textPainter = TextPainter(textDirection: ui.TextDirection.ltr);
    double x = leftPadding;
    const y = 2.0;

    // 获取当前值（十字线位置或最后一个值）
    int index = crossLineIndex >= 0 && crossLineIndex < dif.length ? crossLineIndex : dif.length - 1;

    final difValue = index >= 0 && index < dif.length ? dif[index] : null;
    final deaValue = index >= 0 && index < dea.length ? dea[index] : null;
    final macdValue = index >= 0 && index < macd.length ? macd[index] : null;

    textPainter.text = TextSpan(
      text: 'MACD(12,26,9)',
      style: const TextStyle(color: _textColor, fontSize: 9),
    );
    textPainter.layout();
    textPainter.paint(canvas, Offset(x, y));
    x += textPainter.width + 8;

    if (difValue != null) {
      textPainter.text = TextSpan(
        text: 'DIF:${difValue.toStringAsFixed(6)}',
        style: const TextStyle(color: _difColor, fontSize: 9),
      );
      textPainter.layout();
      textPainter.paint(canvas, Offset(x, y));
      x += textPainter.width + 8;
    }

    if (deaValue != null) {
      textPainter.text = TextSpan(
        text: 'DEA:${deaValue.toStringAsFixed(6)}',
        style: const TextStyle(color: _deaColor, fontSize: 9),
      );
      textPainter.layout();
      textPainter.paint(canvas, Offset(x, y));
      x += textPainter.width + 8;
    }

    if (macdValue != null) {
      textPainter.text = TextSpan(
        text: 'MACD:${macdValue.toStringAsFixed(6)}',
        style: TextStyle(color: macdValue >= 0 ? _red : _green, fontSize: 9),
      );
      textPainter.layout();
      textPainter.paint(canvas, Offset(x, y));
    }
  }

  void _drawKDJLegend(
    Canvas canvas,
    Size size,
    double leftPadding,
    List<double?> k,
    List<double?> d,
    List<double?> j,
  ) {
    final textPainter = TextPainter(textDirection: ui.TextDirection.ltr);
    double x = leftPadding;
    const y = 2.0;

    int index = crossLineIndex >= 0 && crossLineIndex < k.length ? crossLineIndex : k.length - 1;

    final kValue = index >= 0 && index < k.length ? k[index] : null;
    final dValue = index >= 0 && index < d.length ? d[index] : null;
    final jValue = index >= 0 && index < j.length ? j[index] : null;

    textPainter.text = TextSpan(
      text: 'KDJ(9,3,3)',
      style: const TextStyle(color: _textColor, fontSize: 9),
    );
    textPainter.layout();
    textPainter.paint(canvas, Offset(x, y));
    x += textPainter.width + 8;

    if (kValue != null) {
      textPainter.text = TextSpan(
        text: 'K:${kValue.toStringAsFixed(2)}',
        style: const TextStyle(color: _kColor, fontSize: 9),
      );
      textPainter.layout();
      textPainter.paint(canvas, Offset(x, y));
      x += textPainter.width + 8;
    }

    if (dValue != null) {
      textPainter.text = TextSpan(
        text: 'D:${dValue.toStringAsFixed(2)}',
        style: const TextStyle(color: _dColor, fontSize: 9),
      );
      textPainter.layout();
      textPainter.paint(canvas, Offset(x, y));
      x += textPainter.width + 8;
    }

    if (jValue != null) {
      textPainter.text = TextSpan(
        text: 'J:${jValue.toStringAsFixed(2)}',
        style: const TextStyle(color: _jColor, fontSize: 9),
      );
      textPainter.layout();
      textPainter.paint(canvas, Offset(x, y));
    }
  }

  void _drawRSILegend(
    Canvas canvas,
    Size size,
    double leftPadding,
    List<double?> rsi,
  ) {
    final textPainter = TextPainter(textDirection: ui.TextDirection.ltr);
    double x = leftPadding;
    const y = 2.0;

    int index = crossLineIndex >= 0 && crossLineIndex < rsi.length ? crossLineIndex : rsi.length - 1;
    final rsiValue = index >= 0 && index < rsi.length ? rsi[index] : null;

    textPainter.text = TextSpan(
      text: 'RSI(14)',
      style: const TextStyle(color: _textColor, fontSize: 9),
    );
    textPainter.layout();
    textPainter.paint(canvas, Offset(x, y));
    x += textPainter.width + 8;

    if (rsiValue != null) {
      Color color = _rsiColor;
      if (rsiValue >= 70) color = _red;
      if (rsiValue <= 30) color = _green;

      textPainter.text = TextSpan(
        text: 'RSI:${rsiValue.toStringAsFixed(2)}',
        style: TextStyle(color: color, fontSize: 9),
      );
      textPainter.layout();
      textPainter.paint(canvas, Offset(x, y));
    }
  }

  @override
  bool shouldRepaint(covariant KlineIndicatorPainter oldDelegate) {
    return oldDelegate.indicatorType != indicatorType ||
        oldDelegate.macdData != macdData ||
        oldDelegate.kdjData != kdjData ||
        oldDelegate.rsiData != rsiData ||
        oldDelegate.crossLineIndex != crossLineIndex ||
        oldDelegate.candleWidth != candleWidth;
  }
}
