import 'dart:developer';
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:hmg_qline/config/dependency_injection.dart';
import 'package:hmg_qline/constants/app_constants.dart';
import 'package:hmg_qline/models/generic_response_model.dart';
import 'package:hmg_qline/models/global_config_model.dart';
import 'package:hmg_qline/models/kiosk_language_config_model.dart';
import 'package:hmg_qline/models/kiosk_queue_model.dart';
import 'package:hmg_qline/models/kiosk_ticket_model.dart';
import 'package:hmg_qline/models/prayers_widget_model.dart';
import 'package:hmg_qline/models/rss_feed_model.dart';
import 'package:hmg_qline/models/weathers_widget_model.dart';
import 'package:hmg_qline/repositories/screen_details_repo.dart';
import 'package:hmg_qline/repositories/signalR_repo.dart';
import 'package:hmg_qline/services/cache_service.dart';
import 'package:hmg_qline/services/connectivity_service.dart';
import 'package:hmg_qline/services/logger_service.dart';
import 'package:hmg_qline/utilities/enums.dart';
import 'package:hmg_qline/utilities/extensions.dart';
import 'package:hmg_qline/utilities/native_method_handler.dart';
import 'package:hmg_qline/view_models/queuing_view_model.dart';
import 'package:hmg_qline/views/view_helpers/info_components.dart';
import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
// import 'package:timezone/browser.dart' as tz;

class ScreenConfigViewModel extends ChangeNotifier {
  final ScreenDetailsRepo screenDetailsRepo;
  final CacheService cacheService;
  final ConnectivityService connectivityService;
  final LoggerService loggerService;
  final NativeMethodChannelService nativeMethodChannelService;

  ScreenConfigViewModel({
    required this.screenDetailsRepo,
    required this.cacheService,
    required this.connectivityService,
    required this.loggerService,
    required this.nativeMethodChannelService,
  });

  Future<void> initializeScreenConfigVM() async {
    appStartTime = DateTime.now(); // Record when app actually started
    await getGlobalConfigurationsByIP();
    await getLastTimeUpdatedFromCache();
    await getLastTimeLogsClearedFromCache();
    listenNetworkConnectivity();
    initializeTimer();
  }

  Future<void> onAppResumed() async {
    final uptimeHours = DateTime.now().difference(appStartTime).inHours;
    loggerService.logToFile(
      message: "[didChangeAppLifecycleState] : [onAppResumed] - App uptime: ${uptimeHours}h",
      source: "onAppResumed -> screen_config_view_model.dart",
      type: LogTypeEnum.data,
    );

    // Re-enable wakelock when resuming
    try {
      await WakelockPlus.enable();
    } catch (e) {
      loggerService.logError("Failed to enable wakelock on resume: $e");
    }

    // Verify connections are still alive
    syncHubConnectionState();
  }

  Future<void> onAppPaused() async {
    final uptimeHours = DateTime.now().difference(appStartTime).inHours;
    loggerService.logToFile(
      message: "[didChangeAppLifecycleState] : [onAppPaused] - App uptime: ${uptimeHours}h - WARNING: App going to background!",
      source: "onAppPaused -> screen_config_view_model.dart",
      type: LogTypeEnum.data,
    );
  }

  Future<void> onAppDetached() async {
    final uptimeHours = DateTime.now().difference(appStartTime).inHours;
    loggerService.logToFile(
      message: "[didChangeAppLifecycleState] : [onAppDetached] - App uptime: ${uptimeHours}h - CRITICAL: App being killed!",
      source: "onAppDetached -> screen_config_view_model.dart",
      type: LogTypeEnum.data,
    );
  }

  Future<void> waitForIPAndInitializeConfigVM() async {
    while (currentScreenIP == "") {
      await getCurrentScreenIP();
      if (currentScreenIP != "") {
        initializeScreenConfigVM();
      } else {
        await Future.delayed(const Duration(seconds: 2));
      }
    }
  }

