import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:on_field_work/helpers/services/auth_service.dart';
import 'package:on_field_work/helpers/services/storage/local_storage.dart';
import 'package:on_field_work/helpers/widgets/my_form_validator.dart';
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';
import 'package:on_field_work/helpers/services/app_logger.dart';
import 'package:on_field_work/helpers/services/firebase/firebase_messaging_service.dart';
import 'package:on_field_work/controller/permission_controller.dart';
import 'package:on_field_work/controller/project_controller.dart';

class MPINController extends GetxController {
  final MyFormValidator basicValidator = MyFormValidator();
  final isNewUser = false.obs;
  final isChangeMpin = false.obs;
  final RxBool isLoading = false.obs;
  final formKey = GlobalKey<FormState>();

  // Updated to 4-digit MPIN
  final digitControllers = List.generate(4, (_) => TextEditingController());
  final focusNodes = List.generate(4, (_) => FocusNode());

  final retypeControllers = List.generate(4, (_) => TextEditingController());
  final retypeFocusNodes = List.generate(4, (_) => FocusNode());

  final RxInt failedAttempts = 0.obs;

  @override
  void onInit() {
    super.onInit();
    final bool hasMpin = LocalStorage.getIsMpin();
    isNewUser.value = !hasMpin;
    logSafe("onInit called. isNewUser: ${isNewUser.value}");
  }

  /// Enable Change MPIN mode
  void setChangeMpinMode() {
    isChangeMpin.value = true;
    isNewUser.value = false;
    clearFields();
    clearRetypeFields();
    logSafe("setChangeMpinMode activated");
  }

  /// Handle digit entry and focus movement
  void onDigitChanged(String value, int index, {bool isRetype = false}) {
    logSafe(
        "onDigitChanged -> index: $index, value: $value, isRetype: $isRetype");
    final nodes = isRetype ? retypeFocusNodes : focusNodes;
    if (value.isNotEmpty && index < 3) {
      nodes[index + 1].requestFocus();
    } else if (value.isEmpty && index > 0) {
      nodes[index - 1].requestFocus();
    }
  }

  /// Submit MPIN for verification or generation
  Future<void> onSubmitMPIN() async {
    logSafe("onSubmitMPIN triggered");

    if (!formKey.currentState!.validate()) {
      logSafe("Form validation failed", level: LogLevel.warning);
      return;
    }

    final enteredMPIN = digitControllers.map((c) => c.text).join();
    logSafe("Entered MPIN: $enteredMPIN");

    if (enteredMPIN.length < 4) {
      _showError("Please enter all 4 digits.");
      return;
    }

    if (isNewUser.value || isChangeMpin.value) {
      final retypeMPIN = retypeControllers.map((c) => c.text).join();
      logSafe("Retyped MPIN: $retypeMPIN");

      if (retypeMPIN.length < 4) {
        _showError("Please enter all 4 digits in Retype MPIN.");
        return;
      }

      if (enteredMPIN != retypeMPIN) {
        _showError("MPIN and Retype MPIN do not match.");
        clearFields();
        clearRetypeFields();
        return;
      }

      final bool success = await generateMPIN(mpin: enteredMPIN);

      if (success) {
        logSafe("MPIN generation/change successful.");
        showAppSnackbar(
          title: "Success",
          message: isChangeMpin.value
              ? "MPIN changed successfully."
              : "MPIN generated successfully. Please login again.",
          type: SnackbarType.success,
        );
        await LocalStorage.logout();
      } else {
        logSafe("MPIN generation/change failed.", level: LogLevel.warning);
        clearFields();
        clearRetypeFields();
      }
    } else {
      logSafe("Existing user. Proceeding to verify MPIN.");
      await verifyMPIN();
    }
  }

  /// Forgot MPIN
  Future<void> onForgotMPIN() async {
    logSafe("onForgotMPIN called");
    isNewUser.value = true;
    isChangeMpin.value = false;
    clearFields();
    clearRetypeFields();
  }

  /// Switch to login/enter MPIN screen
  void switchToEnterMPIN() {
    logSafe("switchToEnterMPIN called");
    isNewUser.value = false;
    isChangeMpin.value = false;
    clearFields();
    clearRetypeFields();
  }

  /// Show error snackbar
  void _showError(String message) {
    logSafe("ERROR: $message", level: LogLevel.error);
    showAppSnackbar(
      title: "Error",
      message: message,
      type: SnackbarType.error,
    );
  }

  /// Navigate to dashboard
  /// Navigate to tenant selection after MPIN verification
  void _navigateToTenantSelection({String? message}) {
    if (message != null) {
      logSafe("Navigating to Tenant Selection with message: $message");
      showAppSnackbar(
        title: "Success",
        message: message,
        type: SnackbarType.success,
      );
    }
     Get.offAllNamed('/select-tenant');
  }

