import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:logger/logger.dart';
import 'package:sigap/src/features/daily-ops/data/models/models/patrol_units_model.dart';
import 'package:sigap/src/features/daily-ops/data/repositories/patrol_units_repository.dart';
import 'package:sigap/src/utils/popups/loaders.dart';
import 'package:sigap/src/utils/validators/validation.dart';

// Define enums for patrol unit type and selection mode
enum PatrolUnitTypeExtended { car, motorcycle, foot, drone, mixed }

enum PatrolUnitStatus { active, standby, maintenance, patrol, onDuty, offDuty }

enum PatrolSelectionMode { individual, group, createNew }

class PatrolUnitController extends GetxController {
  // Singleton instance
  static PatrolUnitController get instance => Get.find();

  // Data states
  final RxList<PatrolUnitModel> availablePatrolUnits = <PatrolUnitModel>[].obs;
  final RxBool isLoadingPatrolUnits = false.obs;
  final RxString selectedPatrolUnitName = ''.obs;
  final Rx<PatrolUnitTypeExtended> selectedPatrolType =
      PatrolUnitTypeExtended.car.obs;
  final Rx<PatrolSelectionMode> patrolSelectionMode =
      PatrolSelectionMode.individual.obs;

  // Controllers for selected patrol unit
  final patrolUnitIdController = TextEditingController();

  // Controllers for new patrol unit with enhanced fields
  final patrolNameController = TextEditingController();
  final patrolTypeController = TextEditingController(text: 'car');
  final patrolRadiusController = TextEditingController(text: '6500');
  final patrolStatusController = TextEditingController(text: 'active');
  final memberCountController = TextEditingController(text: '1');
  final categoryController = TextEditingController(text: 'individual');

  // Unit ID for current selection
  final unitIdController = TextEditingController();
  final RxString selectedUnitName = ''.obs;

  // Error states for patrol unit fields
  final RxString patrolUnitIdError = ''.obs;
  final RxString patrolNameError = ''.obs;
  final RxString patrolTypeError = ''.obs;
  final RxString patrolRadiusError = ''.obs;
  final RxString patrolStatusError = ''.obs;
  final RxString memberCountError = ''.obs;
  final RxString categoryError = ''.obs;

  // Logger instance
  final Logger logger = Logger();

  // Repository
  late final PatrolUnitRepository patrolUnitRepository;

  // Flag for creation mode
  final RxBool isCreatingNewPatrolUnit = false.obs;

  @override
  void onInit() {
    super.onInit();
    initRepository();
  }

  void initRepository() {
    patrolUnitRepository = Get.find<PatrolUnitRepository>();
    logger.i('PatrolUnitRepository initialized');
  }

  // Fetch patrol units by unit ID
  Future<void> getPatrolUnitsByUnitId(String unitId) async {
    try {
      isLoadingPatrolUnits.value = true;
      availablePatrolUnits.clear();

      final patrolUnits = await patrolUnitRepository.getPatrolUnitsByUnitId(
        unitId,
      );
      availablePatrolUnits.value = patrolUnits;

      logger.i(
        'Fetched ${patrolUnits.length} patrol units for unit ID: $unitId',
      );
      isLoadingPatrolUnits.value = false;
    } catch (error) {
      isLoadingPatrolUnits.value = false;
      TLoaders.errorSnackBar(
        title: 'Error',
        message:
            'Something went wrong while fetching patrol units. Please try again later.',
      );
      logger.e('Failed to fetch patrol units: $error');
    }
  }

  // Set patrol selection mode (individual, group, or create new)
  void setPatrolSelectionMode(PatrolSelectionMode mode) {
    patrolSelectionMode.value = mode;

    // Reset fields when changing modes
    if (mode == PatrolSelectionMode.createNew) {
      isCreatingNewPatrolUnit.value = true;
      patrolUnitIdController.clear();
      selectedPatrolUnitName.value = '';
    } else {
      isCreatingNewPatrolUnit.value = false;

      // Reset patrol unit selection when switching between individual and group
      patrolUnitIdController.clear();
      selectedPatrolUnitName.value = '';
    }

    update(['patrol_mode_tabs']);
  }

  // Set patrol unit type
  void setPatrolUnitType(PatrolUnitTypeExtended type) {
    selectedPatrolType.value = type;
    patrolTypeController.text = type.name;

    // Update the recommended radius based on type
    switch (type) {
      case PatrolUnitTypeExtended.car:
        patrolRadiusController.text = '6500';
        break;
      case PatrolUnitTypeExtended.motorcycle:
        patrolRadiusController.text = '4000';
        break;
      case PatrolUnitTypeExtended.foot:
        patrolRadiusController.text = '1000';
        break;
      case PatrolUnitTypeExtended.drone:
        patrolRadiusController.text = '3000';
        break;
      case PatrolUnitTypeExtended.mixed:
        patrolRadiusController.text = '4000';
        break;
    }

    update(['patrol_type_selector', 'patrol_radius_field', 'patrol_summary']);
  }

