import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:marco/controller/expense/expense_screen_controller.dart';
import 'package:marco/helpers/utils/base_bottom_sheet.dart';
import 'package:marco/helpers/utils/date_time_utils.dart';
import 'package:marco/helpers/widgets/my_spacing.dart';
import 'package:marco/helpers/widgets/my_text.dart';
import 'package:marco/helpers/widgets/my_text_style.dart';
import 'package:marco/model/employee_model.dart';

class ExpenseFilterBottomSheet extends StatelessWidget {
  final ExpenseController expenseController;
  final ScrollController scrollController;

  const ExpenseFilterBottomSheet({
    super.key,
    required this.expenseController,
    required this.scrollController,
  });

  @override
  Widget build(BuildContext context) {
    // Obx rebuilds the widget when observable values from the controller change.
    return Obx(() {
      return BaseBottomSheet(
        title: 'Filter Expenses',
        onCancel: () => Get.back(),
        onSubmit: () {
          expenseController.fetchExpenses();
          Get.back();
        },
        submitText: 'Submit',
        submitColor: Colors.indigo,
        submitIcon: Icons.check_circle_outline,
        child: SingleChildScrollView(
          controller: scrollController,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Align(
                alignment: Alignment.centerRight,
                child: TextButton(
                  onPressed: () => expenseController.clearFilters(),
                  child: const Text(
                    "Reset Filter",
                    style: TextStyle(
                      color: Colors.red,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                ),
              ),
              MySpacing.height(8),
              _buildProjectFilter(context),
              MySpacing.height(16),
              _buildStatusFilter(context),
              MySpacing.height(16),
              _buildDateRangeFilter(context),
              MySpacing.height(16),
              _buildPaidByFilter(),
              MySpacing.height(16),
              _buildCreatedByFilter(),
            ],
          ),
        ),
      );
    });
  }

