import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:on_field_work/controller/dashboard/dashboard_controller.dart';
import 'package:on_field_work/helpers/widgets/my_text.dart';
import 'package:on_field_work/helpers/utils/utils.dart';
import 'package:intl/intl.dart';

// =========================
// CONSTANTS
// =========================
class _ChartConstants {
  static const List<Color> flatColors = [
    Color(0xFFE57373),
    Color(0xFF64B5F6),
    Color(0xFF81C784),
    Color(0xFFFFB74D),
    Color(0xFFBA68C8),
    Color(0xFFFF8A65),
    Color(0xFF4DB6AC),
    Color(0xFFA1887F),
    Color(0xFFDCE775),
    Color(0xFF9575CD),
    Color(0xFF7986CB),
    Color(0xFFAED581),
    Color(0xFFFF7043),
    Color(0xFF4FC3F7),
    Color(0xFFFFD54F),
    Color(0xFF90A4AE),
    Color(0xFFE573BB),
    Color(0xFF81D4FA),
    Color(0xFFBCAAA4),
    Color(0xFFA5D6A7),
    Color(0xFFCE93D8),
    Color(0xFFFF8A65),
    Color(0xFF80CBC4),
    Color(0xFFFFF176),
    Color(0xFF90CAF9),
    Color(0xFFE0E0E0),
    Color(0xFFF48FB1),
    Color(0xFFA1887F),
    Color(0xFFB0BEC5),
    Color(0xFF81C784),
    Color(0xFFFFB74D),
    Color(0xFF64B5F6),
  ];

  static const Map<MonthlyExpenseDuration, String> durationLabels = {
    MonthlyExpenseDuration.oneMonth: "1M",
    MonthlyExpenseDuration.threeMonths: "3M",
    MonthlyExpenseDuration.sixMonths: "6M",
    MonthlyExpenseDuration.twelveMonths: "12M",
    MonthlyExpenseDuration.all: "All",
  };

  static const double mobileBreakpoint = 600;
  static const double mobileChartHeight = 350;
  static const double desktopChartHeight = 400;
  static const double mobilePadding = 12;
  static const double desktopPadding = 20;
  static const double mobileVerticalPadding = 16;
  static const double desktopVerticalPadding = 20;
  static const double noDataIconSize = 48;
  static const double noDataContainerHeight = 220;
  static const double labelRotation = 45;
  static const int tooltipAnimationDuration = 300;
}

// =========================
// MAIN CHART WIDGET
// =========================
class MonthlyExpenseDashboardChart extends StatelessWidget {
  MonthlyExpenseDashboardChart({Key? key}) : super(key: key);

  final DashboardController _controller = Get.find<DashboardController>();

  Color _getColorForIndex(int index) =>
      _ChartConstants.flatColors[index % _ChartConstants.flatColors.length];

  BoxDecoration get _containerDecoration => BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(5),
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.05),
            blurRadius: 6,
            spreadRadius: 1,
            offset: const Offset(0, 2),
          ),
        ],
      );

  bool _isMobileLayout(double screenWidth) =>
      screenWidth < _ChartConstants.mobileBreakpoint;

  double _calculateTotalExpense(List<dynamic> data) =>
      data.fold<double>(0, (sum, item) => sum + item.total);

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;
    final isMobile = _isMobileLayout(screenWidth);

    return Obx(() {
      final isLoading = _controller.isMonthlyExpenseLoading.value;
      final expenseData = _controller.monthlyExpenseList;
      final selectedDuration = _controller.selectedMonthlyExpenseDuration.value;
      final totalExpense = _calculateTotalExpense(expenseData);

      return Container(
        decoration: _containerDecoration,
        padding: EdgeInsets.symmetric(
          vertical: isMobile
              ? _ChartConstants.mobileVerticalPadding
              : _ChartConstants.desktopVerticalPadding,
          horizontal: isMobile
              ? _ChartConstants.mobilePadding
              : _ChartConstants.desktopPadding,
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _ChartHeader(
              controller: _controller, // pass controller explicitly
              selectedDuration: selectedDuration,
              onDurationChanged: _controller.updateMonthlyExpenseDuration,
              totalExpense: totalExpense,
            ),
            const SizedBox(height: 12),
            SizedBox(
              height: isMobile
                  ? _ChartConstants.mobileChartHeight
                  : _ChartConstants.desktopChartHeight,
              child: _buildChartContent(
                isLoading: isLoading,
                data: expenseData,
                isMobile: isMobile,
                totalExpense: totalExpense,
              ),
            ),
          ],
        ),
      );
    });
  }

  Widget _buildChartContent({
    required bool isLoading,
    required List<dynamic> data,
    required bool isMobile,
    required double totalExpense,
  }) {
    if (isLoading) {
      return const Center(child: CircularProgressIndicator());
    }

    if (data.isEmpty) {
      return const _EmptyDataWidget();
    }

    return _MonthlyExpenseChart(
      data: data,
      getColor: _getColorForIndex,
      isMobile: isMobile,
      totalExpense: totalExpense,
    );
  }
}