  bool isInternetConnected = true;

  updateIsInternetConnected(bool value) {
    isInternetConnected = value;
    notifyListeners();
  }

  bool isHubConnected = true;

  updateIsHubConnected(bool value) {
    isHubConnected = value;
    notifyListeners();
  }

  ViewState state = ViewState.idle;

  void updateViewState(ViewState viewState) {
    state = viewState;
    notifyListeners();
  }

  updateCurrentScreenRotation(ScreenOrientationEnum value) {
    globalConfigurationsModel.orientationTypeEnum = value;
    notifyListeners();
  }

  ScreenTypeEnum currentScreenTypeEnum = ScreenTypeEnum.waitingAreaScreen;

  updateCurrentScreenTypeEnum(ScreenTypeEnum value) {
    currentScreenTypeEnum = value;
  }

  QTypeEnum currentQTypeEnum = QTypeEnum.lab;

  updateCurrentQTypeEnum(QTypeEnum value) {
    currentQTypeEnum = value;
  }

  String currentScreenIP = "";

  Future<void> getCurrentScreenIP() async {
    if (useTestIP) {
      currentScreenIP = AppConstants.testIP;
    } else {
      currentScreenIP = await connectivityService.getCurrentScreenIP();
      log("currentScreenIP: $currentScreenIP");
    }
  }

  void listenNetworkConnectivity() {
    return connectivityService.subscribeToConnectivityChange(
      onInternetDisConnected: () {
        updateIsInternetConnected(false);
        updateIsHubConnected(false);
      },
      onInternetConnected: () {
        updateIsInternetConnected(true);
        QueuingViewModel queuingViewModel = getIt.get<QueuingViewModel>();
        queuingViewModel.startHubConnection();
      },
    );
  }

  GlobalConfigurationsModel globalConfigurationsModel = GlobalConfigurationsModel();

  Future<void> getGlobalConfigurationsByIP() async {
    GlobalConfigurationsModel? response = await screenDetailsRepo.getGlobalScreenConfigurations(ipAddress: currentScreenIP);

    if (response == null) {
      loggerService.logError("response was: $response");
      updateViewState(ViewState.error);
      return;
    }
    updateGlobalConfigurationsModel(value: response);
    updateCurrentScreenTypeEnum(globalConfigurationsModel.screenTypeEnum);
    updateCurrentQTypeEnum(globalConfigurationsModel.qTypeEnum);

    notifyListeners();
  }

  void updateGlobalConfigurationsModel({required var value, bool needNotify = false, bool shouldUpdateNextPrayer = false}) {
    // Ensure the incoming value is the GlobalConfigurationsModel and set the Takhasusi flag based on current IP
    if (value is GlobalConfigurationsModel) {
      // IPs that belong to Takhasusi main - using AppConstants
      try {
        value.isFromTakhasusiMain = AppConstants.takhasusiMainBranchIps.contains(currentScreenIP);

        // Debug logging for Takhasusi Main detection
        log("=== TAKHASUSI MAIN CHECK ===");
        log("Current Screen IP: $currentScreenIP");
        log("Is Takhasusi Main: ${value.isFromTakhasusiMain}");
        log("Takhasusi Main IPs count: ${AppConstants.takhasusiMainBranchIps.length}");
        if (value.isFromTakhasusiMain) {
          log("✅ This device will use getTurnsByOrientationForOlderVersions()");
        } else {
          log("✅ This device will use getTurnsByOrientation()");
        }
        log("============================");
      } catch (_) {
        value.isFromTakhasusiMain = false;
      }
      globalConfigurationsModel = value;
    } else {
      globalConfigurationsModel = value;
    }

    if (needNotify) {
      notifyListeners();
    }
    if (shouldUpdateNextPrayer) {
      getNextPrayerToShow();
    }

    getInfoWidgetsDetailsFromServer();
  }

