import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intl/intl.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';

class AttendanceDashboardChart extends StatelessWidget {
  AttendanceDashboardChart({Key? key}) : super(key: key);

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

  static const List<Color> _flatColors = [
    Color(0xFFE57373), // Red 300
    Color(0xFF64B5F6), // Blue 300
    Color(0xFF81C784), // Green 300
    Color(0xFFFFB74D), // Orange 300
    Color(0xFFBA68C8), // Purple 300
    Color(0xFFFF8A65), // Deep Orange 300
    Color(0xFF4DB6AC), // Teal 300
    Color(0xFFA1887F), // Brown 400
    Color(0xFFDCE775), // Lime 300
    Color(0xFF9575CD), // Deep Purple 300
    Color(0xFF7986CB), // Indigo 300
    Color(0xFFAED581), // Light Green 300
    Color(0xFFFF7043), // Deep Orange 400
    Color(0xFF4FC3F7), // Light Blue 300
    Color(0xFFFFD54F), // Amber 300
    Color(0xFF90A4AE), // Blue Grey 300
    Color(0xFFE573BB), // Pink 300
    Color(0xFF81D4FA), // Light Blue 200
    Color(0xFFBCAAA4), // Brown 300
    Color(0xFFA5D6A7), // Green 300
    Color(0xFFCE93D8), // Purple 200
    Color(0xFFFF8A65), // Deep Orange 300 (repeat to fill)
    Color(0xFF80CBC4), // Teal 200
    Color(0xFFFFF176), // Yellow 300
    Color(0xFF90CAF9), // Blue 200
    Color(0xFFE0E0E0), // Grey 300
    Color(0xFFF48FB1), // Pink 200
    Color(0xFFA1887F), // Brown 400 (repeat)
    Color(0xFFB0BEC5), // Blue Grey 200
    Color(0xFF81C784), // Green 300 (repeat)
    Color(0xFFFFB74D), // Orange 300 (repeat)
    Color(0xFF64B5F6), // Blue 300 (repeat)
  ];

  Color _getRoleColor(String role) {
    final index = role.hashCode.abs() % _flatColors.length;
    return _flatColors[index];
  }

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

    return Obx(() {
      final isChartView = _controller.attendanceIsChartView.value;
      final selectedRange = _controller.attendanceSelectedRange.value;

      final filteredData = _getFilteredData();

      return Container(
        decoration: _containerDecoration,
        padding: EdgeInsets.symmetric(
          vertical: 16,
          horizontal: screenWidth < 600 ? 8 : 20,
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _Header(
              selectedRange: selectedRange,
              isChartView: isChartView,
              screenWidth: screenWidth,
              onToggleChanged: (isChart) =>
                  _controller.attendanceIsChartView.value = isChart,
              onRangeChanged: _controller.updateAttendanceRange,
            ),
            const SizedBox(height: 12),
            Expanded(
              child: filteredData.isEmpty
                  ? _NoDataMessage()
                  : isChartView
                      ? _AttendanceChart(
                          data: filteredData, getRoleColor: _getRoleColor)
                      : _AttendanceTable(
                          data: filteredData,
                          getRoleColor: _getRoleColor,
                          screenWidth: screenWidth),
            ),
          ],
        ),
      );
    });
  }

  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),
          ),
        ],
      );

  List<Map<String, dynamic>> _getFilteredData() {
    final now = DateTime.now();
    final daysBack = _controller.getAttendanceDays();
    return _controller.roleWiseData.where((entry) {
      final date = DateTime.parse(entry['date'] as String);
      return date.isAfter(now.subtract(Duration(days: daysBack))) &&
          !date.isAfter(now);
    }).toList();
  }
}

// Header
class _Header extends StatelessWidget {
  const _Header({
    Key? key,
    required this.selectedRange,
    required this.isChartView,
    required this.screenWidth,
    required this.onToggleChanged,
    required this.onRangeChanged,
  }) : super(key: key);

