import 'dart:async';
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/data/organ_mapping_data.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/organ_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/req_models/schedule_appointment_request_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/body_symptom_response_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/explanations_response_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/get_clinic_details_response_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/rationale_response_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/risk_and_suggestions_response_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/schedule_appointment_response_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/symptoms_user_details_response_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/triage_level_response_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/triage_response_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_repo.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';

class SymptomsCheckerViewModel extends ChangeNotifier {
  final SymptomsCheckerRepo symptomsCheckerRepo;
  final ErrorHandlerService errorHandlerService;
  final AppState appState;

  SymptomsCheckerViewModel({
    required this.symptomsCheckerRepo,
    required this.errorHandlerService,
    required this.appState,
  });

  // Gender constants for both English and Arabic
  static const String _maleEn = "male";
  static const String _femaleEn = "female";
  static const String _maleAr = "ذكر";
  static const String _femaleAr = "أنثى";

  /// Convert gender string to integer (1 for male, 2 for female)
  /// Handles both English and Arabic values
  int _getGenderAsInt(String? gender) {
    if (gender == null) return 1; // Default to male
    final lowerGender = gender.toLowerCase();
    if (lowerGender == _maleEn || gender == _maleAr) {
      return 1;
    }
    return 2; // Female or any other value
  }

  // State variables
  bool isBodyHidden = false;
  BodyView _currentView = BodyView.front;
  final Set<String> _selectedOrganIds = {};
  bool _isBottomSheetExpanded = false;

  // Zoom state
  double _currentZoomScale = 1.0;
  static const double _minZoomScale = 1.0;
  static const double _maxZoomScale = 2.0;
  static const double _zoomStep = 1.0;

  // Tooltip state
  String? _tooltipOrganId;
  Timer? _tooltipTimer;

  // API loading states
  bool isBodySymptomsLoading = false;
  bool isRiskFactorsLoading = false;
  bool isSuggestionsLoading = false;
  bool isTriageDiagnosisLoading = false;
  bool isScheduleAppointmentLoading = false;
  bool isRationaleLoading = false;
  bool isTriageLevelLoading = false;
  bool isExplanationsLoading = false;

  // Flag to track if appointment is being booked via symptoms checker flow
  bool isBookingFromSymptomsChecker = false;

  // API data storage - using API models directly
  SymptomsUserDetailsResponseModel? symptomsUserDetailsResponseModel;
  BodySymptomResponseModel? bodySymptomResponse;
  RiskAndSuggestionsResponseModel? riskFactorsResponse;
  RiskAndSuggestionsResponseModel? suggestionsResponse;
  TriageDataDetails? triageDataDetails;
  RationaleResponseModel? rationaleResponse;
  TriageLevelResponseModel? triageLevelResponse;
  ExplanationsResponseModel? explanationsResponse;

  // Triage state
  int? _selectedTriageChoiceIndex; // Deprecated - keeping for backward compatibility
  final Map<String, int> _selectedTriageChoicesByItemId = {}; // Map of itemId -> choiceIndex for multi-item questions
  final List<Map<String, String>> _triageEvidenceList = []; // Store triage evidence with proper format
  int _triageQuestionCount = 0; // Track number of triage questions answered

  // For type=1 questions: single selection across all items
  String? _selectedSingleItemId; // Store which item was selected
  int? _selectedSingleChoiceIndex; // Store which choice was selected

  // Triage question history tracking
  final List<TriageDataDetails> _triageQuestionHistory = []; // Stack of previous questions
  final List<List<Map<String, String>>> _triageEvidenceHistory = []; // Stack of evidence states at each question

  // Selected risk factors tracking
  final Set<String> _selectedRiskFactorIds = {};

  // Selected Suggestions tracking
  final Set<String> _selectedSuggestionsIds = {};

  // Selected symptoms tracking (organId -> Set of symptom IDs)
  final Map<String, Set<String>> _selectedSymptomsByOrgan = {};

  // Symptom search/filter state
  String _symptomSearchQuery = '';
  List<OrganSymptomResult> _filteredOrganSymptomsResults = [];

  // User Info Flow State
  int _userInfoCurrentPage = 0;
  bool _isSinglePageEditMode = false; // Track if editing single page or full flow
  String? _selectedGender;
  DateTime? _dateOfBirth;
  int? _selectedAge;
  num _selectedHeight = 170;
  bool _isHeightCm = true;
  num _selectedWeight = 60;
  bool _isWeightKg = true;

  // Getters

  bool isPossibleConditionsLoading = false;

  // User Info Getters
  int get userInfoCurrentPage => _userInfoCurrentPage;

  bool get isSinglePageEditMode => _isSinglePageEditMode;

  String? get selectedGender => _selectedGender;

  DateTime? get dateOfBirth => _dateOfBirth;

  int? get selectedAge => _selectedAge;

  setSelectedAge(int age) {
    _selectedAge = age;
  }

  setSelectedHeight(num height) {
    _selectedHeight = height;
    notifyListeners();
  }

  setSelectedWeight(num weight) {
    _selectedWeight = weight;
    notifyListeners();
  }

  num? get selectedHeight => _selectedHeight;

  bool get isHeightCm => _isHeightCm;

  num? get selectedWeight => _selectedWeight;

  bool get isWeightKg => _isWeightKg;

  BodyView get currentView => _currentView;

  Set<String> get selectedOrganIds => _selectedOrganIds;

  bool get isBottomSheetExpanded => _isBottomSheetExpanded;

  String? get tooltipOrganId => _tooltipOrganId;

  double get currentZoomScale => _currentZoomScale;

  String get currentSessionAuthToken => symptomsUserDetailsResponseModel?.tokenDetails?.authToken ?? "";

  String get currentSessionId => symptomsUserDetailsResponseModel?.sessionId ?? "";

  // Triage-related getters
  bool get shouldStopTriage => triageDataDetails?.shouldStop ?? false;

  bool get hasEmergencyEvidence => triageDataDetails?.hasEmergencyEvidence ?? false;

  String? get currentInterviewToken => triageDataDetails?.interviewToken;

  TriageQuestion? get currentTriageQuestion => triageDataDetails?.question;

  List<TriageCondition>? get currentConditions => triageDataDetails?.conditions;

  int? get selectedTriageChoiceIndex => _selectedTriageChoiceIndex;