  // Join an existing patrol unit
  void joinPatrolUnit(PatrolUnitModel patrolUnit) {
    patrolUnitIdController.text = patrolUnit.id;
    selectedPatrolUnitName.value = patrolUnit.name;

    // Determine patrol type from the unit type
    if (patrolUnit.type.toLowerCase() == 'car') {
      selectedPatrolType.value = PatrolUnitTypeExtended.car;
    } else if (patrolUnit.type.toLowerCase() == 'motorcycle') {
      selectedPatrolType.value = PatrolUnitTypeExtended.motorcycle;
    } else if (patrolUnit.type.toLowerCase() == 'foot') {
      selectedPatrolType.value = PatrolUnitTypeExtended.foot;
    } else if (patrolUnit.type.toLowerCase() == 'drone') {
      selectedPatrolType.value = PatrolUnitTypeExtended.drone;
    } else {
      selectedPatrolType.value = PatrolUnitTypeExtended.mixed;
    }

    update(['patrol_selection']);
  }

  // Get available patrol units filtered by type AND category
  List<PatrolUnitModel> getFilteredPatrolUnits() {
    // Filter by vehicle type first
    var filteredByType =
        availablePatrolUnits
            .where(
              (unit) =>
                  unit.type.toLowerCase() ==
                  selectedPatrolType.value.name.toLowerCase(),
            )
            .toList();

    // Then filter by category based on selection mode
    if (patrolSelectionMode.value == PatrolSelectionMode.individual) {
      return filteredByType
          .where((unit) => unit.category?.toLowerCase() == 'individual')
          .toList();
    } else if (patrolSelectionMode.value == PatrolSelectionMode.group) {
      return filteredByType
          .where((unit) => unit.category?.toLowerCase() == 'group')
          .toList();
    }

    // Default to returning all units filtered by type if in create mode
    return filteredByType;
  }

  // Validate new patrol unit data with enhanced validation
  bool validateNewPatrolUnit() {
    bool isValid = true;

    // Clear previous errors
    clearErrors();

    // Validate patrol unit name
    final nameValidation = TValidators.validateUserInput(
      'Patrol Unit Name',
      patrolNameController.text,
      50,
    );
    if (nameValidation != null) {
      patrolNameError.value = nameValidation;
      isValid = false;
    }

    // Validate patrol unit type
    if (patrolTypeController.text.isEmpty) {
      patrolTypeError.value = 'Patrol type is required';
      isValid = false;
    }

    // Validate patrol status
    if (patrolStatusController.text.isEmpty) {
      patrolStatusError.value = 'Status is required';
      isValid = false;
    }

    // Validate member count
    if (memberCountController.text.isEmpty) {
      memberCountError.value = 'Member count is required';
      isValid = false;
    } else {
      try {
        final count = int.parse(memberCountController.text);
        if (count <= 0) {
          memberCountError.value = 'Must have at least 1 member';
          isValid = false;
        }
      } catch (e) {
        memberCountError.value = 'Invalid member count';
        isValid = false;
      }
    }

    // Validate category
    if (categoryController.text.isEmpty) {
      categoryError.value = 'Category is required';
      isValid = false;
    } else if (categoryController.text != 'individual' &&
        categoryController.text != 'group') {
      categoryError.value = 'Category must be either individual or group';
      isValid = false;
    }

    // Validate patrol radius
    if (patrolRadiusController.text.isEmpty) {
      patrolRadiusError.value = 'Patrol radius is required';
      isValid = false;
    } else {
      try {
        final radius = double.parse(patrolRadiusController.text);
        if (radius <= 0) {
          patrolRadiusError.value = 'Radius must be greater than 0';
          isValid = false;
        } else {
          // Validate against recommended ranges for each type
          final String? rangeError = validateRadiusRange(
            patrolTypeController.text.toLowerCase(),
            radius,
          );
          if (rangeError != null) {
            patrolRadiusError.value = rangeError;
            isValid = false;
          }
        }
      } catch (e) {
        patrolRadiusError.value = 'Invalid radius value';
        isValid = false;
      }
    }

    return isValid;
  }

  // Validate radius against recommended range
  String? validateRadiusRange(String patrolType, double radius) {
    switch (patrolType) {
      case 'car':
        if (radius < 5000)
          return 'Car patrols should have at least 5000m radius';
        if (radius > 8000) return 'Car patrol radius should not exceed 8000m';
        break;
      case 'motorcycle':
        if (radius < 3000)
          return 'Motorcycle patrols should have at least 3000m radius';
        if (radius > 5000)
          return 'Motorcycle patrol radius should not exceed 5000m';
        break;
      case 'foot':
        if (radius < 500)
          return 'Foot patrols should have at least 500m radius';
        if (radius > 1500) return 'Foot patrol radius should not exceed 1500m';
        break;
      case 'drone':
        if (radius < 2000)
          return 'Drone patrols should have at least 2000m radius';
        if (radius > 4000) return 'Drone patrol radius should not exceed 4000m';
        break;
      case 'mixed':
        if (radius < 2000)
          return 'Mixed patrols should have at least 2000m radius';
        if (radius > 6000) return 'Mixed patrol radius should not exceed 6000m';
        break;
    }
    return null;
  }