  final String selectedRange;
  final bool isChartView;
  final double screenWidth;
  final ValueChanged<bool> onToggleChanged;
  final ValueChanged<String> onRangeChanged;

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          children: [
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  MyText.bodyMedium('Attendance Overview', fontWeight: 700),
                  const SizedBox(height: 2),
                  MyText.bodySmall('Role-wise present count',
                      color: Colors.grey),
                ],
              ),
            ),
            ToggleButtons(
              borderRadius: BorderRadius.circular(5),
              borderColor: Colors.grey,
              fillColor: Colors.blueAccent.withOpacity(0.15),
              selectedBorderColor: Colors.blueAccent,
              selectedColor: Colors.blueAccent,
              color: Colors.grey,
              constraints: BoxConstraints(
                minHeight: 30,
                minWidth: screenWidth < 400 ? 28 : 36,
              ),
              isSelected: [isChartView, !isChartView],
              onPressed: (index) => onToggleChanged(index == 0),
              children: const [
                Icon(Icons.bar_chart_rounded, size: 15),
                Icon(Icons.table_chart, size: 15),
              ],
            ),
          ],
        ),
        const SizedBox(height: 8),
        Row(
          children: ["7D", "15D", "30D"]
              .map(
                (label) => 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: selectedRange == label,
                    onSelected: (_) => onRangeChanged(label),
                    selectedColor: Colors.blueAccent.withOpacity(0.15),
                    backgroundColor: Colors.grey.shade200,
                    labelStyle: TextStyle(
                      color: selectedRange == label
                          ? Colors.blueAccent
                          : Colors.black87,
                      fontWeight: selectedRange == label
                          ? FontWeight.w600
                          : FontWeight.normal,
                    ),
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(5),
                      side: BorderSide(
                        color: selectedRange == label
                            ? Colors.blueAccent
                            : Colors.grey.shade300,
                      ),
                    ),
                  ),
                ),
              )
              .toList(),
        ),
      ],
    );
  }
}

// No Data
class _NoDataMessage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 180,
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(Icons.info_outline, color: Colors.grey.shade400, size: 48),
            const SizedBox(height: 10),
            MyText.bodyMedium(
              'No attendance data available for this range.',
              textAlign: TextAlign.center,
              color: Colors.grey.shade500,
            ),
          ],
        ),
      ),
    );
  }
}

// Chart
class _AttendanceChart extends StatelessWidget {
  const _AttendanceChart({
    Key? key,
    required this.data,
    required this.getRoleColor,
  }) : super(key: key);

  final List<Map<String, dynamic>> data;
  final Color Function(String role) getRoleColor;

  @override
  Widget build(BuildContext context) {
    final dateFormat = DateFormat('d MMM');
    final uniqueDates = data
        .map((e) => DateTime.parse(e['date'] as String))
        .toSet()
        .toList()
      ..sort();
    final filteredDates = uniqueDates.map(dateFormat.format).toList();

    final filteredRoles = data.map((e) => e['role'] as String).toSet().toList();

    final allZero = filteredRoles.every((role) {
      return data
          .where((entry) => entry['role'] == role)
          .every((entry) => (entry['present'] ?? 0) == 0);
    });

    if (allZero) {
      return Container(
        height: 600,
        child: const Center(
          child: Text(
            'No attendance data for the selected range.',
            textAlign: TextAlign.center,
            style: TextStyle(fontSize: 14, color: Colors.grey),
          ),
        ),
      );
    }

    final formattedMap = {
      for (var e in data)
        '${e['role']}_${dateFormat.format(DateTime.parse(e['date'] as String))}':
            e['present'],
    };

    final rolesWithData = filteredRoles.where((role) {
      return data
          .any((entry) => entry['role'] == role && (entry['present'] ?? 0) > 0);
    }).toList();

    return Container(
      height: 600,
      padding: const EdgeInsets.all(6),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(5),
      ),
      child: SfCartesianChart(
        tooltipBehavior: TooltipBehavior(enable: true, shared: true),
        legend: Legend(isVisible: true, position: LegendPosition.bottom),
        primaryXAxis: CategoryAxis(
          labelRotation: 45,
          majorGridLines:
              const MajorGridLines(width: 0), // removes vertical grid lines
        ),
        primaryYAxis: NumericAxis(
          minimum: 0,
          interval: 1,
          majorGridLines:
              const MajorGridLines(width: 0), // removes horizontal grid lines
        ),
        series: rolesWithData.map((role) {
          final seriesData = filteredDates
              .map((date) {
                final key = '${role}_$date';
                return {'date': date, 'present': formattedMap[key] ?? 0};
              })
              .where((d) => (d['present'] ?? 0) > 0)
              .toList();

          return StackedColumnSeries<Map<String, dynamic>, String>(
            dataSource: seriesData,
            xValueMapper: (d, _) => d['date'],
            yValueMapper: (d, _) => d['present'],
            name: role,
            color: getRoleColor(role),
            dataLabelSettings: DataLabelSettings(
              isVisible: true,
              builder: (dynamic data, _, __, ___, ____) {
                return (data['present'] ?? 0) > 0
                    ? Text(
                        NumberFormat.decimalPattern().format(data['present']),
                        style: const TextStyle(fontSize: 11),
                      )
                    : const SizedBox.shrink();
              },
            ),
          );
        }).toList(),
      ),
    );
  }
}