  Future<void> getInfoWidgetsDetailsFromServer() async {
    if (globalConfigurationsModel.isWeatherReq) {
      await getWeatherDetailsFromServer();
    }
    if (globalConfigurationsModel.isPrayerTimeReq) {
      await getPrayerDetailsFromServer();
    }
    if (globalConfigurationsModel.isRssFeedReq) {
      await getRssFeedDetailsFromServer();
    }

    int currentDate = DateTime.now().millisecondsSinceEpoch;
    await cacheService.setLastTimeUpdatedInCache(lasTimeUpdated: currentDate.toString());
  }

  RssFeedModel rssFeedModel = RssFeedModel();

  Future<void> getRssFeedDetailsFromServer() async {
    RssFeedModel? response = await screenDetailsRepo.getRssFeedDetailsByLanguageID(languageId: 0);

    if (response == null) {
      return;
    }
    rssFeedModel = response;
    notifyListeners();
  }

  PrayersWidgetModel prayersWidgetModel = PrayersWidgetModel();

  Future<void> getPrayerDetailsFromServer() async {
    double testLatitude = 24.722136;
    double testLongitude = 46.774303;
    PrayersWidgetModel? response = await screenDetailsRepo.getPrayerDetailsByLatLong(
      latitude: globalConfigurationsModel.projectLatitude == 0.0 ? testLatitude : globalConfigurationsModel.projectLatitude ?? testLatitude,
      longitude: globalConfigurationsModel.projectLongitude == 0.0 ? testLongitude : globalConfigurationsModel.projectLongitude ?? testLongitude,
    );

    if (response == null) {
      return;
    }

    prayersWidgetModel = response;
    getNextPrayerToShow();
    notifyListeners();
  }

  WeathersWidgetModel weathersWidgetModel = WeathersWidgetModel();

  Future<void> getWeatherDetailsFromServer() async {
    int testCityKey = 297030;
    WeathersWidgetModel? response = await screenDetailsRepo.getWeatherDetailsByCity(
      cityId: ((globalConfigurationsModel.cityKey == null || globalConfigurationsModel.cityKey == 0) ? testCityKey : globalConfigurationsModel.cityKey).toString(),
    );

    if (response == null) {
      return;
    }
    weathersWidgetModel = response;
    notifyListeners();
  }

  String nextPrayerTime = '';
  String nextPrayerToShowEng = '';
  String nextPrayerToShowArb = '';