  /// Builds a generic field layout with a label and a child widget.
  Widget _buildField(String label, Widget child) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        MyText.labelMedium(label),
        MySpacing.height(8),
        child,
      ],
    );
  }

  /// Extracted widget builder for the Project filter.
  Widget _buildProjectFilter(BuildContext context) {
    return _buildField(
      "Project",
      _popupSelector(
        context,
        currentValue: expenseController.selectedProject.value.isEmpty
            ? 'Select Project'
            : expenseController.selectedProject.value,
        items: expenseController.globalProjects,
        onSelected: (value) => expenseController.selectedProject.value = value,
      ),
    );
  }

  /// Extracted widget builder for the Expense Status filter.
  Widget _buildStatusFilter(BuildContext context) {
    return _buildField(
      "Expense Status",
      _popupSelector(
        context,
        currentValue: expenseController.selectedStatus.value.isEmpty
            ? 'Select Expense Status'
            : expenseController.expenseStatuses
                    .firstWhereOrNull(
                        (e) => e.id == expenseController.selectedStatus.value)
                    ?.name ??
                'Select Expense Status',
        items: expenseController.expenseStatuses.map((e) => e.name).toList(),
        onSelected: (name) {
          final status = expenseController.expenseStatuses
              .firstWhere((e) => e.name == name);
          expenseController.selectedStatus.value = status.id;
        },
      ),
    );
  }

  /// Extracted widget builder for the Date Range filter.
  Widget _buildDateRangeFilter(BuildContext context) {
  return _buildField(
    "Date Filter",
    Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Obx(() {
          return SegmentedButton<String>(
            segments: expenseController.dateTypes
                .map(
                  (type) => ButtonSegment(
                    value: type,
                    label: Text(
                      type,
                      style: MyTextStyle.bodySmall(
                        fontWeight: 600,
                        fontSize: 13,
                        height: 1.2,
                      ),
                    ),
                  ),
                )
                .toList(),
            selected: {expenseController.selectedDateType.value},
            onSelectionChanged: (newSelection) {
              if (newSelection.isNotEmpty) {
                expenseController.selectedDateType.value = newSelection.first;
              }
            },
            style: ButtonStyle(
              visualDensity: const VisualDensity(horizontal: -2, vertical: -2),
              padding: MaterialStateProperty.all(
                  const EdgeInsets.symmetric(horizontal: 8, vertical: 6)),
              backgroundColor: MaterialStateProperty.resolveWith(
                (states) => states.contains(MaterialState.selected)
                    ? Colors.indigo.shade100
                    : Colors.grey.shade100,
              ),
              foregroundColor: MaterialStateProperty.resolveWith(
                (states) => states.contains(MaterialState.selected)
                    ? Colors.indigo
                    : Colors.black87,
              ),
              shape: MaterialStateProperty.all(
                RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(8),
                ),
              ),
              side: MaterialStateProperty.resolveWith(
                (states) => BorderSide(
                  color: states.contains(MaterialState.selected)
                      ? Colors.indigo
                      : Colors.grey.shade300,
                  width: 1,
                ),
              ),
            ),
          );
        }),
        MySpacing.height(16),
        Row(
          children: [
            Expanded(
              child: _dateButton(
                label: expenseController.startDate.value == null
                    ? 'Start Date'
                    : DateTimeUtils.formatDate(
                        expenseController.startDate.value!, 'dd MMM yyyy'),
                onTap: () => _selectDate(
                  context,
                  expenseController.startDate,
                  lastDate: expenseController.endDate.value,
                ),
              ),
            ),
            MySpacing.width(12),
            Expanded(
              child: _dateButton(
                label: expenseController.endDate.value == null
                    ? 'End Date'
                    : DateTimeUtils.formatDate(
                        expenseController.endDate.value!, 'dd MMM yyyy'),
                onTap: () => _selectDate(
                  context,
                  expenseController.endDate,
                  firstDate: expenseController.startDate.value,
                ),
              ),
            ),
          ],
        ),
      ],
    ),
  );
}


  /// Extracted widget builder for the "Paid By" employee filter.
  Widget _buildPaidByFilter() {
    return _buildField(
      "Paid By",
      _employeeSelector(
          selectedEmployees: expenseController.selectedPaidByEmployees),
    );
  }

  /// Extracted widget builder for the "Created By" employee filter.
  Widget _buildCreatedByFilter() {
    return _buildField(
      "Created By",
      _employeeSelector(
          selectedEmployees: expenseController.selectedCreatedByEmployees),
    );
  }

  /// Helper method to show a date picker and update the state.
  Future<void> _selectDate(
    BuildContext context,
    Rx<DateTime?> dateNotifier, {
    DateTime? firstDate,
    DateTime? lastDate,
  }) async {
    final DateTime? picked = await showDatePicker(
      context: context,
      initialDate: dateNotifier.value ?? DateTime.now(),
      firstDate: firstDate ?? DateTime(2020),
      lastDate: lastDate ?? DateTime.now().add(const Duration(days: 365)),
    );
    if (picked != null && picked != dateNotifier.value) {
      dateNotifier.value = picked;
    }
  }

  /// Reusable popup selector widget.
  Widget _popupSelector(
    BuildContext context, {
    required String currentValue,
    required List<String> items,
    required ValueChanged<String> onSelected,
  }) {
    return PopupMenuButton<String>(
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
      onSelected: onSelected,
      itemBuilder: (context) => items
          .map((e) => PopupMenuItem<String>(
                value: e,
                child: Text(e),
              ))
          .toList(),
      child: Container(
        padding: MySpacing.all(12),
        decoration: BoxDecoration(
          color: Colors.grey.shade100,
          border: Border.all(color: Colors.grey.shade300),
          borderRadius: BorderRadius.circular(12),
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Expanded(
              child: Text(
                currentValue,
                style: const TextStyle(color: Colors.black87),
                overflow: TextOverflow.ellipsis,
              ),
            ),
            const Icon(Icons.arrow_drop_down, color: Colors.grey),
          ],
        ),
      ),
    );
  }

  /// Reusable date button widget.
  Widget _dateButton({required String label, required VoidCallback onTap}) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        padding: MySpacing.xy(16, 12),
        decoration: BoxDecoration(
          color: Colors.grey.shade100,
          borderRadius: BorderRadius.circular(12),
          border: Border.all(color: Colors.grey.shade300),
        ),
        child: Row(
          children: [
            const Icon(Icons.calendar_today, size: 16, color: Colors.grey),
            MySpacing.width(8),
            Expanded(
              child: Text(
                label,
                style: MyTextStyle.bodyMedium(),
                overflow: TextOverflow.ellipsis,
              ),
            ),
          ],
        ),
      ),
    );
  }

  /// Reusable employee selector with Autocomplete.
  Widget _employeeSelector({required RxList<EmployeeModel> selectedEmployees}) {
    final textController = TextEditingController();
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Obx(() {
          if (selectedEmployees.isEmpty) {
            return const SizedBox.shrink();
          }
          return Wrap(
            spacing: 8,
            runSpacing: 0,
            children: selectedEmployees
                .map((emp) => Chip(
                      label: Text(emp.name),
                      onDeleted: () => selectedEmployees.remove(emp),
                      deleteIcon: const Icon(Icons.close, size: 18),
                      backgroundColor: Colors.grey.shade200,
                      padding: const EdgeInsets.all(8),
                    ))
                .toList(),
          );
        }),
        MySpacing.height(8),
        Autocomplete<EmployeeModel>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            if (textEditingValue.text.isEmpty) {
              return const Iterable<EmployeeModel>.empty();
            }
            return expenseController.allEmployees.where((emp) {
              final isNotSelected = !selectedEmployees.contains(emp);
              final matchesQuery = emp.name
                  .toLowerCase()
                  .contains(textEditingValue.text.toLowerCase());
              return isNotSelected && matchesQuery;
            });
          },
          displayStringForOption: (EmployeeModel emp) => emp.name,
          onSelected: (EmployeeModel emp) {
            if (!selectedEmployees.contains(emp)) {
              selectedEmployees.add(emp);
            }
            textController.clear();
          },
          fieldViewBuilder: (context, controller, focusNode, onFieldSubmitted) {
            // Assign the local controller to the one from the builder
            // to allow clearing it on selection.
            WidgetsBinding.instance.addPostFrameCallback((_) {
              if (textController != controller) {
                // This is a workaround to sync controllers
              }
            });
            return TextField(
              controller: controller,
              focusNode: focusNode,
              decoration: _inputDecoration("Search Employee"),
              onSubmitted: (_) => onFieldSubmitted(),
            );
          },
          optionsViewBuilder: (context, onSelected, options) {
            return Align(
              alignment: Alignment.topLeft,
              child: Material(
                color: Colors.white,
                elevation: 4.0,
                child: ConstrainedBox(
                  constraints: const BoxConstraints(maxHeight: 200),
                  child: ListView.builder(
                    padding: EdgeInsets.zero,
                    itemCount: options.length,
                    itemBuilder: (context, index) {
                      final emp = options.elementAt(index);
                      return ListTile(
                        title: Text(emp.name),
                        onTap: () => onSelected(emp),
                      );
                    },
                  ),
                ),
              ),
            );
          },
        ),
      ],
    );
  }

  /// Centralized decoration for text fields.
  InputDecoration _inputDecoration(String hint) {
    return InputDecoration(
      hintText: hint,
      hintStyle: MyTextStyle.bodySmall(xMuted: true),
      filled: true,
      fillColor: Colors.grey.shade100,
      border: OutlineInputBorder(
        borderRadius: BorderRadius.circular(12),
        borderSide: BorderSide(color: Colors.grey.shade300),
      ),
      enabledBorder: OutlineInputBorder(
        borderRadius: BorderRadius.circular(12),
        borderSide: BorderSide(color: Colors.grey.shade300),
      ),
      focusedBorder: OutlineInputBorder(
        borderRadius: BorderRadius.circular(12),
        borderSide: const BorderSide(color: Colors.blueAccent, width: 1.5),
      ),
      contentPadding: MySpacing.all(12),
    );
  }
}