// Table
class _AttendanceTable extends StatelessWidget {
  const _AttendanceTable({
    Key? key,
    required this.data,
    required this.getRoleColor,
    required this.screenWidth,
  }) : super(key: key);

  final List<Map<String, dynamic>> data;
  final Color Function(String role) getRoleColor;
  final double screenWidth;

  @override
  Widget build(BuildContext context) {
    final dateFormat = DateFormat('d MMM');
    final uniqueDates = data
        .map((e) => DateTime.parse(e['date'] as String))
        .toSet()
        .toList()
      ..sort();
    final filteredDates = uniqueDates.map(dateFormat.format).toList();

    final filteredRoles = data.map((e) => e['role'] as String).toSet().toList();

    final allZero = filteredRoles.every((role) {
      return data
          .where((entry) => entry['role'] == role)
          .every((entry) => (entry['present'] ?? 0) == 0);
    });

    if (allZero) {
      return Container(
        height: 300,
        child: const Center(
          child: Text(
            'No attendance data for the selected range.',
            textAlign: TextAlign.center,
            style: TextStyle(fontSize: 14, color: Colors.grey),
          ),
        ),
      );
    }

    final formattedMap = {
      for (var e in data)
        '${e['role']}_${dateFormat.format(DateTime.parse(e['date'] as String))}':
            e['present'],
    };

    return Container(
      height: 300,
      decoration: BoxDecoration(
        border: Border.all(color: Colors.grey.shade300),
        borderRadius: BorderRadius.circular(5),
      ),
      child: Scrollbar(
        thumbVisibility: true,
        trackVisibility: true,
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: ConstrainedBox(
            constraints:
                BoxConstraints(minWidth: MediaQuery.of(context).size.width),
            child: SingleChildScrollView(
              scrollDirection: Axis.vertical,
              child: DataTable(
                columnSpacing: 20,
                headingRowHeight: 44,
                headingRowColor: MaterialStateProperty.all(
                    Colors.blueAccent.withOpacity(0.08)),
                headingTextStyle: const TextStyle(
                    fontWeight: FontWeight.bold, color: Colors.black87),
                columns: [
                  const DataColumn(label: Text('Role')),
                  ...filteredDates
                      .map((d) => DataColumn(label: Center(child: Text(d)))),
                ],
                rows: filteredRoles.map((role) {
                  return DataRow(
                    cells: [
                      DataCell(
                          _RolePill(role: role, color: getRoleColor(role))),
                      ...filteredDates.map((date) {
                        final key = '${role}_$date';
                        return DataCell(
                          Center(
                            child: Text(
                              NumberFormat.decimalPattern()
                                  .format(formattedMap[key] ?? 0),
                              textAlign: TextAlign.center,
                              style: const TextStyle(fontSize: 13),
                            ),
                          ),
                        );
                      }),
                    ],
                  );
                }).toList(),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class _RolePill extends StatelessWidget {
  const _RolePill({Key? key, required this.role, required this.color})
      : super(key: key);

  final String role;
  final Color color;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      decoration: BoxDecoration(
        color: color.withOpacity(0.15),
        borderRadius: BorderRadius.circular(5),
      ),
      child: MyText.labelSmall(role, fontWeight: 500),
    );
  }
}
