import 'package:easy_localization/easy_localization.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/common_models/data_points.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';

/// A customizable bar chart widget using `fl_chart`.
///
/// Displays a bar chart with configurable axis labels, colors, and data points.
/// Useful for visualizing comparative data, categories, or grouped values.
///
/// **Parameters:**
/// - [dataPoints]: List of `DataPoint` objects to plot.
/// - [secondaryDataPoints]: Optional list for grouped bars (e.g., comparison data).
/// - [leftLabelFormatter]: Function to build left axis labels.
/// - [bottomLabelFormatter]: Function to build bottom axis labels.
/// - [width]: Optional width of the chart.
/// - [height]: Required height of the chart.
/// - [maxY], [maxX], [minX]: Axis bounds.
/// - [barColor]: Color of the bars.
/// - [secondaryBarColor]: Color of the secondary bars.
/// - [barRadius]: Border radius for bar corners.
/// - [barWidth]: Width of each bar.
/// - [bottomLabelColor]: Color of bottom axis labels.
/// - [bottomLabelSize]: Font size for bottom axis labels.
/// - [bottomLabelFontWeight]: Font weight for bottom axis labels.
/// - [leftLabelInterval]: Interval between left axis labels.
/// - [leftLabelReservedSize]: Reserved space for left axis labels.
/// - [showBottomTitleDates]: Whether to show bottom axis labels.
/// - [isFullScreeGraph]: Whether the graph is fullscreen.
/// - [makeGraphBasedOnActualValue]: Use `actualValue` for plotting.
///
/// Example usage:
/// ```dart
/// CustomBarChart(
///   dataPoints: sampleData,
///   leftLabelFormatter: (value) => ...,
///   bottomLabelFormatter: (value, dataPoints) => ...,
///   height: 300,
///   maxY: 100,
/// )
class CustomBarChart extends StatelessWidget {
  final List<DataPoint> dataPoints;
  final List<DataPoint>? secondaryDataPoints; // For grouped bar charts
  final double? width;
  final double height;
  final double? maxY;
  final double? maxX;
  final double? minX;
  Color? barColor;
  final Color? secondaryBarColor;
  Color? barGridColor;
  Color? bottomLabelColor;
  final double? bottomLabelSize;
  final FontWeight? bottomLabelFontWeight;
  final double? leftLabelInterval;
  final double? leftLabelReservedSize;
  final double? bottomLabelReservedSize;
  final bool? showGridLines;
  final GetDrawingGridLine? getDrawingVerticalLine;
  final double? verticalInterval;
  final double? minY;
  final BorderRadius? barRadius;
  final double barWidth;
  final BarTooltipItem Function(DataPoint)? getTooltipItem;

  /// Creates the left label and provides it to the chart
  final Widget Function(double) leftLabelFormatter;
  final Widget Function(double, List<DataPoint>) bottomLabelFormatter;

  final bool showBottomTitleDates;
  final bool isFullScreeGraph;
  final bool makeGraphBasedOnActualValue;

   CustomBarChart(
      {super.key,
        required this.dataPoints,
        this.secondaryDataPoints,
        required this.leftLabelFormatter,
        this.width,
        required this.height,
        this.maxY,
        this.maxX,
        this.showBottomTitleDates = true,
        this.isFullScreeGraph = false,
        this.secondaryBarColor,
        this.bottomLabelFontWeight = FontWeight.w600,
        this.bottomLabelSize,
        this.leftLabelInterval,
        this.leftLabelReservedSize,
        this.bottomLabelReservedSize,
        this.makeGraphBasedOnActualValue = false,
        required this.bottomLabelFormatter,
        this.minX,
        this.showGridLines = false,
        this.getDrawingVerticalLine,
        this.verticalInterval,
        this.minY,
        this.barRadius,
        this.barWidth = 16,
        this.getTooltipItem,
        this.barColor ,
        this.barGridColor ,
        this.bottomLabelColor,
      });