  void getNextPrayerToShow() async {
    final current = DateTime.now();
    log("Checking Namaz time Locally at $current and ${current.timeZoneName}");

    // log("Data Before Check : ${prayersWidgetModel.fajr}");
    // log("Data Before Check : ${globalConfigurationsModel.isPrayerTimeReq}");

    if (globalConfigurationsModel.isPrayerTimeReq && prayersWidgetModel.fajr == null) {
      await getPrayerDetailsFromServer();
    }

    // log("prayersWidgetModel.dhuhr: ${prayersWidgetModel.dhuhr!}");
    // log("dhuhr: ${prayersWidgetModel.dhuhr!.toDateTimeFromInt()}");
    // log("current: ${DateFormat('yyyy-MM-dd hh:mm a').format(DateTime.now().toLocal())}");
    // log("current: ${DateTime.now().timeZoneName}");

    if (prayersWidgetModel.fajr != null && prayersWidgetModel.fajr!.toDateTimeFromInt().isAfter(current)) {
      final namazTime = prayersWidgetModel.fajr!.toFormattedDateTimeFromInt();
      nextPrayerTime = namazTime;
      nextPrayerToShowEng = "${globalConfigurationsModel.fajarTextEng}";
      nextPrayerToShowArb = "${globalConfigurationsModel.fajarTextArb}";
      notifyListeners();
      return;
    }
    if (prayersWidgetModel.dhuhr != null && prayersWidgetModel.dhuhr!.toDateTimeFromInt().isAfter(current)) {
      final namazTime = prayersWidgetModel.dhuhr!.toFormattedDateTimeFromInt();
      nextPrayerTime = namazTime;
      nextPrayerToShowEng = "${globalConfigurationsModel.dhuhrTextEng}";
      nextPrayerToShowArb = "${globalConfigurationsModel.dhuhrTextArb}";

      notifyListeners();
      return;
    }
    if (prayersWidgetModel.asr != null && prayersWidgetModel.asr!.toDateTimeFromInt().isAfter(current)) {
      final namazTime = prayersWidgetModel.asr!.toFormattedDateTimeFromInt();
      nextPrayerTime = namazTime;
      nextPrayerToShowEng = "${globalConfigurationsModel.asarTextEng}";
      nextPrayerToShowArb = "${globalConfigurationsModel.asarTextArb}";

      notifyListeners();
      return;
    }
    if (prayersWidgetModel.maghrib != null && prayersWidgetModel.maghrib!.toDateTimeFromInt().isAfter(current)) {
      final namazTime = prayersWidgetModel.maghrib!.toFormattedDateTimeFromInt();
      nextPrayerTime = namazTime;
      nextPrayerToShowEng = "${globalConfigurationsModel.maghribTextEng}";
      nextPrayerToShowArb = "${globalConfigurationsModel.maghribTextArb}";

      notifyListeners();
      return;
    }
    if (prayersWidgetModel.isha != null && prayersWidgetModel.isha!.toDateTimeFromInt().isAfter(current)) {
      final namazTime = prayersWidgetModel.isha!.toFormattedDateTimeFromInt();
      nextPrayerTime = namazTime;
      nextPrayerToShowEng = "${globalConfigurationsModel.ishaTextEng}";
      nextPrayerToShowArb = "${globalConfigurationsModel.ishaTextArb}";

      notifyListeners();
      return;
    }
    final namazTime = prayersWidgetModel.fajr!.toFormattedDateTimeFromInt();
    nextPrayerTime = namazTime;
    nextPrayerToShowEng = "${globalConfigurationsModel.fajarTextEng}";
    nextPrayerToShowArb = "${globalConfigurationsModel.fajarTextArb}";

    notifyListeners();
    return;
  }

  int counter = 0;
  DateTime lastChecked = DateTime.now();
  DateTime appStartTime = DateTime.now(); // Track actual app start time
  Timer? _midnightTimer;
  Timer? _healthCheckTimer;
  int healthCheckFailures = 0; // Track consecutive failures

  Future<void> initializeTimer() async {
    // Cancel any existing timer to avoid multiple timers running
    _midnightTimer?.cancel();
    _healthCheckTimer?.cancel();

    if (!(globalConfigurationsModel.isWeatherReq) && !(globalConfigurationsModel.isPrayerTimeReq) && !(globalConfigurationsModel.isRssFeedReq)) {
      // Even if widgets are not required, start a minimal health check
      _startHealthCheckTimer();
      return;
    }

    // Start the main periodic timer
    _midnightTimer = Timer.periodic(
      const Duration(minutes: 10),
      (timer) async {
        counter++;
        DateTime now = DateTime.now();
        log("counterValue: $counter");

        if (globalConfigurationsModel.id == null) {
          await getGlobalConfigurationsByIP();
        }

        // Every Two hour, update RSS feed if required
        if (counter % 12 == 0 && globalConfigurationsModel.isRssFeedReq) {
          await getRssFeedDetailsFromServer();
        }

        log("lastChecked: [${lastChecked.day}]");
        log("now: [${now.day}]");

        // At midnight, update weather and prayer details if required
        if (now.day != lastChecked.day) {
          if (now.difference(now.copyWith(hour: 0, minute: 0, second: 0, millisecond: 0, microsecond: 0)).inMinutes >= 5) {
            await nativeMethodChannelService.smartRestart(forceRestart: true, cleanupFirst: true);
            lastChecked = now;
          }
        }
        getNextPrayerToShow();
        syncHubConnectionState();
      },
    );

    // Start health check timer
    _startHealthCheckTimer();
  }