  /// Get the number of triage questions answered
  int get triageQuestionCount => _triageQuestionCount;

  /// Check if this is the first triage question (no history)
  bool get isFirstTriageQuestion => _triageQuestionHistory.isEmpty;

  List<GetClinicDetailsResponseModel> clinicDetailsList = [];

  /// Get choice index for a specific item
  int? getTriageChoiceForItem(String itemId) {
    return _selectedTriageChoicesByItemId[itemId];
  }

  /// Check if current question type is single selection (type=1)
  bool get isTriageQuestionSingleSelection => currentTriageQuestion?.type == 1;

  /// Check if current question type is multi-item selection (type=2)
  bool get isTriageQuestionMultiItem => currentTriageQuestion?.type == 2;

  /// For type=1 questions: check if a specific item is selected (ignore choiceIndex)
  bool isTriageSingleOptionSelected(String itemId, int choiceIndex) {
    return _selectedSingleItemId == itemId;
  }

  /// Get selected item ID for type=1 questions
  String? get selectedSingleItemId => _selectedSingleItemId;

  /// Get selected choice index for type=1 questions
  int? get selectedSingleChoiceIndex => _selectedSingleChoiceIndex;

  /// Set flag for booking from symptoms checker
  void setBookingFromSymptomsChecker(bool value) {
    isBookingFromSymptomsChecker = value;

    log("isBookingFromSymptomsChecker: $isBookingFromSymptomsChecker");
    notifyListeners();
  }

  /// Check if all items in current question have been answered
  bool get areAllTriageItemsAnswered {
    if (currentTriageQuestion?.items == null || currentTriageQuestion!.items!.isEmpty) {
      return false;
    }

    // Type 1: Single selection mode - check if any option is selected
    if (isTriageQuestionSingleSelection) {
      return _selectedSingleItemId != null && _selectedSingleChoiceIndex != null;
    }

    // Type 2: Multi-item selection mode - check if all items have answers
    // Check if we have an answer for each item
    for (var item in currentTriageQuestion!.items!) {
      if (item.id != null && !_selectedTriageChoicesByItemId.containsKey(item.id)) {
        return false;
      }
    }
    return true;
  }

  /// Get organs for current view
  List<OrganModel> get currentOrgans => OrganData.getOrgansForView(_currentView, genderKey: _selectedGender);

  /// Get all selected organs from both views (for the selected gender)
  List<OrganModel> get selectedOrgans {
    final allOrgans = OrganData.getAllOrgans(genderKey: _selectedGender);
    return allOrgans.where((organ) => _selectedOrganIds.contains(organ.id)).toList();
  }

  /// Check if any organs are selected
  bool get hasSelectedOrgans => _selectedOrganIds.isNotEmpty;

  /// Get count of selected organs
  int get selectedOrgansCount => _selectedOrganIds.length;

  List<OrganSymptomResult> get organSymptomsResults {
    if (bodySymptomResponse?.dataDetails?.result == null) {
      return [];
    }
    return bodySymptomResponse!.dataDetails!.result ?? [];
  }

  /// Get filtered organ symptoms results based on search query
  List<OrganSymptomResult> get filteredOrganSymptomsResults {
    if (_symptomSearchQuery.isEmpty) {
      return organSymptomsResults;
    }
    return _filteredOrganSymptomsResults;
  }

  /// Get current search query
  String get symptomSearchQuery => _symptomSearchQuery;

  /// Get all symptoms from all organs (for search suggestions)
  List<BodySymptom> get allSymptoms {
    List<BodySymptom> symptoms = [];
    for (var organResult in organSymptomsResults) {
      if (organResult.bodySymptoms != null) {
        symptoms.addAll(organResult.bodySymptoms!);
      }
    }
    return symptoms;
  }

  int get totalSelectedSymptomsCount {
    return _selectedSymptomsByOrgan.values.fold(0, (sum, symptomIds) => sum + symptomIds.length);
  }

  bool get hasSelectedSymptoms {
    return _selectedSymptomsByOrgan.values.any((symptomIds) => symptomIds.isNotEmpty);
  }

  /// Get risk factors list
  List<RiskAndSuggestionsItemModel> get riskFactorsList {
    return riskFactorsResponse?.dataDetails ?? [];
  }

  /// Check if any risk factors are selected
  bool get hasSelectedRiskFactors => _selectedRiskFactorIds.isNotEmpty;

  /// Get selected risk factors count
  int get selectedRiskFactorsCount => _selectedRiskFactorIds.length;

  /// Check if any risk factors are selected
  bool get hasSelectedSuggestions => _selectedSuggestionsIds.isNotEmpty;

  /// Get selected risk factors count
  int get selectedSuggestionsCount => _selectedSuggestionsIds.length;

  /// Get risk factors list
  List<RiskAndSuggestionsItemModel> get suggestionsList {
    return suggestionsResponse?.dataDetails ?? [];
  }

  void toggleView() {
    _currentView = _currentView == BodyView.front ? BodyView.back : BodyView.front;
    _currentZoomScale = 1.0; // Reset zoom when switching views
    notifyListeners();
  }

  toggleIsBodyHidden() {
    isBodyHidden = !isBodyHidden;
    notifyListeners();
  }

  void toggleOrganSelection(String organId) {
    if (selectedOrganIds.isEmpty && _isBottomSheetExpanded == false) {
      toggleBottomSheet();
    }

    if (_selectedOrganIds.contains(organId)) {
      _selectedOrganIds.remove(organId);
    } else {
      _selectedOrganIds.add(organId);
    }

    // Show tooltip
    _showTooltip(organId);

    if (_selectedOrganIds.isEmpty) {
      _isBottomSheetExpanded = false;
      notifyListeners();
    }

    notifyListeners();
  }

  toggleZoomIn() {
    if (_currentZoomScale < _maxZoomScale) {
      _currentZoomScale = (_currentZoomScale + _zoomStep).clamp(_minZoomScale, _maxZoomScale);
      notifyListeners();
    }
  }

  toggleZoomOut() {
    if (_currentZoomScale > _minZoomScale) {
      _currentZoomScale = (_currentZoomScale - _zoomStep).clamp(_minZoomScale, _maxZoomScale);
      notifyListeners();
    }
  }