  @override
  Widget build(BuildContext context) {
      barColor ??= AppColors.bgGreenColor;
      barGridColor ??= AppColors.graphGridColor;
      bottomLabelColor ??= AppColors.textColor;
    return Material(
      color: Colors.white,
      child: SizedBox(
        width: width,
        height: height,
        child: BarChart(
          BarChartData(
              minY: minY ?? 0,
              maxY: maxY,

              barTouchData: BarTouchData(
                handleBuiltInTouches: true,
                touchCallback: (FlTouchEvent event, BarTouchResponse? touchResponse) {
                  // Let fl_chart handle the touch
                },

                touchTooltipData: BarTouchTooltipData(
                  getTooltipColor: (_)=>AppColorsContext.tooltipColor,
                  getTooltipItem: (group, groupIndex, rod, rodIndex) {
                    final dataPoint = dataPoints[groupIndex];
                    if(getTooltipItem != null) {
                      return getTooltipItem!(dataPoint);
                    }

                    return BarTooltipItem(
                      '${dataPoint.actualValue} ${dataPoint.unitOfMeasurement ?? ""}\n${DateFormat('dd MMM, yyyy').format(dataPoint.time)}',
                      TextStyle(
                        color: Colors.black,
                        fontSize: 12.f,
                        fontWeight: FontWeight.w600,
                      ),
                    );
                  },
                ),
                enabled: true,
              ),
              titlesData: FlTitlesData(
                leftTitles: AxisTitles(
                  sideTitles: SideTitles(
                    showTitles: true,
                    reservedSize: leftLabelReservedSize ?? 80,
                    interval: leftLabelInterval ?? .1,
                    getTitlesWidget: (value, _) {
                      return leftLabelFormatter(value);
                    },
                  ),
                ),
                bottomTitles: AxisTitles(
                  axisNameSize: 20,
                  sideTitles: SideTitles(
                    showTitles: showBottomTitleDates,
                    reservedSize: bottomLabelReservedSize ?? 30,
                    getTitlesWidget: (value, _) {
                      return bottomLabelFormatter(value, dataPoints);
                    },
                    interval: 1,
                  ),
                ),
                topTitles: AxisTitles(),
                rightTitles: AxisTitles(),
              ),
              borderData: FlBorderData(
                show: true,
                border: const Border(
                  bottom: BorderSide.none,
                  left: BorderSide(color: Colors.grey, width: .5),
                  right: BorderSide.none,
                  top: BorderSide.none,
                ),
              ),
              barGroups: _buildBarGroups(dataPoints),

              gridData: FlGridData(
                show: showGridLines ?? true,
                drawHorizontalLine: false,
                verticalInterval: verticalInterval,
                getDrawingVerticalLine: getDrawingVerticalLine ??
                        (value) {
                      return FlLine(
                        color: barGridColor,
                        strokeWidth: 1,
                        dashArray: [5, 5],
                      );
                    },
              )),
        ),
      ),
    );
  }

  /// Builds bar chart groups from data points
  List<BarChartGroupData> _buildBarGroups(List<DataPoint> dataPoints) {
    return dataPoints.asMap().entries.map((entry) {
      final index = entry.key;
      final dataPoint = entry.value;
      double value = (makeGraphBasedOnActualValue)
          ? double.tryParse(dataPoint.actualValue) ?? 0.0
          : dataPoint.value;

      final barRods = <BarChartRodData>[
        BarChartRodData(
          toY: value,
          color: barColor,
          width: barWidth,
          borderRadius: barRadius ?? BorderRadius.circular(6),
          // backDrawRodData: BackgroundBarChartRodData(
          //   show: true,
          //   toY: maxY,
          //   color: Colors.grey[100],
          // ),
        ),
      ];

      // Add secondary bar if provided (for grouped bar charts)
      if (secondaryDataPoints != null && index < secondaryDataPoints!.length) {
        final secondaryDataPoint = secondaryDataPoints![index];
        double secondaryValue = (makeGraphBasedOnActualValue)
            ? double.tryParse(secondaryDataPoint.actualValue) ?? 0.0
            : secondaryDataPoint.value;

        barRods.add(
          BarChartRodData(
            toY: secondaryValue,
            color: secondaryBarColor ?? AppColors.blueColor,
            width: barWidth,
            borderRadius: barRadius ?? BorderRadius.circular(6),
          ),
        );
      }

      return BarChartGroupData(
        x: index,
        barRods: barRods,
        barsSpace: 8.w
      );
    }).toList();
  }
}