// =========================
// HEADER WIDGET
// =========================
class _ChartHeader extends StatelessWidget {
  const _ChartHeader({
    Key? key,
    required this.controller, // added
    required this.selectedDuration,
    required this.onDurationChanged,
    required this.totalExpense,
  }) : super(key: key);

  final DashboardController controller; // added
  final MonthlyExpenseDuration selectedDuration;
  final ValueChanged<MonthlyExpenseDuration> onDurationChanged;
  final double totalExpense;

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        _buildTitle(),
        const SizedBox(height: 2),
        _buildSubtitle(),
        const SizedBox(height: 8),
        // ==========================
        // Row with popup menu on the right
        // ==========================
        Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            Obx(() {
              final selectedType = controller.selectedExpenseType.value;

              return PopupMenuButton<String>(
                tooltip: 'Filter by Expense Category',
                onSelected: (String value) {
                  if (value == 'all') {
                    controller.updateSelectedExpenseType(null);
                  } else {
                    final type = controller.expenseTypes
                        .firstWhere((t) => t.id == value);
                    controller.updateSelectedExpenseType(type);
                  }
                },
                itemBuilder: (context) {
                  final types = controller.expenseTypes;
                  return [
                    PopupMenuItem<String>(
                      value: 'all',
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          const Text('All Types'),
                          if (selectedType == null)
                            const Icon(Icons.check,
                                size: 16, color: Colors.blueAccent),
                        ],
                      ),
                    ),
                    ...types.map((type) => PopupMenuItem<String>(
                          value: type.id,
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            children: [
                              Text(type.name),
                              if (selectedType?.id == type.id)
                                const Icon(Icons.check,
                                    size: 16, color: Colors.blueAccent),
                            ],
                          ),
                        )),
                  ];
                },
                child: Container(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.grey.shade300),
                    borderRadius: BorderRadius.circular(6),
                  ),
                  child: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Flexible(
                        child: Text(
                          selectedType?.name ?? 'All Types',
                          overflow: TextOverflow.ellipsis,
                          style: const TextStyle(fontSize: 14),
                        ),
                      ),
                      const SizedBox(width: 4),
                      const Icon(Icons.arrow_drop_down, size: 20),
                    ],
                  ),
                ),
              );
            }),
          ],
        ),

        const SizedBox(height: 8),
        _buildDurationSelector(),
      ],
    );
  }

  Widget _buildTitle() =>
      MyText.bodyMedium('Monthly Expense Overview', fontWeight: 700);

  Widget _buildSubtitle() =>
      MyText.bodySmall('Month-wise total expense', color: Colors.grey);

  Widget _buildDurationSelector() {
    return Row(
      children: _ChartConstants.durationLabels.entries
          .map((entry) => _DurationChip(
                label: entry.value,
                duration: entry.key,
                isSelected: selectedDuration == entry.key,
                onSelected: onDurationChanged,
              ))
          .toList(),
    );
  }
}

// =========================
// DURATION CHIP WIDGET
// =========================
class _DurationChip extends StatelessWidget {
  const _DurationChip({
    Key? key,
    required this.label,
    required this.duration,
    required this.isSelected,
    required this.onSelected,
  }) : super(key: key);

  final String label;
  final MonthlyExpenseDuration duration;
  final bool isSelected;
  final ValueChanged<MonthlyExpenseDuration> onSelected;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(right: 4),
      child: ChoiceChip(
        label: Text(label, style: const TextStyle(fontSize: 12)),
        padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 0),
        materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
        visualDensity: VisualDensity.compact,
        selected: isSelected,
        onSelected: (_) => onSelected(duration),
        selectedColor: Colors.blueAccent.withOpacity(0.15),
        backgroundColor: Colors.grey.shade200,
        labelStyle: TextStyle(
          color: isSelected ? Colors.blueAccent : Colors.black87,
          fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
        ),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(5),
          side: BorderSide(
            color: isSelected ? Colors.blueAccent : Colors.grey.shade300,
          ),
        ),
      ),
    );
  }
}