  void _showTooltip(String organId) {
    _tooltipTimer?.cancel();

    _tooltipOrganId = organId;
    notifyListeners();

    // Hide tooltip after 2 seconds
    _tooltipTimer = Timer(const Duration(seconds: 1), () {
      _tooltipOrganId = null;
      notifyListeners();
    });
  }

  /// Hide tooltip immediately
  void hideTooltip() {
    _tooltipTimer?.cancel();
    _tooltipOrganId = null;
    notifyListeners();
  }

  void removeOrgan(String organId) {
    _selectedOrganIds.remove(organId);
    notifyListeners();
    if (_selectedOrganIds.isEmpty) {
      _isBottomSheetExpanded = false;
      notifyListeners();
    }
  }

  void clearAllSelections() {
    _selectedOrganIds.clear();
    notifyListeners();
  }

  void toggleBottomSheet({bool? value}) {
    if (value != null) {
      _isBottomSheetExpanded = value;
      notifyListeners();
      return;
    }
    _isBottomSheetExpanded = !_isBottomSheetExpanded;
    notifyListeners();
  }

  void setBottomSheetExpanded(bool isExpanded) {
    _isBottomSheetExpanded = isExpanded;
    notifyListeners();
  }

  bool validateSelection() {
    return _selectedOrganIds.isNotEmpty;
  }

  List<String> getSelectedOrganIds() {
    return _selectedOrganIds.toList();
  }

  List<String> getSelectedOrganNames() {
    return selectedOrgans.map((organ) => organ.description).toList();
  }

  Future<void> initializeSymptomGroups({
    Function()? onSuccess,
    Function(String)? onError,
  }) async {
    if (_selectedOrganIds.isEmpty) {
      if (onError != null) {
        onError('No organs selected');
      }
      return;
    }

    List<String> organNames = selectedOrgans.map((organ) => organ.name).toList();

    await getBodySymptomsByName(
      organNames: organNames,
      onSuccess: (response) {
        if (onSuccess != null) {
          onSuccess();
        }
      },
      onError: (error) {
        if (onError != null) {
          onError(error);
        }
      },
    );
  }

  void toggleSymptomSelection(String organId, String symptomId) {
    if (!_selectedSymptomsByOrgan.containsKey(organId)) {
      _selectedSymptomsByOrgan[organId] = {};
    }

    if (_selectedSymptomsByOrgan[organId]!.contains(symptomId)) {
      _selectedSymptomsByOrgan[organId]!.remove(symptomId);
    } else {
      _selectedSymptomsByOrgan[organId]!.add(symptomId);
    }
    notifyListeners();
  }

  bool isSymptomSelected(String organId, String symptomId) {
    return _selectedSymptomsByOrgan[organId]?.contains(symptomId) ?? false;
  }

  List<BodySymptom> getAllSelectedSymptoms() {
    List<BodySymptom> allSymptoms = [];

    if (bodySymptomResponse?.dataDetails?.result == null) {
      return allSymptoms;
    }

    for (var organResult in bodySymptomResponse!.dataDetails!.result!) {
      String? matchingOrganId;
      for (var organ in selectedOrgans) {
        if (organ.name == organResult.name) {
          matchingOrganId = organ.id;
          break;
        }
      }

      if (matchingOrganId != null && _selectedSymptomsByOrgan.containsKey(matchingOrganId)) {
        final selectedIds = _selectedSymptomsByOrgan[matchingOrganId]!;

        if (organResult.bodySymptoms != null) {
          for (var symptom in organResult.bodySymptoms!) {
            if (symptom.id != null && selectedIds.contains(symptom.id)) {
              allSymptoms.add(symptom);
            }
          }
        }
      }
    }

    return allSymptoms;
  }

  void clearAllSymptomSelections() {
    _selectedSymptomsByOrgan.clear();
    notifyListeners();
  }

  /// Filter symptoms based on search query
  void filterSymptoms(String query, {bool isArabic = false}) {
    _symptomSearchQuery = query;

    if (query.isEmpty) {
      _filteredOrganSymptomsResults.clear();
      notifyListeners();
      return;
    }

    final lowercaseQuery = query.toLowerCase();
    _filteredOrganSymptomsResults = [];

    for (var organResult in organSymptomsResults) {
      if (organResult.bodySymptoms == null || organResult.bodySymptoms!.isEmpty) {
        continue;
      }

      // Filter symptoms that match the query
      final filteredSymptoms = organResult.bodySymptoms!.where((symptom) {
        final displayName = symptom.getDisplayName(isArabic).toLowerCase();
        return displayName.contains(lowercaseQuery);
      }).toList();

      // Only add organ result if it has matching symptoms
      if (filteredSymptoms.isNotEmpty) {
        _filteredOrganSymptomsResults.add(
          OrganSymptomResult(
            name: organResult.name,
            bodySymptoms: filteredSymptoms,
          ),
        );
      }
    }

    notifyListeners();
  }

  /// Clear symptom search filter
  void clearSymptomFilter() {
    _symptomSearchQuery = '';
    _filteredOrganSymptomsResults.clear();
    notifyListeners();
  }

  // Risk Factors Methods

  /// Toggle risk factor selection
  void toggleRiskFactorSelection(String riskFactorId) {
    if (riskFactorId == "not_applicable") {
      // "Not applicable" is mutually exclusive:  if selected, clear all others
      if (_selectedRiskFactorIds.contains(riskFactorId)) {
        _selectedRiskFactorIds.remove(riskFactorId);
      } else {
        _selectedRiskFactorIds
          ..clear()
          ..add(riskFactorId);
      }
    } else {
      _selectedRiskFactorIds.remove("not_applicable");
      if (!_selectedRiskFactorIds.add(riskFactorId)) {
        _selectedRiskFactorIds.remove(riskFactorId);
      }
    }

    notifyListeners();
  }

  /// Check if risk factor is selected
  bool isRiskFactorSelected(String riskFactorId) {
    return _selectedRiskFactorIds.contains(riskFactorId);
  }

  /// Get all selected risk factors
  List<RiskAndSuggestionsItemModel> getAllSelectedRiskFactors() {
    return riskFactorsList.where((factor) => factor.id != null && _selectedRiskFactorIds.contains(factor.id)).toList();
  }

  /// Clear all risk factor selections
  void clearAllRiskFactorSelections() {
    _selectedRiskFactorIds.clear();
    notifyListeners();
  }

