import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:on_field_work/helpers/widgets/my_spacing.dart';
import 'package:on_field_work/helpers/widgets/my_text.dart';
import 'package:on_field_work/helpers/theme/app_theme.dart';
import 'package:on_field_work/controller/employee/employees_screen_controller.dart';
import 'package:on_field_work/model/employees/employee_model.dart';
import 'package:on_field_work/helpers/utils/base_bottom_sheet.dart';
import 'package:on_field_work/helpers/services/api_service.dart';
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';

class ManageReportingBottomSheet extends StatefulWidget {
  final EmployeeModel? initialEmployee;
  final bool hideMainSelector;
  final bool renderAsCard;
  final bool hideLoggedUserFromSelection;
  final String? loggedUserId;

  const ManageReportingBottomSheet({
    super.key,
    this.initialEmployee,
    this.hideMainSelector = false,
    this.renderAsCard = false,
    this.hideLoggedUserFromSelection = false,
    this.loggedUserId,
  });

  @override
  State<ManageReportingBottomSheet> createState() =>
      _ManageReportingBottomSheetState();
}

class _ManageReportingBottomSheetState
    extends State<ManageReportingBottomSheet> {
  final EmployeesScreenController _employeeController = Get.find();
  final TextEditingController _primaryController = TextEditingController();
  final TextEditingController _secondaryController = TextEditingController();

  final RxList<EmployeeModel> _filteredPrimary = <EmployeeModel>[].obs;
  final RxList<EmployeeModel> _filteredSecondary = <EmployeeModel>[].obs;
  final RxList<EmployeeModel> _selectedPrimary = <EmployeeModel>[].obs;
  final RxList<EmployeeModel> _selectedSecondary = <EmployeeModel>[].obs;

  final TextEditingController _selectEmployeeController =
      TextEditingController();
  final RxList<EmployeeModel> _filteredEmployees = <EmployeeModel>[].obs;
  EmployeeModel? _selectedEmployee;

  bool _isSubmitting = false;

  @override
  void initState() {
    super.initState();
    _primaryController
        .addListener(() => _filterEmployees(_primaryController.text, true));
    _secondaryController
        .addListener(() => _filterEmployees(_secondaryController.text, false));
    _selectEmployeeController
        .addListener(() => _filterMainEmployee(_selectEmployeeController.text));

    // if the parent passed an initialEmployee (profile page), preselect & load hierarchy
    if (widget.initialEmployee != null) {
      // delay to let widget finish first build
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _onMainEmployeeSelected(widget.initialEmployee!);
      });
    }
  }

  @override
  void dispose() {
    _primaryController.dispose();
    _secondaryController.dispose();
    _selectEmployeeController.dispose();
    super.dispose();
  }

  void _filterMainEmployee(String query) {
    final employees = _employeeController.employees;
    final searchQuery = query.toLowerCase();

    final filtered = query.isEmpty
        ? <EmployeeModel>[]
        : employees
            .where((e) => e.name.toLowerCase().contains(searchQuery))
            .take(6)
            .toList();

    _filteredEmployees.assignAll(filtered);
  }

  void _filterEmployees(String query, bool isPrimary) {
    final employees = _employeeController.employees;
    final searchQuery = query.toLowerCase();

    final filtered = query.isEmpty
        ? <EmployeeModel>[]
        : employees
            .where((e) => e.name.toLowerCase().contains(searchQuery))
            .take(6)
            .toList();

    if (isPrimary) {
      _filteredPrimary.assignAll(filtered);
    } else {
      _filteredSecondary.assignAll(filtered);
    }
  }

  void _toggleSelection(EmployeeModel emp, bool isPrimary) {
    final list = isPrimary ? _selectedPrimary : _selectedSecondary;

    if (isPrimary) {
      //Allow only one primary employee at a time
      list.clear();
      list.add(emp);
    } else {
      // ✅ Secondary employees can still have multiple selections
      if (list.any((e) => e.id == emp.id)) {
        list.removeWhere((e) => e.id == emp.id);
      } else {
        list.add(emp);
      }
    }
  }

  /// helper to find employee by id from controller list (returns nullable)
  EmployeeModel? _findEmployeeById(String id) {
    for (final e in _employeeController.employees) {
      if (e.id == id) return e;
    }
    return null;
  }

  /// Called when user taps an employee from dropdown to manage reporting for.
  /// It sets selected employee and fetches existing hierarchy to preselect reporters.
  Future<void> _onMainEmployeeSelected(EmployeeModel emp) async {
    setState(() {
      _selectedEmployee = emp;
      _selectEmployeeController.text = emp.name;
      _filteredEmployees.clear();
    });

    // Clear previous selections
    _selectedPrimary.clear();
    _selectedSecondary.clear();

    // Fetch existing reporting hierarchy for this employee
    try {
      final data = await ApiService.getOrganizationHierarchyList(emp.id);
      if (data == null || data.isEmpty) return;

      for (final item in data) {
        try {
          final isPrimary = item['isPrimary'] == true;
          final reportTo = item['reportTo'];
          if (reportTo == null) continue;
          final reportToId = reportTo['id'] as String?;
          if (reportToId == null) continue;

          final match = _findEmployeeById(reportToId);
          if (match == null) continue;

          // ✅ Skip the employee whose profile is open
          if (widget.initialEmployee != null &&
              match.id == widget.initialEmployee!.id) {
            continue;
          }

          if (isPrimary) {
            if (!_selectedPrimary.any((e) => e.id == match.id)) {
              _selectedPrimary.add(match);
            }
          } else {
            if (!_selectedSecondary.any((e) => e.id == match.id)) {
              _selectedSecondary.add(match);
            }
          }
        } catch (_) {
          // ignore malformed items
        }
      }
    } catch (e) {
      // Fetch failure - show a subtle snackbar
      showAppSnackbar(
          title: 'Error',
          message: 'Failed to load existing reporting.',
          type: SnackbarType.error);
    }
  }

  void _resetForm() {
    setState(() {
      _selectedEmployee = null;
      _selectEmployeeController.clear();
      _selectedPrimary.clear();
      _selectedSecondary.clear();
      _filteredEmployees.clear();
      _filteredPrimary.clear();
      _filteredSecondary.clear();
    });
  }

  void _resetReportersOnly() {
    _selectedPrimary.clear();
    _selectedSecondary.clear();
    _primaryController.clear();
    _secondaryController.clear();
    _filteredPrimary.clear();
    _filteredSecondary.clear();
  }

  Future<void> _handleSubmit() async {
    if (_selectedEmployee == null) {
      showAppSnackbar(
        title: 'Error',
        message: 'Please select the employee.',
        type: SnackbarType.error,
      );
      return;
    }

    if (_selectedPrimary.isEmpty) {
      showAppSnackbar(
        title: 'Error',
        message: 'Please select at least one primary employee.',
        type: SnackbarType.error,
      );
      return;
    }

    final employeeId = _selectedEmployee!.id;

    // === BUILD PAYLOAD (updated logic) ===

    // fetch current assignments so we can deactivate old ones
    List<dynamic>? currentAssignments;
    try {
      currentAssignments =
          await ApiService.getOrganizationHierarchyList(employeeId);
    } catch (_) {
      currentAssignments = null;
    }

    // helper sets of newly selected ids
    final newPrimaryIds = _selectedPrimary.map((e) => e.id).toSet();
    final newSecondaryIds = _selectedSecondary.map((e) => e.id).toSet();

    final List<Map<String, dynamic>> payload = [];

    // 1) For current active assignments: if they are not in new selections -> add isActive:false
    if (currentAssignments != null && currentAssignments.isNotEmpty) {
      for (final item in currentAssignments) {
        try {
          final reportTo = item['reportTo'];
          if (reportTo == null) continue;
          final reportToId = reportTo['id'] as String?;
          if (reportToId == null) continue;
          final isPrimary = item['isPrimary'] == true;
          final currentlyActive =
              item['isActive'] == true || item['isActive'] == null; // be safe

          // if currently active and not included in new selection -> mark false
          if (currentlyActive) {
            if (isPrimary && !newPrimaryIds.contains(reportToId)) {
              payload.add({
                "reportToId": reportToId,
                "isPrimary": true,
                "isActive": false,
              });
            } else if (!isPrimary && !newSecondaryIds.contains(reportToId)) {
              payload.add({
                "reportToId": reportToId,
                "isPrimary": false,
                "isActive": false,
              });
            }
          }
        } catch (_) {
          // ignore malformed items (same behavior as before)
        }
      }
    }

    // 2) Add new primary (active)
    for (final emp in _selectedPrimary) {
      payload.add({
        "reportToId": emp.id,
        "isPrimary": true,
        "isActive": true,
      });
    }

    // 3) Add new secondary (active)
    for (final emp in _selectedSecondary) {
      payload.add({
        "reportToId": emp.id,
        "isPrimary": false,
        "isActive": true,
      });
    }

    setState(() => _isSubmitting = true);

    // show loader
    Get.dialog(
      const Center(child: CircularProgressIndicator()),
      barrierDismissible: false,
    );

    final success = await ApiService.manageOrganizationHierarchy(
      employeeId: employeeId,
      payload: payload,
    );

    // hide loader
    if (Get.isDialogOpen == true) Get.back();
    setState(() => _isSubmitting = false);

    if (success) {
      showAppSnackbar(
        title: 'Success',
        message: 'Reporting assigned successfully',
        type: SnackbarType.success,
      );

      // ✅ Refresh both the organization hierarchy and employee details so UI shows updated managers
      try {
        final empId = employeeId;
        final EmployeesScreenController controller = Get.find();
        await controller.fetchReportingManagers(empId);
        await controller.fetchEmployeeDetails(empId);
      } catch (_) {}

      // Optional: re-fetch the organization hierarchy list (if needed elsewhere)
      await ApiService.getOrganizationHierarchyList(employeeId);

      _resetForm();
      if (Navigator.of(context).canPop()) {
        Navigator.of(context).pop();
      }
    } else {
      showAppSnackbar(
        title: 'Error',
        message: 'Failed to assign reporting. Please try again.',
        type: SnackbarType.error,
      );
    }
  }

  void _handleCancel() => Navigator.pop(context);

  @override
  Widget build(BuildContext context) {
    // build the same child column content you already had, but assign to a variable
    final Widget content = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // conditional: show search section or simple header
        if (widget.hideMainSelector)
          _buildMainEmployeeHeader()
        else
          _buildMainEmployeeSection(),

        MySpacing.height(20),

        // Primary Employees section
        _buildSearchSection(
          label: "Primary Reporting Manager*",
          controller: _primaryController,
          filteredList: _filteredPrimary,
          selectedList: _selectedPrimary,
          isPrimary: true,
        ),

        MySpacing.height(20),

        // Secondary Employees section
        _buildSearchSection(
          label: "Secondary Reporting Manager",
          controller: _secondaryController,
          filteredList: _filteredSecondary,
          selectedList: _selectedSecondary,
          isPrimary: false,
        ),
      ],
    );

    // 🔥 WRAP EVERYTHING IN SAFEAREA + SCROLL + BOTTOM PADDING
    final safeWrappedContent = SafeArea(
      child: SingleChildScrollView(
        padding: EdgeInsets.only(
          bottom: MediaQuery.of(context).viewPadding.bottom + 20, 
          left: 16, right: 16, top: 8,
        ),
        child: content,
      ),
    );

    if (widget.renderAsCard) {
      // Inline card for profile screen
      return Card(
        margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 0),
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
        elevation: 2,
        child: Padding(
          padding: const EdgeInsets.all(12),
          child: safeWrappedContent,
        ),
      );
    }

    // default: existing bottom sheet usage
    return BaseBottomSheet(
      title: "Manage Reporting",
      submitText: "Submit",
      isSubmitting: _isSubmitting,
      onCancel: _handleCancel,
      onSubmit: _handleSubmit,
      child: safeWrappedContent, 
    );
  }

  Widget _buildMainEmployeeHeader() {
    // show selected employee name non-editable (chip-style)
    final emp = _selectedEmployee;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        MyText.bodyMedium("Selected Employee", fontWeight: 600),
        MySpacing.height(8),
        if (emp != null)
          Padding(
            padding: const EdgeInsets.only(top: 8),
            child: Chip(
              label: Text(emp.name, style: const TextStyle(fontSize: 12)),
              backgroundColor: Colors.indigo.shade50,
              labelStyle: TextStyle(color: AppTheme.primaryColor),
              deleteIcon: const Icon(Icons.close, size: 16),
            ),
          )
        else
          const Text('No employee selected',
              style: TextStyle(color: Colors.grey)),
      ],
    );
  }

  Widget _buildSearchSection({
    required String label,
    required TextEditingController controller,
    required RxList<EmployeeModel> filteredList,
    required RxList<EmployeeModel> selectedList,
    required bool isPrimary,
  }) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        MyText.bodyMedium(label, fontWeight: 600),
        MySpacing.height(8),

        // Search field
        TextField(
          controller: controller,
          decoration: InputDecoration(
            hintText: "Type to search employees...",
            isDense: true,
            filled: true,
            fillColor: Colors.grey[50],
            prefixIcon: const Icon(Icons.search, size: 18, color: Colors.grey),
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(6),
              borderSide: BorderSide(color: Colors.grey.shade300),
            ),
          ),
        ),

        // Dropdown suggestions
        Obx(() {
          if (filteredList.isEmpty) return const SizedBox.shrink();
          return Container(
            margin: const EdgeInsets.only(top: 4),
            decoration: BoxDecoration(
              color: Colors.white,
              border: Border.all(color: Colors.grey.shade300),
              borderRadius: BorderRadius.circular(6),
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withOpacity(0.05),
                  blurRadius: 4,
                  offset: const Offset(0, 2),
                )
              ],
            ),
            child: ListView.builder(
              itemCount: filteredList.length,
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              itemBuilder: (_, index) {
                final emp = filteredList[index];
                final isSelected = selectedList.any((e) => e.id == emp.id);
                return ListTile(
                  dense: true,
                  leading: CircleAvatar(
                    radius: 14,
                    backgroundColor: AppTheme.primaryColor.withOpacity(0.1),
                    child: MyText.labelSmall(
                      emp.name.isNotEmpty ? emp.name[0].toUpperCase() : "?",
                      fontWeight: 600,
                      color: AppTheme.primaryColor,
                    ),
                  ),
                  title: Text(emp.name, style: const TextStyle(fontSize: 13)),
                  trailing: Icon(
                    isSelected
                        ? Icons.check_circle
                        : Icons.radio_button_unchecked,
                    color: isSelected ? AppTheme.primaryColor : Colors.grey,
                    size: 18,
                  ),
                  onTap: () {
                    _toggleSelection(emp, isPrimary);
                    filteredList.clear();
                    controller.clear();
                  },
                );
              },
            ),
          );
        }),

        MySpacing.height(10),

        // Selected employees as chips
        Obx(() {
          if (selectedList.isEmpty) return const SizedBox.shrink();
          return Wrap(
            spacing: 6,
            runSpacing: 6,
            children: selectedList.map((emp) {
              final isProfileEmployee = widget.initialEmployee != null &&
                  emp.id == widget.initialEmployee!.id;

              return Chip(
                label: Text(emp.name, style: const TextStyle(fontSize: 12)),
                backgroundColor: isProfileEmployee
                    ? Colors.indigo.shade50
                    : Colors.indigo.shade50,
                labelStyle: TextStyle(color: AppTheme.primaryColor),
                // Only show delete icon / action for non-profile employees
                deleteIcon: isProfileEmployee
                    ? null
                    : const Icon(Icons.close, size: 16),
                onDeleted:
                    isProfileEmployee ? null : () => selectedList.remove(emp),
              );
            }).toList(),
          );
        }),
      ],
    );
  }

  Widget _buildMainEmployeeSection() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        MyText.bodyMedium("Select Employee *", fontWeight: 600),
        MySpacing.height(8),
        TextField(
          controller: _selectEmployeeController,
          decoration: InputDecoration(
            hintText: "Type to search employee...",
            isDense: true,
            filled: true,
            fillColor: Colors.grey[50],
            prefixIcon: const Icon(Icons.search, size: 18, color: Colors.grey),
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(6),
              borderSide: BorderSide(color: Colors.grey.shade300),
            ),
          ),
        ),
        Obx(() {
          if (_filteredEmployees.isEmpty) return const SizedBox.shrink();
          return Container(
            margin: const EdgeInsets.only(top: 4),
            decoration: BoxDecoration(
              color: Colors.white,
              border: Border.all(color: Colors.grey.shade300),
              borderRadius: BorderRadius.circular(6),
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withOpacity(0.05),
                  blurRadius: 4,
                  offset: const Offset(0, 2),
                )
              ],
            ),
            child: ListView.builder(
              itemCount: _filteredEmployees.length,
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              itemBuilder: (_, index) {
                final emp = _filteredEmployees[index];
                return ListTile(
                  dense: true,
                  leading: CircleAvatar(
                    radius: 14,
                    backgroundColor: AppTheme.primaryColor.withOpacity(0.1),
                    child: MyText.labelSmall(
                      emp.name.isNotEmpty ? emp.name[0].toUpperCase() : "?",
                      fontWeight: 600,
                      color: AppTheme.primaryColor,
                    ),
                  ),
                  title: Text(emp.name, style: const TextStyle(fontSize: 13)),
                  onTap: () => _onMainEmployeeSelected(emp),
                );
              },
            ),
          );
        }),
        if (_selectedEmployee != null)
          Padding(
            padding: const EdgeInsets.only(top: 8),
            child: Chip(
              label: Text(_selectedEmployee!.name,
                  style: const TextStyle(fontSize: 12)),
              backgroundColor: Colors.indigo.shade50,
              labelStyle: TextStyle(color: AppTheme.primaryColor),
              deleteIcon: const Icon(Icons.close, size: 16),
              onDeleted: () => setState(() {
                _selectedEmployee = null;
                _selectEmployeeController.clear();
                // clear selected reporters too, since employee changed
                _resetReportersOnly();
              }),
            ),
          ),
      ],
    );
  }
}