  /// Clear the primary MPIN fields
  void clearFields() {
    logSafe("clearFields called");
    for (final c in digitControllers) {
      c.clear();
    }
    focusNodes.first.requestFocus();
  }

  /// Clear the retype MPIN fields
  void clearRetypeFields() {
    logSafe("clearRetypeFields called");
    for (final c in retypeControllers) {
      c.clear();
    }
    retypeFocusNodes.first.requestFocus();
  }

  /// Cleanup
  @override
  void onClose() {
    logSafe("onClose called");
    for (final controller in digitControllers) {
      controller.dispose();
    }
    for (final node in focusNodes) {
      node.dispose();
    }
    for (final controller in retypeControllers) {
      controller.dispose();
    }
    for (final node in retypeFocusNodes) {
      node.dispose();
    }
    super.onClose();
  }

  /// Generate MPIN for new user/change MPIN
  Future<bool> generateMPIN({required String mpin}) async {
    try {
      isLoading.value = true;
      logSafe("generateMPIN started");

      final employeeInfo = LocalStorage.getEmployeeInfo();
      final String? employeeId = employeeInfo?.id;

      if (employeeId == null || employeeId.isEmpty) {
        isLoading.value = false;
        _showError("Missing employee ID.");
        return false;
      }

      logSafe("Calling AuthService.generateMpin for employeeId: $employeeId");

      final response = await AuthService.generateMpin(
        employeeId: employeeId,
        mpin: mpin,
      );

      isLoading.value = false;

      if (response == null) {
        return true;
      } else {
        logSafe("MPIN generation returned error: $response",
            level: LogLevel.warning);
        showAppSnackbar(
          title: "MPIN Operation Failed",
          message: "Please check your inputs.",
          type: SnackbarType.error,
        );
        basicValidator.addErrors(response);
        basicValidator.validateForm();
        basicValidator.clearErrors();
        return false;
      }
    } catch (e) {
      isLoading.value = false;
      logSafe("Exception in generateMPIN", level: LogLevel.error, error: e);
      _showError("Failed to process MPIN.");
      return false;
    }
  }

  /// Verify MPIN for existing user
  Future<void> verifyMPIN() async {
    logSafe("verifyMPIN triggered");

    final enteredMPIN = digitControllers.map((c) => c.text).join();
    if (enteredMPIN.length < 4) {
      _showError("Please enter all 4 digits.");
      return;
    }

    final mpinToken = await LocalStorage.getMpinToken();
    if (mpinToken == null || mpinToken.isEmpty) {
      _showError("Missing MPIN token. Please log in again.");
      return;
    }

    try {
      isLoading.value = true;

      final fcmToken = await FirebaseNotificationService().getFcmToken();

      final response = await AuthService.verifyMpin(
        mpin: enteredMPIN,
        mpinToken: mpinToken,
        fcmToken: fcmToken ?? '',
      );

      isLoading.value = false;

      if (response == null) {
        logSafe("MPIN verified successfully");
        await LocalStorage.setBool('mpin_verified', true);

        // 🔹 Ensure controllers are injected and loaded
        final token = await LocalStorage.getJwtToken();
        if (token != null && token.isNotEmpty) {
          if (!Get.isRegistered<PermissionController>()) {
            Get.put(PermissionController());
            await Get.find<PermissionController>().loadData(token);
          }
          if (!Get.isRegistered<ProjectController>()) {
            Get.put(ProjectController(), permanent: true);
            await Get.find<ProjectController>().fetchProjects();
          }
        }

        showAppSnackbar(
          title: "Success",
          message: "MPIN Verified Successfully",
          type: SnackbarType.success,
        );
        _navigateToTenantSelection();
      } else {
        final errorMessage = response["error"] ?? "Invalid MPIN";
        logSafe("MPIN verification failed: $errorMessage",
            level: LogLevel.warning);
        showAppSnackbar(
          title: "Error",
          message: errorMessage,
          type: SnackbarType.error,
        );
        clearFields();
        onInvalidMPIN();
      }
    } catch (e) {
      isLoading.value = false;
      logSafe("Exception in verifyMPIN", level: LogLevel.error, error: e);
      _showError("Something went wrong. Please try again.");
    }
  }

  /// Increment failed attempts and warn
  void onInvalidMPIN() {
    failedAttempts.value++;
    if (failedAttempts.value >= 3) {
      showAppSnackbar(
        title: "Error",
        message: "Too many failed attempts. Consider logging in again.",
        type: SnackbarType.error,
      );
    }
  }
}