// =========================
// EMPTY DATA WIDGET
// =========================
class _EmptyDataWidget extends StatelessWidget {
  const _EmptyDataWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: _ChartConstants.noDataContainerHeight,
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(
              Icons.info_outline,
              color: Colors.grey.shade400,
              size: _ChartConstants.noDataIconSize,
            ),
            const SizedBox(height: 10),
            MyText.bodyMedium(
              'No monthly expense data available.',
              textAlign: TextAlign.center,
              color: Colors.grey.shade500,
            ),
          ],
        ),
      ),
    );
  }
}

// =========================
// CHART WIDGET
// =========================
class _MonthlyExpenseChart extends StatelessWidget {
  const _MonthlyExpenseChart({
    Key? key,
    required this.data,
    required this.getColor,
    required this.isMobile,
    required this.totalExpense,
  }) : super(key: key);

  final List<dynamic> data;
  final Color Function(int index) getColor;
  final bool isMobile;
  final double totalExpense;

  @override
  Widget build(BuildContext context) {
    return SfCartesianChart(
      tooltipBehavior: _buildTooltipBehavior(),
      primaryXAxis: _buildXAxis(),
      primaryYAxis: _buildYAxis(),
      series: <ColumnSeries>[_buildColumnSeries()],
    );
  }

  TooltipBehavior _buildTooltipBehavior() {
    return TooltipBehavior(
      enable: true,
      builder: _tooltipBuilder,
      animationDuration: _ChartConstants.tooltipAnimationDuration,
    );
  }

  Widget _tooltipBuilder(
    dynamic data,
    dynamic point,
    dynamic series,
    int pointIndex,
    int seriesIndex,
  ) {
    final value = data.total as double;
    final percentage = totalExpense > 0 ? (value / totalExpense * 100) : 0;

    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
      decoration: BoxDecoration(
        color: Colors.blueAccent,
        borderRadius: BorderRadius.circular(4),
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            '${data.monthName} ${data.year}',
            style: const TextStyle(
              color: Colors.white,
              fontWeight: FontWeight.w600,
            ),
          ),
          const SizedBox(height: 2),
          Text(
            Utils.formatCurrency(value),
            style: const TextStyle(
              color: Colors.white,
              fontWeight: FontWeight.w600,
            ),
          ),
          Text(
            '${percentage.toStringAsFixed(1)}%',
            style: const TextStyle(
              color: Colors.white70,
              fontWeight: FontWeight.w500,
              fontSize: 10,
            ),
          ),
        ],
      ),
    );
  }

  CategoryAxis _buildXAxis() {
    return CategoryAxis(
      labelRotation: _ChartConstants.labelRotation.toInt(),
      majorGridLines:
          const MajorGridLines(width: 0), // removes X-axis grid lines
    );
  }

  NumericAxis _buildYAxis() {
    return NumericAxis(
      numberFormat: NumberFormat.simpleCurrency(
        locale: 'en_IN',
        name: '₹',
        decimalDigits: 0,
      ),
      axisLabelFormatter: (AxisLabelRenderDetails args) {
        return ChartAxisLabel(Utils.formatCurrency(args.value), null);
      },
      majorGridLines:
          const MajorGridLines(width: 0), // removes Y-axis grid lines
    );
  }

  ColumnSeries<dynamic, String> _buildColumnSeries() {
    return ColumnSeries<dynamic, String>(
      dataSource: data,
      xValueMapper: (d, _) => _ChartFormatter.formatMonthYear(d),
      yValueMapper: (d, _) => d.total,
      pointColorMapper: (_, index) => getColor(index),
      name: 'Monthly Expense',
      borderRadius: BorderRadius.circular(4),
      dataLabelSettings: _buildDataLabelSettings(),
    );
  }

  DataLabelSettings _buildDataLabelSettings() {
    return DataLabelSettings(
      isVisible: true,
      builder: (data, _, __, ___, ____) => Text(
        Utils.formatCurrency(data.total),
        style: const TextStyle(fontSize: 11),
      ),
    );
  }
}

// =========================
// FORMATTER HELPER
// =========================
class _ChartFormatter {
  static String formatMonthYear(dynamic data) {
    try {
      final month = data.month ?? 1;
      final year = data.year ?? DateTime.now().year;
      final date = DateTime(year, month, 1);
      final monthName = DateFormat('MMM').format(date);
      final shortYear = year % 100;
      return '$shortYear $monthName';
    } catch (e) {
      return '${data.monthName} ${data.year}';
    }
  }
}
