import 'dart:math';
import 'package:flutter/material.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:intl/intl.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/num_extension.dart';
import 'models/transaction_summary_by_date_model.dart';

class MonthlyPointsChart extends StatelessWidget {
  const MonthlyPointsChart({
    super.key,
    required this.items,
    required this.date,
    this.monthSummary,
    this.onPrevMonth,
    this.onNextMonth,
    this.onChangeDate,
  });

  final MonthSummaryChartModel? monthSummary;
  final List<DaySummaryChartModel> items;
  final DateTime date;
  final VoidCallback? onPrevMonth;
  final VoidCallback? onNextMonth;
  final VoidCallback? onChangeDate;
  final EdgeInsets cardPadding = const EdgeInsets.all(16);

  @override
  Widget build(BuildContext context) {
    final parsed = _parseToDayMap(items, date);
    final daysInMonth = DateUtils.getDaysInMonth(date.year, date.month);
    final maxVal = parsed.values.isEmpty ? 0 : parsed.values.reduce((a, b) => a > b ? a : b);
    final yMax = _niceMax(maxVal.abs().toDouble());
    final yStep = _niceStep(yMax);
    
    final stats = _statsByDay(items, date);
    final barGroups = List.generate(daysInMonth, (i) {
      final day = i + 1;
      final v = parsed[day] ?? 0.0;
      final color = v >= 0 ? const Color(0xFFFE515A) : const Color(0xFF21C777);
      return BarChartGroupData(
        x: day,
        barRods: [BarChartRodData(toY: v, width: 8, borderRadius: BorderRadius.circular(2), color: color)],
      );
    });
    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(16),
        boxShadow: const [BoxShadow(color: Colors.black26, blurRadius: 12, offset: Offset(0, 3))],
      ),
      padding: cardPadding,
      margin: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          const SizedBox(height: 4),
          const Center(child: Text('Thống kê tích điểm', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600))),
          const SizedBox(height: 8),
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                _toDouble(monthSummary?.rewardMonthTotal ?? '0').money(CurrencyUnit.noneSpace),
                style: const TextStyle(
                  fontSize: 40,
                  fontWeight: FontWeight.w700,
                  color: Color(0xFF21C777),
                  height: 1.0,
                ),
              ),
              const SizedBox(width: 4),
              Image.asset('assets/images/ic_point.png', width: 20, height: 20),
            ],
          ),
          const SizedBox(height: 24),
          SizedBox(
            height: 160,
            child: BarChart(
              BarChartData(
                minY: 0,
                maxY: yMax > 0 ? yMax : 10, // Đảm bảo có giá trị tối thiểu
                barGroups: barGroups,
                gridData: FlGridData(
                  show: true,
                  drawVerticalLine: false,
                  horizontalInterval: yStep > 0 ? yStep : 2,
                  getDrawingHorizontalLine: (v) => FlLine(color: Colors.black12, strokeWidth: 1),
                ),
                extraLinesData: ExtraLinesData(
                  extraLinesOnTop: true,
                  horizontalLines: [
                    HorizontalLine(y: 0, color: Colors.black12, strokeWidth: 1),
                    HorizontalLine(y: yMax > 0 ? yMax : 10, color: Colors.black12, strokeWidth: 1),
                  ],
                ),
                titlesData: FlTitlesData(
                  topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
                  rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
                  leftTitles: AxisTitles(
                    sideTitles: SideTitles(
                      reservedSize: 40, // Tăng độ rộng để chứa text dài
                      showTitles: true,
                      interval: yStep > 0 ? yStep : 2,
                      getTitlesWidget: (value, meta) {
                        final text = _formatYAxisLabel(value.toInt());
                        return SizedBox(
                          width: 35, // Cố định độ rộng
                          child: Text(
                            text,
                            style: const TextStyle(fontSize: 9, color: Colors.black54),
                            textAlign: TextAlign.right,
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                          ),
                        );
                      },
                    ),
                  ),
                  bottomTitles: AxisTitles(
                    sideTitles: SideTitles(
                      showTitles: true,
                      interval: 4, // hiển thị 1,5,9,...; muốn 1,5,10,15... đổi thành 5
                      getTitlesWidget: (value, meta) {
                        final d = value.toInt();
                        if (d < 1 || d > daysInMonth) return const SizedBox.shrink();
                        // chỉ hiện 1,5,10,15,20,25,31 để đỡ rối
                        var marks = {1, 5, 10, 15, 20, 25, daysInMonth};
                        if (!marks.contains(d)) return const SizedBox.shrink();
                        return Padding(
                          padding: const EdgeInsets.only(top: 4),
                          child: Text('$d', style: const TextStyle(fontSize: 10, color: Colors.black54)),
                        );
                      },
                    ),
                  ),
                ),
                borderData: FlBorderData(show: false),
                barTouchData: BarTouchData(
                  enabled: true,
                  handleBuiltInTouches: true,
                  touchTooltipData: BarTouchTooltipData(
                    // tooltipBgColor: Colors.black87,
                    fitInsideHorizontally: true,
                    fitInsideVertically: true,
                    getTooltipItem: (group, groupIndex, rod, rodIndex) {
                      final day = group.x.toInt();
                      final stat = stats[day];
                      final r = stat?.reward ?? 0;
                      return BarTooltipItem(
                        textAlign: TextAlign.center,
                        'Ngày $day/${date.month}\n'
                        'Tích điểm: ${r.money(CurrencyUnit.noneSpace)}',
                        const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w500),
                      );
                    },
                  ),
                ),
              ),
            ),
          ),
          const SizedBox(height: 12),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              IconButton(
                visualDensity: VisualDensity.compact,
                onPressed: onPrevMonth,
                icon: Icon(Icons.chevron_left, color: Colors.blue[900]),
              ),
              GestureDetector(
                onTap: onChangeDate,
                child: Container(
                  padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
                  child: Text(
                    'Tháng ${date.month}/${date.year}',
                    style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15, color: Colors.blue[900]),
                  ),
                ),
              ),
              IconButton(
                visualDensity: VisualDensity.compact,
                onPressed: onNextMonth,
                icon: Icon(Icons.chevron_right, color: Colors.blue[900]),
              ),
            ],
          ),
        ],
      ),
    );
  }

  /// Map<day, value> cho tháng đang chọn
  Map<int, double> _parseToDayMap(List<DaySummaryChartModel> list, DateTime month) {
    final map = <int, double>{};
    final m = month.month;
    final y = month.year;

    for (final e in list) {
      final dt = _parseYmd(e.summaryDate);
      if (dt == null || dt.month != m || dt.year != y) continue;

      final reward = _toDouble(e.rewardDayTotal);
      // final redeem = _toDouble(e.redeemDayTotal);
      // final adjust = _toDouble(e.adjustDayTotal);
      // final val = reward - redeem + adjust;
      var val = (map[dt.day] ?? 0) + reward;
      val = max(val, 0); // không âm
      map[dt.day] = val; // gộp nếu trùng ngày
    }
    return map;
  }

  static final _fmtYmd = DateFormat('yyyy-MM-dd');

  DateTime? _parseYmd(String? s) {
    if (s == null || s.isEmpty) return null;
    try {
      return _fmtYmd.parseStrict(s);
    } catch (_) {
      return DateTime.tryParse(s);
    }
  }

  double _toDouble(String? v) {
    if (v == null) return 0;
    final s = v.replaceAll(RegExp(r'[,\s_]'), '');
    return double.tryParse(s) ?? 0;
  }

  /// Format Y-axis label để hiển thị gọn gàng
  String _formatYAxisLabel(int value) {
    if (value >= 1000000) {
      return '${(value / 1000000).toStringAsFixed(1)}M';
    } else if (value >= 1000) {
      return '${(value / 1000).toStringAsFixed(0)}K';
    } else {
      return value.toString();
    }
  }

  /// Làm tròn max Y cho đẹp (bước 4/5)
  double _niceMax(double maxVal) {
    if (maxVal <= 0) return 10;
    
    // Xử lý giá trị lớn (> 1000)
    if (maxVal > 1000) {
      // Làm tròn lên đến bội số 1000 gần nhất
      final up = ((maxVal / 1000).ceil()) * 1000;
      return up.toDouble();
    }
    
    // Xử lý giá trị nhỏ (< 1000)
    final candidates = [4, 5, 10, 20, 50, 100];
    for (final step in candidates) {
      final up = ((maxVal / step).ceil()) * step;
      if (up >= maxVal && up / step <= 6) return up.toDouble(); // tối đa 6 vạch cho gọn
    }
    return ((maxVal / 10).ceil()) * 10.0;
  }

  double _niceStep(double yMax) {
    if (yMax <= 10) return 2; // 0,2,4,6,8,10
    if (yMax <= 20) return 4; // 0,4,8,12,16,20
    if (yMax <= 50) return 10;
    if (yMax <= 100) return 20;
    if (yMax <= 500) return 50;
    if (yMax <= 1000) return 100;
    if (yMax <= 5000) return 500;
    if (yMax <= 10000) return 1000;
    if (yMax <= 50000) return 5000;
    if (yMax <= 100000) return 10000;
    if (yMax <= 500000) return 50000;
    if (yMax <= 1000000) return 100000;
    return 200000; // cho giá trị rất lớn
  }

  Map<int, _DayStat> _statsByDay(List<DaySummaryChartModel> list, DateTime month) {
    final map = <int, _DayStat>{};
    for (final e in list) {
      final dt = _parseYmd(e.summaryDate);
      if (dt == null || dt.month != month.month || dt.year != month.year) continue;
      final rwd = _toDouble(e.rewardDayTotal);
      final rdm = _toDouble(e.redeemDayTotal);
      final adj = _toDouble(e.adjustDayTotal);
      final cur = map[dt.day];
      map[dt.day] =
          cur == null ? _DayStat(rwd, rdm, adj) : _DayStat(cur.reward + rwd, cur.redeem + rdm, cur.adjust + adj);
    }
    return map;
  }
}

class _DayStat {
  _DayStat(this.reward, this.redeem, this.adjust);

  final double reward, redeem, adjust;

  double get net => reward - redeem + adjust;
}