  void _startHealthCheckTimer() {
    // Health check every 5 minutes to keep app active and check connections
    _healthCheckTimer = Timer.periodic(
      const Duration(minutes: 5),
      (timer) async {
        try {
          final now = DateTime.now();
          final actualUptime = now.difference(appStartTime);
          final uptimeHours = actualUptime.inHours;
          final uptimeMinutes = actualUptime.inMinutes % 60;

          log("Health check - App uptime: ${uptimeHours}h ${uptimeMinutes}m");
          loggerService.logToFile(
            message: "Health check performed - App uptime: ${uptimeHours}h ${uptimeMinutes}m (started: ${appStartTime.toString().substring(0, 19)})",
            source: "_startHealthCheckTimer -> screen_config_view_model.dart",
            type: LogTypeEnum.data,
          );

          // Check if app has been running for dangerously long (>60 hours)
          if (uptimeHours > 60) {
            loggerService.logToFile(
              message: "WARNING: App running for ${uptimeHours} hours - scheduling proactive restart",
              source: "_startHealthCheckTimer -> screen_config_view_model.dart",
              type: LogTypeEnum.data,
            );
          }

          // Sync hub connection state
          try {
            syncHubConnectionState();
            healthCheckFailures = 0; // Reset on success
          } catch (e) {
            healthCheckFailures++;
            loggerService.logError("Health check - Hub sync failed (${healthCheckFailures} consecutive): $e");

            // If multiple consecutive failures, try to recover
            if (healthCheckFailures >= 3) {
              loggerService.logToFile(
                message: "CRITICAL: ${healthCheckFailures} consecutive health check failures - attempting recovery",
                source: "_startHealthCheckTimer -> screen_config_view_model.dart",
                type: LogTypeEnum.data,
              );
              QueuingViewModel queuingViewModel = getIt.get<QueuingViewModel>();
              await queuingViewModel.stopHubConnection();
              await Future.delayed(const Duration(seconds: 2));
              await queuingViewModel.startHubConnection();
            }
          }

          // Ensure wakelock is still enabled
          try {
            await WakelockPlus.enable();
          } catch (e) {
            loggerService.logError("Failed to enable wakelock: $e");
          }

          // Log memory/performance indicators
          loggerService.logToFile(
            message: "Health check - Hub connected: $isHubConnected, Internet: $isInternetConnected",
            source: "_startHealthCheckTimer -> screen_config_view_model.dart",
            type: LogTypeEnum.connectivity,
          );

          // Trigger a small notifyListeners to keep UI thread active
          notifyListeners();
        } catch (e, stackTrace) {
          healthCheckFailures++;
          loggerService.logError("Health check timer error (${healthCheckFailures} consecutive): $e\n$stackTrace");

          // If health check itself is failing repeatedly, something is seriously wrong
          if (healthCheckFailures >= 5) {
            loggerService.logToFile(
              message: "FATAL: Health check failing repeatedly - app may be in bad state",
              source: "_startHealthCheckTimer -> screen_config_view_model.dart",
              type: LogTypeEnum.data,
            );
          }
        }
      },
    );
  }

  @override
  void dispose() {
    _midnightTimer?.cancel();
    _healthCheckTimer?.cancel();
    patientIdController.dispose();

    super.dispose();
  }

  DateTime currentLastTimeUpdated = DateTime.now();

  Future<void> getLastTimeUpdatedFromCache() async {
    DateTime? response = await cacheService.getLastTimeUpdatedFromCache();
    if (response != null) {
      currentLastTimeUpdated = response;
    }
  }

  DateTime? lastTimeLogsCleared = DateTime.now();