  // Get recommended range text based on patrol type
  String getRecommendedRangeText(String patrolType) {
    switch (patrolType) {
      case 'car':
        return '5000-8000m';
      case 'motorcycle':
        return '3000-5000m';
      case 'foot':
        return '500-1500m';
      case 'drone':
        return '2000-4000m';
      case 'mixed':
        return '2000-6000m';
      default:
        return '';
    }
  }

  // Create a new patrol unit with enhanced fields
  Future<bool> createNewPatrolUnit() async {
    if (!validateNewPatrolUnit()) {
      return false;
    }

    if (unitIdController.text.isEmpty) {
      TLoaders.errorSnackBar(
        title: 'Unit Required',
        message: 'Please select a unit before creating a patrol unit',
      );
      return false;
    }

    try {
      // Generate a proper ID for the new patrol unit
      final String typeCode =
          patrolTypeController.text.isNotEmpty
              ? patrolTypeController.text[0].toUpperCase()
              : 'X';

      final String unitCode =
          unitIdController.text.length >= 2
              ? unitIdController.text.substring(
                unitIdController.text.length - 2,
              )
              : 'XX';

      // Generate a sequence number based on current time
      final int rawSequence = DateTime.now().millisecondsSinceEpoch % 100000;
      final String sequence = rawSequence
          .toString()
          .padLeft(2, '0')
          .substring(0, rawSequence.toString().length.clamp(2, 5));

      final String patrolUnitId = 'PU-$typeCode$unitCode$sequence';

      // In a real scenario, we would create the patrol unit in the database
      // Here we're simulating a successful creation

      // Create patrol unit model
      final newPatrolUnit = PatrolUnitModel(
        id: patrolUnitId,
        unitId: unitIdController.text,
        locationId:
            '', // This would come from the location selection or current location
        name: patrolNameController.text,
        type: patrolTypeController.text,
        status: patrolStatusController.text,
        radius: double.parse(patrolRadiusController.text),
        createdAt: DateTime.now(),
        memberCount: int.tryParse(memberCountController.text),
        category: categoryController.text,
      );

      // In a real app, we would save this to the database
      // final result = await patrolUnitRepository.createPatrolUnit(newPatrolUnit);

      // Update the controller state
      patrolUnitIdController.text = patrolUnitId;
      selectedPatrolUnitName.value = patrolNameController.text;

      // Simulate success
      TLoaders.successSnackBar(
        title: 'Success',
        message: 'Patrol unit created successfully',
      );

      // Add to available patrol units for immediate display
      availablePatrolUnits.add(newPatrolUnit);

      update(['patrol_summary', 'patrol_selection']);
      return true;
    } catch (error) {
      TLoaders.errorSnackBar(
        title: 'Error',
        message: 'Failed to create patrol unit: $error',
      );
      return false;
    }
  }

  // Clear all error messages
  void clearErrors() {
    patrolNameError.value = '';
    patrolTypeError.value = '';
    patrolRadiusError.value = '';
    patrolStatusError.value = '';
    memberCountError.value = '';
    categoryError.value = '';
    patrolUnitIdError.value = '';
  }

  // Set the unit info (called from the parent controller)
  void setUnitInfo(String unitId, String unitName) {
    unitIdController.text = unitId;
    selectedUnitName.value = unitName;

    // Fetch patrol units for this unit
    getPatrolUnitsByUnitId(unitId);
  }

  // Reset all form fields
  void resetForm() {
    patrolNameController.text = '';
    patrolTypeController.text = 'car';
    patrolRadiusController.text = '6500';
    patrolStatusController.text = 'active';
    memberCountController.text = '1';
    categoryController.text = 'individual';
    patrolUnitIdController.text = '';
    selectedPatrolUnitName.value = '';
    selectedPatrolType.value = PatrolUnitTypeExtended.car;
    patrolSelectionMode.value = PatrolSelectionMode.individual;
    clearErrors();
  }

  @override
  void onClose() {
    // Dispose all controllers
    patrolUnitIdController.dispose();
    patrolNameController.dispose();
    patrolTypeController.dispose();
    patrolRadiusController.dispose();
    patrolStatusController.dispose();
    memberCountController.dispose();
    categoryController.dispose();
    unitIdController.dispose();
    super.onClose();
  }
}