  /// Fetch risk factors based on selected symptoms
  Future<void> fetchRiskFactors({
    Function()? onSuccess,
    Function(String)? onError,
  }) async {
    // Get all selected symptoms
    final selectedSymptoms = getAllSelectedSymptoms();

    if (selectedSymptoms.isEmpty) {
      if (onError != null) {
        onError('No symptoms selected');
      }
      return;
    }

    // Validate user info
    if (_selectedAge == null || _selectedGender == null) {
      if (onError != null) {
        onError('User information is incomplete');
      }
      return;
    }

    // Extract symptom IDs
    List<String> evidenceIds = selectedSymptoms.where((s) => s.id != null).map((s) => s.id!).toList();

    await getRiskFactors(
      age: _selectedAge!,
      gender: _getGenderAsInt(_selectedGender),
      evidenceIds: evidenceIds,
      sessionId: currentSessionId,
      language: appState.isArabic() ? 'ar' : 'en',
      onSuccess: (response) {
        if (onSuccess != null) {
          onSuccess();
        }
      },
      onError: (error) {
        if (onError != null) {
          onError(error);
        }
      },
    );
  }

  /// Call Risk Factors API
  Future<void> getRiskFactors({
    required int age,
    required int gender,
    required String sessionId,
    required List<String> evidenceIds,
    required String language,
    Function(RiskAndSuggestionsResponseModel)? onSuccess,
    Function(String)? onError,
  }) async {
    isRiskFactorsLoading = true;
    notifyListeners();

    final result = await symptomsCheckerRepo.getRiskFactors(
      age: age,
      gender: gender,
      evidenceIds: evidenceIds,
      language: language,
      sessionId: sessionId,
      userSessionToken: currentSessionAuthToken,
    );

    result.fold(
      (failure) async {
        isRiskFactorsLoading = false;
        notifyListeners();
        await errorHandlerService.handleError(failure: failure);
        if (onError != null) {
          onError(failure.toString());
        }
      },
      (apiResponse) {
        isRiskFactorsLoading = false;
        if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
          riskFactorsResponse = apiResponse.data;

          if (riskFactorsResponse != null && riskFactorsResponse!.dataDetails != null) {
            RiskAndSuggestionsItemModel riskFactorItem = RiskAndSuggestionsItemModel(
              id: "not_applicable",
              commonName: "Not Applicable",
              name: "Not Applicable",
              commonNameAr: "لا ينطبق",
              nameAr: "لا ينطبق",
              language: appState.isArabic() ? 'ar' : 'en',
              type: null,
            );
            riskFactorsResponse!.dataDetails!.add(riskFactorItem);
          }

          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse.data!);
          }
        } else {
          notifyListeners();
          if (onError != null) {
            onError(apiResponse.errorMessage ?? 'Failed to fetch risk factors');
          }
        }
      },
    );
  }

  // Suggestions Methods

  /// Toggle suggestions selection
  void toggleSuggestionsSelection(String suggestionsId) {
    if (suggestionsId == "not_applicable") {
      // "Not applicable" is mutually exclusive:  if selected, clear all others
      if (_selectedSuggestionsIds.contains(suggestionsId)) {
        _selectedSuggestionsIds.remove(suggestionsId);
      } else {
        _selectedSuggestionsIds
          ..clear()
          ..add(suggestionsId);
      }
    } else {
      _selectedSuggestionsIds.remove("not_applicable");
      if (!_selectedSuggestionsIds.add(suggestionsId)) {
        _selectedSuggestionsIds.remove(suggestionsId);
      }
    }

    notifyListeners();
  }

  /// Check if risk factor is selected
  bool isSuggestionsSelected(String riskFactorId) {
    return _selectedSuggestionsIds.contains(riskFactorId);
  }

  /// Get all selected risk factors
  List<RiskAndSuggestionsItemModel> getAllSelectedSuggestions() {
    return suggestionsList.where((factor) => factor.id != null && _selectedSuggestionsIds.contains(factor.id)).toList();
  }

  /// Clear all risk factor selections
  void clearAllSuggestionsSelections() {
    _selectedSuggestionsIds.clear();
    notifyListeners();
  }

  /// Get all evidence IDs (symptoms + risk factors + suggestions) for triage/diagnosis
  List<String> getAllEvidenceIds() {
    List<String> evidenceIds = [];

    // Add selected symptoms
    final selectedSymptoms = getAllSelectedSymptoms();
    evidenceIds.addAll(selectedSymptoms.where((s) => s.id != null).map((s) => s.id!));

    // Add selected risk factors (excluding "not_applicable")
    final selectedRiskFactors = getAllSelectedRiskFactors();
    evidenceIds.addAll(selectedRiskFactors.where((rf) => rf.id != null && rf.id != "not_applicable").map((rf) => rf.id!));

    // Add selected suggestions (excluding "not_applicable")
    final selectedSuggestions = getAllSelectedSuggestions();
    evidenceIds.addAll(selectedSuggestions.where((s) => s.id != null && s.id != "not_applicable").map((s) => s.id!));

    return evidenceIds;
  }

  /// Get all evidence with their sources based on selection step
  /// Source values:
  /// - "initial" for symptoms (used in GetRiskFactors)
  /// - "red_flags" for risk factors (used in GetSuggestions)
  /// - "suggest" for suggestions (used in GetDiagnosis)
  List<Map<String, dynamic>> getAllEvidenceWithSources({String defaultSource = "initial"}) {
    List<Map<String, dynamic>> evidenceList = [];

    // Add selected symptoms with source "initial"
    final selectedSymptoms = getAllSelectedSymptoms();
    for (var symptom in selectedSymptoms.where((s) => s.id != null)) {
      evidenceList.add({
        "id": symptom.id!,
        "source": "initial",
      });
    }

    // Add selected risk factors with source "red_flags" (excluding "not_applicable")
    final selectedRiskFactors = getAllSelectedRiskFactors();
    for (var riskFactor in selectedRiskFactors.where((rf) => rf.id != null && rf.id != "not_applicable")) {
      evidenceList.add({
        "id": riskFactor.id!,
        "source": "red_flags",
      });
    }

    // Add selected suggestions with source "suggest" (excluding "not_applicable")
    final selectedSuggestions = getAllSelectedSuggestions();
    for (var suggestion in selectedSuggestions.where((s) => s.id != null && s.id != "not_applicable")) {
      evidenceList.add({
        "id": suggestion.id!,
        "source": "suggest",
      });
    }

    return evidenceList;
  }

  /// Fetch risk factors based on selected symptoms
  Future<void> fetchSuggestions({
    Function()? onSuccess,
    Function(String)? onError,
  }) async {
    // Get all selected symptoms
    final selectedSymptoms = getAllSelectedSymptoms();

    if (selectedSymptoms.isEmpty) {
      if (onError != null) {
        onError('No symptoms selected');
      }
      return;
    }

    // Validate user info
    if (_selectedAge == null || _selectedGender == null) {
      if (onError != null) {
        onError('User information is incomplete');
      }
      return;
    }

    // Build evidence list with proper sources
    List<Map<String, dynamic>> evidenceList = [];

    // Add selected symptoms with source "initial"
    for (var symptom in selectedSymptoms.where((s) => s.id != null)) {
      evidenceList.add({
        "id": symptom.id!,
        "source": "initial",
      });
    }

    // Get selected risk factors and add with source "red_flags"
    final selectedRisks = getAllSelectedRiskFactors();
    for (var riskFactor in selectedRisks.where((rf) => rf.id != null && rf.id != "not_applicable")) {
      evidenceList.add({
        "id": riskFactor.id!,
        "source": "red_flags",
      });
    }

    await getSuggestions(
      age: _selectedAge!,
      gender: _getGenderAsInt(_selectedGender),
      evidenceList: evidenceList,
      language: appState.isArabic() ? 'ar' : 'en',
      onSuccess: (response) {
        if (onSuccess != null) {
          onSuccess();
        }
      },
      onError: (error) {
        if (onError != null) {
          onError(error);
        }
      },
    );
  }

  /// Call Suggestions API
  Future<void> getSuggestions({
    required int age,
    required int gender,
    required List<Map<String, dynamic>> evidenceList,
    required String language,
    Function(RiskAndSuggestionsResponseModel)? onSuccess,
    Function(String)? onError,
  }) async {
    isSuggestionsLoading = true;
    notifyListeners();

    final result = await symptomsCheckerRepo.getSuggestions(
      age: age,
      gender: gender,
      evidenceList: evidenceList,
      language: language,
      sessionId: currentSessionId,
      userSessionToken: currentSessionAuthToken,
    );

    result.fold(
      (failure) async {
        isSuggestionsLoading = false;
        notifyListeners();
        await errorHandlerService.handleError(failure: failure);
        if (onError != null) {
          onError(failure.toString());
        }
      },
      (apiResponse) {
        isSuggestionsLoading = false;
        if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
          suggestionsResponse = apiResponse.data;

          if (suggestionsResponse != null && suggestionsResponse!.dataDetails != null) {
            RiskAndSuggestionsItemModel riskFactorItem = RiskAndSuggestionsItemModel(
              id: "not_applicable",
              commonName: "Not Applicable",
              name: "Not Applicable",
              commonNameAr: "لا ينطبق",
              nameAr: "لا ينطبق",
              language: appState.isArabic() ? 'ar' : 'en',
              type: null,
            );
            suggestionsResponse!.dataDetails!.add(riskFactorItem);
          }

          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse.data!);
          }
        } else {
          notifyListeners();
          if (onError != null) {
            onError(apiResponse.errorMessage ?? 'Failed to fetch risk factors');
          }
        }
      },
    );
  }

  /// Call Diagnosis API for Triage - This is called iteratively until shouldStop is true
  Future<void> getDiagnosisForTriage({
    required int age,
    required int gender,
    required List<Map<String, dynamic>> initialEvidenceList, // Evidence with sources (initial, red_flags, suggest)
    List<Map<String, String>>? triageEvidence, // Triage-specific evidence (id, choice_id, source=triage)
    required String language,
    Function(TriageDataDetails)? onSuccess,
    Function(String)? onError,
    bool isGoingBack = false, // Flag to indicate if we're going back in history
  }) async {
    // Save current question and evidence to history BEFORE making new API call
    // (but only if we're moving forward, not going back)
    if (!isGoingBack && triageDataDetails != null) {
      _triageQuestionHistory.add(triageDataDetails!);
      _triageEvidenceHistory.add(List<Map<String, String>>.from(_triageEvidenceList));
    }

    isTriageDiagnosisLoading = true;
    notifyListeners();

    final result = await symptomsCheckerRepo.getDiagnosisForTriage(
      age: age,
      gender: gender,
      initialEvidenceList: initialEvidenceList,
      triageEvidence: triageEvidence,
      language: language,
      sessionId: currentSessionId,
      userSessionToken: currentSessionAuthToken,
    );

    result.fold(
      (failure) async {
        isTriageDiagnosisLoading = false;
        notifyListeners();
        await errorHandlerService.handleError(failure: failure);
        if (onError != null) {
          onError(failure.toString());
        }
      },
      (apiResponse) {
        isTriageDiagnosisLoading = false;
        if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
          triageDataDetails = apiResponse.data;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse.data!);
          }
        } else {
          notifyListeners();
          if (onError != null) {
            onError(apiResponse.errorMessage ?? 'Failed to fetch diagnosis');
          }
        }
      },
    );
  }

  /// Convenience method to start or continue the triage process
  /// This automatically uses all selected evidence (symptoms + risk factors + suggestions)
  Future<void> startOrContinueTriage({
    Function()? onSuccess,
    Function(String)? onError,
  }) async {
    // Validate user info
    if (_selectedAge == null || _selectedGender == null) {
      if (onError != null) {
        onError('User information is incomplete');
      }
      return;
    }

    // Get all evidence with sources
    final evidenceList = getAllEvidenceWithSources();

    if (evidenceList.isEmpty) {
      if (onError != null) {
        onError('No evidence selected');
      }
      return;
    }

    await getDiagnosisForTriage(
      age: _selectedAge!,
      gender: _getGenderAsInt(_selectedGender),
      initialEvidenceList: evidenceList,
      language: appState.isArabic() ? 'ar' : 'en',
      onSuccess: (response) {
        if (onSuccess != null) {
          onSuccess();
        }
      },
      onError: (error) {
        if (onError != null) {
          onError(error);
        }
      },
    );
  }

  /// Select a triage choice option (for backward compatibility with single-item questions)
  void selectTriageChoice(int choiceIndex) {
    _selectedTriageChoiceIndex = choiceIndex;
    notifyListeners();
  }

  /// Select a choice for a specific item (for multi-item questions)
  void selectTriageChoiceForItem(String itemId, int choiceIndex) {
    // Type 1: Single selection mode - only one ITEM can be selected (choice is always "Yes")
    if (isTriageQuestionSingleSelection) {
      // If same item clicked again, deselect it
      if (_selectedSingleItemId == itemId) {
        _selectedSingleItemId = null;
        _selectedSingleChoiceIndex = null;
      } else {
        // Select new item, clear previous selection
        _selectedSingleItemId = itemId;
        // For type=1, we don't use choiceIndex from UI, we'll find "Yes" choice in the API call
        _selectedSingleChoiceIndex = 0; // Placeholder, actual Yes choice will be found later
      }
    } else {
      // Type 2: Multi-item selection mode - each item can have one selected option
      _selectedTriageChoicesByItemId[itemId] = choiceIndex;
    }
    notifyListeners();
  }

  /// Reset triage choice selection and increment question count
  void resetTriageChoice() {
    _selectedTriageChoiceIndex = null;
    _selectedTriageChoicesByItemId.clear();
    _selectedSingleItemId = null;
    _selectedSingleChoiceIndex = null;
    _triageQuestionCount++; // Increment question count
    notifyListeners();
  }

  /// Add triage evidence in the proper format
  void addTriageEvidence(String itemId, String choiceId) {
    _triageEvidenceList.add({
      "id": itemId,
      "choice_id": choiceId,
      "source": "suggest",
    });
    notifyListeners();
  }

  /// Get all triage evidence
  List<Map<String, String>> getTriageEvidence() {
    return List.from(_triageEvidenceList);
  }

  /// Clear triage evidence
  void clearTriageEvidence() {
    _triageEvidenceList.clear();
    notifyListeners();
  }

  /// Go back to previous triage question
  /// Returns true if successfully went back, false if already at first question
  bool goBackToPreviousTriageQuestion() {
    if (_triageQuestionHistory.isEmpty) {
      return false; // Already at first question
    }

    // Pop the last question from history
    final previousQuestion = _triageQuestionHistory.removeLast();
    final previousEvidence = _triageEvidenceHistory.removeLast();

    // Restore the previous question
    triageDataDetails = previousQuestion;

    // Restore the previous evidence state
    _triageEvidenceList.clear();
    _triageEvidenceList.addAll(previousEvidence);

    // Decrement question count
    if (_triageQuestionCount > 0) {
      _triageQuestionCount--;
    }

    // Clear current selections
    _selectedTriageChoiceIndex = null;
    _selectedTriageChoicesByItemId.clear();
    _selectedSingleItemId = null;
    _selectedSingleChoiceIndex = null;

    notifyListeners();
    return true;
  }

  void reset() {
    _currentView = BodyView.front;
    _selectedOrganIds.clear();
    _selectedSymptomsByOrgan.clear();
    _selectedRiskFactorIds.clear();
    _selectedSuggestionsIds.clear();
    _triageEvidenceList.clear();
    _selectedTriageChoicesByItemId.clear();
    _triageQuestionCount = 0; // Reset question count
    _triageQuestionHistory.clear(); // Clear question history
    _triageEvidenceHistory.clear(); // Clear evidence history
    _currentZoomScale = 1.0; // Reset zoom scale
    _symptomSearchQuery = ''; // Reset search query
    _filteredOrganSymptomsResults.clear(); // Clear filtered results
    bodySymptomResponse = null;
    riskFactorsResponse = null;
    suggestionsResponse = null;
    triageDataDetails = null;
    isTriageDiagnosisLoading = false;
    _selectedTriageChoiceIndex = null;
    _selectedSingleItemId = null;
    _selectedSingleChoiceIndex = null;
    _isBottomSheetExpanded = false;
    _tooltipTimer?.cancel();
    _tooltipOrganId = null;
    isBookingFromSymptomsChecker = false; // Reset booking flag
    // Reset user info flow
    _userInfoCurrentPage = 0;
    _isSinglePageEditMode = false;
    _selectedGender = null;
    _dateOfBirth = null;
    _selectedAge = null;
    _selectedHeight = 170;
    _isHeightCm = true;
    _selectedWeight = 60;
    _isWeightKg = true;
    notifyListeners();
  }

  /// Clear user selections (organs, symptoms, risk factors, questions) but keep results
  /// This is useful when user reaches results page and we want to prevent going back to edit selections
  void clearSelectionsKeepResults() {
    _selectedOrganIds.clear();
    _selectedSymptomsByOrgan.clear();
    _selectedRiskFactorIds.clear();
    _selectedSuggestionsIds.clear();
    _triageEvidenceList.clear();
    _triageQuestionHistory.clear(); // Clear question history
    _triageEvidenceHistory.clear(); // Clear evidence history
    _selectedTriageChoicesByItemId.clear();
    _selectedSingleItemId = null;
    _selectedSingleChoiceIndex = null;
    _symptomSearchQuery = '';
    _filteredOrganSymptomsResults.clear();
    _isBottomSheetExpanded = false;
    _tooltipTimer?.cancel();
    _tooltipOrganId = null;
    // Keep: bodySymptomResponse, riskFactorsResponse, suggestionsResponse, triageDataDetails, user info, booking flag
    notifyListeners();
  }

  /// Clear selections when reaching possible conditions screen
  /// This clears organs, symptoms, risk factors, suggestions, and questions
  void clearSelectionsForPossibleConditions() {
    _selectedOrganIds.clear();
    _selectedSymptomsByOrgan.clear();
    _selectedRiskFactorIds.clear();
    _selectedSuggestionsIds.clear();
    _triageEvidenceList.clear();
    _triageQuestionHistory.clear();
    _triageEvidenceHistory.clear();
    _selectedTriageChoicesByItemId.clear();
    _selectedSingleItemId = null;
    _selectedSingleChoiceIndex = null;
    _triageQuestionCount = 0;
    _symptomSearchQuery = '';
    _filteredOrganSymptomsResults.clear();
    _isBottomSheetExpanded = false;
    _tooltipTimer?.cancel();
    _tooltipOrganId = null;
    notifyListeners();
  }

  // User Info Flow Methods

  /// Set current page in user info flow
  void setUserInfoPage(int page, {bool isSinglePageEdit = false}) {
    _userInfoCurrentPage = page;
    _isSinglePageEditMode = isSinglePageEdit;
    notifyListeners();
  }

  /// Set single page edit mode
  void setSinglePageEditMode(bool isSingleEdit) {
    _isSinglePageEditMode = isSingleEdit;
    notifyListeners();
  }

  /// Navigate to next page in user info flow
  void nextUserInfoPage() {
    if (_userInfoCurrentPage < 3) {
      _userInfoCurrentPage++;
      notifyListeners();
    }
  }

  /// Navigate to previous page in user info flow
  void previousUserInfoPage() {
    if (_userInfoCurrentPage > 0) {
      _userInfoCurrentPage--;
      notifyListeners();
    }
  }

  /// Set selected gender
  void setGender(String gender) {
    _selectedGender = gender;
    notifyListeners();
  }

  /// Set selected age
  void setAge(int age) {
    _selectedAge = age;
    notifyListeners();
  }

  /// Set date of birth
  void setDateOfBirth(DateTime dateOfBirth) {
    _dateOfBirth = dateOfBirth;
    // Calculate age from date of birth
    final now = DateTime.now();
    int age = now.year - dateOfBirth.year;
    if (now.month < dateOfBirth.month || (now.month == dateOfBirth.month && now.day < dateOfBirth.day)) {
      age--;
    }
    _selectedAge = age;
    notifyListeners();
  }

  /// Set selected height
  void setHeight(double height, bool isCm) {
    _selectedHeight = height;
    _isHeightCm = isCm;
    notifyListeners();
  }

  /// Set selected weight
  void setWeight(double weight, bool isKg) {
    _selectedWeight = weight;
    _isWeightKg = isKg;
    notifyListeners();
  }

  /// Check if user info page is last
  bool get isUserInfoLastPage => _userInfoCurrentPage == 3;

  bool get isUserInfoFirstPage => _userInfoCurrentPage == 0;

  /// Check if current user info page has valid selection
  bool get isCurrentUserInfoPageValid {
    switch (_userInfoCurrentPage) {
      case 0: // Gender page
        return _selectedGender != null && _selectedGender!.isNotEmpty;
      case 1: // Age/Birth date page
        return _dateOfBirth != null || (_selectedAge != null && _selectedAge! > 0);
      case 2: // Height page
        return _selectedHeight > 0;
      case 3: // Weight page
        return _selectedWeight > 0;
      default:
        return false;
    }
  }

  /// Validate and submit user info
  Map<String, dynamic> getUserInfoData() {
    return {
      'gender': _selectedGender,
      'dateOfBirth': _dateOfBirth?.toIso8601String(),
      'age': _selectedAge,
      'height': _selectedHeight,
      'heightUnit': _isHeightCm ? 'cm' : 'ft',
      'weight': _selectedWeight,
      'weightUnit': _isWeightKg ? 'kg' : 'lbs',
    };
  }

  // User Consent Methods

  bool isTermsAccepted = false;
  bool isPrivacyAccepted = false;

  /// Toggle terms acceptance
  void toggleTermsAcceptance() {
    isTermsAccepted = !isTermsAccepted;
    notifyListeners();
  }

  /// Toggle privacy policy acceptance
  void togglePrivacyAcceptance() {
    isPrivacyAccepted = !isPrivacyAccepted;
    notifyListeners();
  }

  void setTermsAcceptance(bool value) {
    isTermsAccepted = value;
    notifyListeners();
  }

  /// Toggle privacy policy acceptance
  void setPrivacyAcceptance(bool value) {
    isPrivacyAccepted = value;
    notifyListeners();
  }

  Future<void> getSymptomsUserDetails({
    required String userName,
    required String password,
    String? fileNo,
    Function()? onSuccess,
    Function(String)? onError,
  }) async {
    isBodySymptomsLoading = true;
    notifyListeners();
    final result = await symptomsCheckerRepo.getUserDetails(
      userName: userName,
      password: password,
      fileNo: fileNo,
    );

    result.fold(
      (failure) async {
        isBodySymptomsLoading = false;
        notifyListeners();
        await errorHandlerService.handleError(failure: failure);
        if (onError != null) {
          onError(failure.toString());
        }
      },
      (apiResponse) {
        isBodySymptomsLoading = false;
        if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
          symptomsUserDetailsResponseModel = apiResponse.data;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess();
          }
        } else {
          notifyListeners();
          if (onError != null) {
            onError(apiResponse.errorMessage ?? 'Failed to fetch symptoms');
          }
        }
      },
    );
  }

  Future<void> getBodySymptomsByName({
    required List<String> organNames,
    Function(BodySymptomResponseModel)? onSuccess,
    Function(String)? onError,
  }) async {
    isBodySymptomsLoading = true;
    notifyListeners();

    final result = await symptomsCheckerRepo.getBodySymptomsByName(
      organNames: organNames,
      userSessionToken: currentSessionAuthToken,
      gender: _getGenderAsInt(selectedGender ?? "Male"),
    );

    result.fold(
      (failure) async {
        isBodySymptomsLoading = false;
        notifyListeners();
        await errorHandlerService.handleError(failure: failure);
        if (onError != null) {
          onError(failure.toString());
        }
      },
      (apiResponse) {
        isBodySymptomsLoading = false;
        if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
          bodySymptomResponse = apiResponse.data;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse.data!);
          }
        } else {
          notifyListeners();
          if (onError != null) {
            onError(apiResponse.errorMessage ?? 'Failed to fetch symptoms');
          }
        }
      },
    );
  }

  Future<void> getClinicConditionsFromCategory({
    required String categoryName,
    Function(dynamic)? onSuccess,
    Function(String)? onError,
  }) async {
    clinicDetailsList.clear();
    notifyListeners();

    final result = await symptomsCheckerRepo.getClinicDetails(
      categoryName: categoryName,
      language: appState.isArabic() ? 'ar' : 'en',
      userSessionToken: currentSessionAuthToken,
    );

    result.fold(
      (failure) async {
        await errorHandlerService.handleError(failure: failure);
        if (onError != null) {
          onError(failure.toString());
        }
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
          clinicDetailsList = apiResponse.data!;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse.data!);
          }
        } else {
          notifyListeners();
          if (onError != null) {
            onError(apiResponse.errorMessage ?? 'Failed to fetch clinic details');
          }
        }
      },
    );
  }

  /// Schedule appointment for symptoms checker
  Future<void> saveAppointmentDetailsForSymptomsChecker({
    required String fileNo,
    required String appointmentNo,
    required String doctorId,
    required String appointmentDate,
    required String mobileNumber,
    required int projectId,
    required int clinicId,
    Function(ScheduleAppointmentResponseModel)? onSuccess,
    Function(String)? onError,
  }) async {
    isScheduleAppointmentLoading = true;
    notifyListeners();

    // Import the request model at the top of the file
    final request = ScheduleAppointmentRequestModel(
      generalId: currentSessionId,
      fileNo: fileNo,
      appointmentNo: appointmentNo,
      doctorId: doctorId,
      appointmentDate: appointmentDate,
      mobileNumber: mobileNumber,
      projectId: projectId,
      clinicId: clinicId,
    );

    final result = await symptomsCheckerRepo.saveAppointmentDetailsForSymptomsChecker(
      request: request,
      userSessionToken: currentSessionAuthToken,
    );

    result.fold(
      (failure) async {
        isScheduleAppointmentLoading = false;
        isBookingFromSymptomsChecker = false; // Reset flag on error
        notifyListeners();
        await errorHandlerService.handleError(failure: failure);
        if (onError != null) {
          onError(failure.toString());
        }
      },
      (apiResponse) {
        isScheduleAppointmentLoading = false;
        if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
          isBookingFromSymptomsChecker = false; // Reset flag on success
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse.data!);
          }
        } else {
          isBookingFromSymptomsChecker = false; // Reset flag on error
          notifyListeners();
          if (onError != null) {
            onError(apiResponse.errorMessage ?? 'Failed to schedule appointment');
          }
        }
      },
    );
  }

  /// Get Rationale for symptoms
  /// This API shows which symptoms and conditions are being considered
  Future<void> fetchRationale({
    required List<Map<String, dynamic>> evidence,
    Function(RationaleResponseModel)? onSuccess,
    Function(String)? onError,
  }) async {
    // Validate user info
    if (_selectedAge == null || _selectedGender == null) {
      if (onError != null) {
        onError('User information is incomplete');
      }
      return;
    }

    isRationaleLoading = true;
    notifyListeners();

    final result = await symptomsCheckerRepo.getRationale(
      age: _selectedAge!,
      gender: _getGenderAsInt(_selectedGender),
      evidence: evidence,
      language: appState.isArabic() ? 'ar' : 'en',
      generalId: currentSessionId,
      userSessionToken: currentSessionAuthToken,
    );

    result.fold(
      (failure) async {
        isRationaleLoading = false;
        notifyListeners();
        await errorHandlerService.handleError(failure: failure);
        if (onError != null) {
          onError(failure.toString());
        }
      },
      (apiResponse) {
        isRationaleLoading = false;
        if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
          rationaleResponse = apiResponse.data;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse.data!);
          }
        } else {
          notifyListeners();
          if (onError != null) {
            onError(apiResponse.errorMessage ?? 'Failed to fetch rationale');
          }
        }
      },
    );
  }

  /// Get Triage Level for symptoms
  /// This API determines the urgency level and serious symptoms
  Future<void> fetchTriageLevel({
    required List<Map<String, dynamic>> evidence,
    Function(TriageLevelResponseModel)? onSuccess,
    Function(String)? onError,
  }) async {
    // Validate user info
    if (_selectedAge == null || _selectedGender == null) {
      if (onError != null) {
        onError('User information is incomplete');
      }
      return;
    }

    isTriageLevelLoading = true;
    notifyListeners();

    final result = await symptomsCheckerRepo.getTriage(
      age: _selectedAge!,
      gender: _getGenderAsInt(_selectedGender),
      evidence: evidence,
      language: appState.isArabic() ? 'ar' : 'en',
      generalId: currentSessionId,
      userSessionToken: currentSessionAuthToken,
    );

    result.fold(
      (failure) async {
        isTriageLevelLoading = false;
        notifyListeners();
        await errorHandlerService.handleError(failure: failure);
        if (onError != null) {
          onError(failure.toString());
        }
      },
      (apiResponse) {
        isTriageLevelLoading = false;
        if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
          triageLevelResponse = apiResponse.data;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse.data!);
          }
        } else {
          notifyListeners();
          if (onError != null) {
            onError(apiResponse.errorMessage ?? 'Failed to fetch triage level');
          }
        }
      },
    );
  }

  /// Get Explanations for a specific condition
  /// This API explains why a condition was suggested based on evidence
  Future<void> fetchExplanations({
    required String targetConditionId,
    required List<Map<String, dynamic>> evidence,
    Function(ExplanationsResponseModel)? onSuccess,
    Function(String)? onError,
  }) async {
    // Validate user info
    if (_selectedAge == null || _selectedGender == null) {
      if (onError != null) {
        onError('User information is incomplete');
      }
      return;
    }

    isExplanationsLoading = true;
    notifyListeners();

    final result = await symptomsCheckerRepo.getExplanations(
      age: _selectedAge!,
      gender: _getGenderAsInt(_selectedGender),
      evidence: evidence,
      language: appState.isArabic() ? 'ar' : 'en',
      target: targetConditionId,
      generalId: currentSessionId,
      userSessionToken: currentSessionAuthToken,
    );

    result.fold(
      (failure) async {
        isExplanationsLoading = false;
        notifyListeners();
        await errorHandlerService.handleError(failure: failure);
        if (onError != null) {
          onError(failure.toString());
        }
      },
      (apiResponse) {
        isExplanationsLoading = false;
        if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
          explanationsResponse = apiResponse.data;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse.data!);
          }
        } else {
          notifyListeners();
          if (onError != null) {
            onError(apiResponse.errorMessage ?? 'Failed to fetch explanations');
          }
        }
      },
    );
  }

  @override
  void dispose() {
    _tooltipTimer?.cancel();
    super.dispose();
  }
}