  Future<void> getLastTimeLogsClearedFromCache() async {
    lastTimeLogsCleared = await cacheService.getLastTimeLogsCleared();
    if (lastTimeLogsCleared == null) {
      await cacheService.setLastTimeLogsCleared(lastTimeCleared: DateTime.now().millisecondsSinceEpoch).whenComplete(() => lastTimeLogsCleared = DateTime.now());
    }
  }

//   *************************** KIOSK FUNCTIONS *************************

  KioskScreenStateEnums kioskScreenStateEnum = KioskScreenStateEnums.languageState;

  void updateKioskScreenState(KioskScreenStateEnums state) {
    kioskScreenStateEnum = state;
    notifyListeners();
  }

  KioskPatientTicket? kioskPatientTicket = KioskPatientTicket();

  void updateTicketGeneratedFromKiosk(KioskPatientTicket? value) {
    kioskPatientTicket = value;
    notifyListeners();
  }

  KioskLanguageConfigModel? currentSelectedKioskLanguage;

  void updateCurrentSelectedKioskLanguageModel(KioskLanguageConfigModel value) {
    currentSelectedKioskLanguage = value;
    notifyListeners();
  }

  late KioskQueueModel currentSelectedKioskQueueModel;

  void updateCurrentSelectedKioskQueueModel(KioskQueueModel value) {
    currentSelectedKioskQueueModel = value;
    notifyListeners();
  }

  Future<bool> generateTicketForQueue({required KioskQueueModel kioskQueueModel, int patientId = 0}) async {
    updateKioskScreenState(KioskScreenStateEnums.busyState);
    KioskPatientTicket? kioskPatientTicket = await createTicketFromKiosk(
      projectId: kioskQueueModel.projectID ?? 0,
      queueId: kioskQueueModel.queueID ?? 0,
      patientId: patientId,
    );
    if (kioskPatientTicket == null) {
      updateKioskScreenState(KioskScreenStateEnums.languageState);
      return false;
    }
    updateTicketGeneratedFromKiosk(kioskPatientTicket);
    updateKioskScreenState(KioskScreenStateEnums.ticketNumState);
    return true;
  }

  Future<void> createTestTickets({required int numOfTicketsToCreate}) async {
    int startTicket = 123457100;

    for (int i = 0; i < numOfTicketsToCreate; i++) {
      GenericRespModel? response = await screenDetailsRepo.createTestTickets(ticketNumber: startTicket);
      startTicket = startTicket + 1;
      if (response == null || response.messageStatus != 1) {
        log("response null from createNextTickets");
        return;
      }
    }

    log("last ticket is: $startTicket ");
  }

  Future<KioskPatientTicket?> createTicketFromKiosk({required int projectId, required int queueId, int patientId = 0}) async {
    try {
      GenericRespModel? response = await screenDetailsRepo.createTicketFromKiosk(
        projectId: projectId,
        queueId: queueId,
        patientId: patientId,
      );
      if (response == null || response.messageStatus != 1) {
        loggerService.logError("response null from createTicketFromKiosk");
        return null;
      }
      return response.data;
    } catch (e) {
      InfoComponents.showToast(e.toString());
      loggerService.logError(e.toString());
      return null;
    }
  }

  Future<void> acknowledgeTicket({required int ticketQueueID, required String ipAddress}) async {
    GenericRespModel? response = await screenDetailsRepo.acknowledgeTicket(
      ipAddress: ipAddress,
      ticketQueueID: ticketQueueID,
      qTypeEnum: globalConfigurationsModel.qTypeEnum,
    );
    if (response == null || response.messageStatus != 1) {
      loggerService.logError("response null from acknowledgeTicket");
      return;
    } else {
      loggerService.logInfo("response from acknowledgeTicket ${response.data}");
    }
  }

  Future<void> acknowledgeTicketForAppointmentOnly({required int ticketQueueID, required String ipAddress, required CallTypeEnum callTypeEnum}) async {
    GenericRespModel? response = await screenDetailsRepo.acknowledgeTicketForAppointment(
      ticketId: ticketQueueID,
      ipAddress: ipAddress,
      callTypeEnum: callTypeEnum,
    );
    if (response == null || response.messageStatus != 1) {
      loggerService.logError("response null from acknowledgeTicketForAppointmentOnly");
      return;
    } else {
      loggerService.logInfo("response from acknowledgeTicketForAppointmentOnly ${response.data}");
    }
  }

// ***************************** TEXT INPUT PATIENT ID  FUNCTIONS *********************

  final TextEditingController patientIdController = TextEditingController();

  Future<void> onPatientIdSubmitted(String text) async {
    int? patientId = int.tryParse(text);
    if (patientId != null && patientId > 0) {
      isGeneratingTicket = true;
      await generateTicketForQueue(kioskQueueModel: currentSelectedKioskQueueModel, patientId: patientId);
      patientIdController.clear();
      await Future.delayed(const Duration(seconds: 2)).whenComplete(() => isGeneratingTicket = false);
    }
  }

//   *************************** QR SCANNER FUNCTIONS *************************

  Barcode? qrCodeResult;
  QRViewController? qrViewController;
  bool isGeneratingTicket = false;

  Future<void> flipCamera() async {
    await qrViewController!.flipCamera();
  }

  void onQRViewCreated({
    required QRViewController controller,
    required VoidCallback onSuccess,
    required VoidCallback onFailure,
  }) async {
    qrViewController = controller;

    controller.scannedDataStream.listen((scanData) async {
      loggerService.logInfo("Found: ${scanData.code} and isGeneratingTicket: $isGeneratingTicket");
      if (isGeneratingTicket) return;
      await validateAndGenerateTicketFromQR(data: scanData, onFailure: onFailure, onSuccess: onSuccess);
    });
    await flipCamera();
  }

  Future<void> validateAndGenerateTicketFromQR({required var data, required VoidCallback onSuccess, required VoidCallback onFailure}) async {
    if (data == null) return;
    qrCodeResult = data;
    notifyListeners();

    final code = qrCodeResult!.code;
    int? patientId = int.tryParse(code ?? '');
    if (patientId != null && patientId > 0) {
      isGeneratingTicket = true;
      bool status = await generateTicketForQueue(kioskQueueModel: currentSelectedKioskQueueModel, patientId: patientId);
      qrCodeResult = null;
      notifyListeners();

      if (status) {
        log("status: $status");
        onSuccess();
      }

      await Future.delayed(const Duration(seconds: 2)).whenComplete(() => isGeneratingTicket = false);
    }
  }

  Future<void> reassemble() async {
    if (qrViewController != null) {
      if (defaultTargetPlatform == TargetPlatform.android) {
        await qrViewController!.pauseCamera();
      } else if (defaultTargetPlatform == TargetPlatform.iOS) {
        await qrViewController!.resumeCamera();
      }
      await qrViewController!.flipCamera();
    }
  }

  void syncHubConnectionState() async {
    QueuingViewModel queuingViewModel = getIt.get<QueuingViewModel>();
    bool newState = (queuingViewModel.signalrRepo as SignalrRepoImp).isConnected;

    loggerService.logToFile(
      message: "Hub Current Status : $newState",
      source: "syncHubConnectionState-> screen_config_view_model.dart",
      type: LogTypeEnum.connectivity,
    );
    log("[isHubConnected: $isHubConnected] , [newState: $newState]");

    if (isHubConnected != newState) {
      updateIsHubConnected(newState);
    }
    if (!isHubConnected) {
      QueuingViewModel queuingViewModel = getIt.get<QueuingViewModel>();
      bool? status = await queuingViewModel.startHubConnection();
      // syncHubConnectionState will update isHubConnected
    } else {
      log("Hub is Connected!");
    }
  }
}
