import 'dart:convert';
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/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/request_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/common/models/family_file_request.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_repo.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/patient_medical_response_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/patient_sickleave_response_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/patient_vaccine_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';

class MedicalFileViewModel extends ChangeNotifier {
  int selectedTabIndex = 0;
  bool isPatientVaccineListLoading = false;
  bool isPatientSickLeaveListLoading = false;
  bool isPatientSickLeavePDFLoading = false;
  bool isPatientMedicalReportsListLoading = false;

  MedicalFileRepo medicalFileRepo;
  ErrorHandlerService errorHandlerService;

  List<PatientVaccineResponseModel> patientVaccineList = [];
  List<PatientSickLeavesResponseModel> patientSickLeaveList = [];

  List<PatientMedicalReportResponseModel> patientMedicalReportList = [];

  List<PatientMedicalReportResponseModel> patientMedicalReportRequestedList = [];
  List<PatientMedicalReportResponseModel> patientMedicalReportReadyList = [];
  List<PatientMedicalReportResponseModel> patientMedicalReportCancelledList = [];

  List<PatientAppointmentHistoryResponseModel> patientMedicalReportAppointmentHistoryList = [];
  PatientAppointmentHistoryResponseModel? patientMedicalReportSelectedAppointment;

  List<FamilyFileResponseModelLists> patientFamilyFiles = [];
  List<FamilyFileResponseModelLists> pendingFamilyFiles = [];

  String patientSickLeavePDFBase64 = "";
  String patientMedicalReportPDFBase64 = "";

  int selectedMedicalReportsTabIndex = 0;
  int _selectedFamilyFileTabIndex = 0;

  int get getSelectedFamilyFileTabIndex => _selectedFamilyFileTabIndex;

  set setSelectedFamilyFileTabIndex(int value) {
    if (_selectedFamilyFileTabIndex != value) {
      _selectedFamilyFileTabIndex = value;
      notifyListeners();
    }
  }

  static final DialogService _dialogService = getIt.get<DialogService>();
  final AppState _appState = getIt<AppState>();
  AuthenticationViewModel authVM = getIt.get<AuthenticationViewModel>();

  MedicalFileViewModel({required this.medicalFileRepo, required this.errorHandlerService});

  initMedicalFileProvider() {
    patientMedicalReportAppointmentHistoryList.clear();
    isPatientVaccineListLoading = true;
    isPatientMedicalReportsListLoading = true;
    notifyListeners();
  }

  void onMedicalReportTabChange(int index) {
    selectedMedicalReportsTabIndex = index;
    print("Selected Medical Report Tab Index: $selectedMedicalReportsTabIndex");
    if (index == 0) {
      patientMedicalReportList = patientMedicalReportRequestedList;
    } else if (index == 1) {
      patientMedicalReportList = patientMedicalReportReadyList;
    } else if (index == 2) {
      patientMedicalReportList = patientMedicalReportCancelledList;
    }
    notifyListeners();
  }

  void onFamilyFileTabChange(int index) {
    setSelectedFamilyFileTabIndex = index;
    notifyListeners();
  }

  setIsPatientVaccineListLoading(bool isLoading) {
    isPatientVaccineListLoading = isLoading;
    notifyListeners();
  }

  setIsPatientSickLeavePDFLoading(bool isLoading) {
    isPatientSickLeavePDFLoading = isLoading;
    notifyListeners();
  }

  setIsPatientSickLeaveListLoading(bool val) {
    if (val) {
      patientSickLeaveList.clear();
      patientSickLeavePDFBase64 = "";
    }
    isPatientSickLeaveListLoading = val;
    notifyListeners();
  }

  setIsPatientMedicalReportsLoading(bool val) {
    if (val) {
      onMedicalReportTabChange(0);
      patientMedicalReportList.clear();
      patientMedicalReportPDFBase64 = "";
    }
    isPatientMedicalReportsListLoading = val;
    notifyListeners();
  }

  setSelectedMedicalReportAppointment(PatientAppointmentHistoryResponseModel? val) {
    patientMedicalReportSelectedAppointment = val;
    notifyListeners();
  }

  void onTabChanged(int index) {
    selectedTabIndex = index;
    notifyListeners();
  }

  Future<void> getPatientVaccinesList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    patientVaccineList.clear();
    final result = await medicalFileRepo.getPatientVaccinesList();

    result.fold(
      // (failure) async => await errorHandlerService.handleError(
      //   failure: failure,
      //   onOkPressed: () {
      //     onError!(failure.message);
      //   },
      // ),
      (failure) async {
        // onError!(failure.message);
        isPatientVaccineListLoading = false;
        notifyListeners();
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          patientVaccineList = apiResponse.data!;
          isPatientVaccineListLoading = false;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getPatientSickLeaveList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    patientSickLeaveList.clear();
    final result = await medicalFileRepo.getPatientSickLeavesList();

    result.fold(
      // (failure) async => await errorHandlerService.handleError(
      //   failure: failure,
      //   onOkPressed: () {
      //     onError!(failure.message);
      //   },
      // ),
      (failure) async {
        isPatientSickLeaveListLoading = false;
        notifyListeners();
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          patientSickLeaveList = apiResponse.data!;
          isPatientSickLeaveListLoading = false;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getPatientSickLeavePDF(PatientSickLeavesResponseModel patientSickLeavesResponseModel, AuthenticatedUser authenticatedUser,
      {Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await medicalFileRepo.getPatientSickLeavePDF(patientSickLeavesResponseModel, authenticatedUser);

    result.fold(
      (failure) async => await errorHandlerService.handleError(
        failure: failure,
        onOkPressed: () {
          onError!(failure.message);
        },
      ),
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          patientSickLeavePDFBase64 = apiResponse.data!;
          isPatientSickLeaveListLoading = false;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getPatientMedicalReportList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    patientMedicalReportList.clear();
    final result = await medicalFileRepo.getPatientMedicalReportsList();

    result.fold(
      (failure) async => await errorHandlerService.handleError(
        failure: failure,
        onOkPressed: () {
          onError!(failure.message);
        },
      ),
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          patientMedicalReportList = apiResponse.data!;
          if (patientMedicalReportList.isNotEmpty) {
            patientMedicalReportRequestedList = patientMedicalReportList.where((element) => element.status == 1).toList();
            patientMedicalReportReadyList = patientMedicalReportList.where((element) => element.status == 2).toList();
            patientMedicalReportCancelledList = patientMedicalReportList.where((element) => element.status == 4).toList();
          }
          onMedicalReportTabChange(0);
          isPatientMedicalReportsListLoading = false;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getPatientMedicalReportPDF(PatientMedicalReportResponseModel patientMedicalReportResponseModel, AuthenticatedUser authenticatedUser,
      {Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await medicalFileRepo.getPatientMedicalReportPDF(patientMedicalReportResponseModel, authenticatedUser);

    result.fold(
      (failure) async => await errorHandlerService.handleError(
        failure: failure,
        onOkPressed: () {
          onError!(failure.message);
        },
      ),
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          patientMedicalReportPDFBase64 = apiResponse.data!;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getFamilyFiles({int? status, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await medicalFileRepo.getPatientFamilyFiles(status, _appState.getSuperUserID != null ? _appState.getSuperUserID! : _appState.getAuthenticatedUser()!.patientId!);

    result.fold(
      (failure) async => await errorHandlerService.handleError(
        failure: failure,
        onOkPressed: () {
          onError!(failure.message);
        },
      ),
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          if (apiResponse.data != null) {
            // Add current user as the first active family file
            final currentUser = _appState.getAuthenticatedUser()!;
            final currentUserFamilyFile = FamilyFileResponseModelLists(
              patientId: currentUser.patientId,
              patientName: '${currentUser.firstName!} ${currentUser.lastName!}',
              isActive: true,
              gender: currentUser.gender!,
              responseId: currentUser.patientId,
              age: currentUser.age,
              mobileNumber: currentUser.mobileNumber,
              patientIdenficationNumber: currentUser.patientIdentificationNo,
              emaiLAddress: currentUser.emailAddress,
              genderDescription: currentUser.genderDescription,
            );

            // Clear and start fresh with current user
            patientFamilyFiles.clear();
            patientFamilyFiles.add(currentUserFamilyFile);

            final List<FamilyFileResponseModelLists> activeFamilyFiles = [];
            final List<FamilyFileResponseModelLists> pendingFamilyFiles = [];

            for (var element in apiResponse.data!) {
              if (element.status == null) {
                continue;
              }

              final isPending = element.status == FamilyFileEnum.pending.toInt || element.status == FamilyFileEnum.rejected.toInt;
              final isActive = element.status == FamilyFileEnum.active.toInt;

              if (!isPending && !isActive) {
                continue;
              }

              final familyFile = FamilyFileResponseModelLists(
                id: element.id,
                patientId: element.patientId,
                patientName: element.patientName!,
                isActive: element.isActive,
                gender: element.gender!,
                responseId: element.responseId,
                mobileNumber: element.mobileNumber,
                age: element.age,
                patientIdenficationNumber: element.patientIdenficationNumber,
                relationship: element.relationship,
                relationshipId: element.relationshipId,
                relationshipN: element.relationshipN,
                status: element.status,
                statusDescription: element.statusDescription,
                createdOn: element.createdOn,
                editedOn: element.editedOn,
                patientDataVerified: element.patientDataVerified,
                regionId: element.regionId,
                familyRegionId: element.familyRegionId,
                genderDescription: element.genderDescription,
                genderImage: element.genderImage,
                emaiLAddress: element.emaiLAddress,
              );

              if (isPending) {
                familyFile.isRequestFromMySide = true;
                pendingFamilyFiles.add(familyFile);
              }
              if (isActive) {
                activeFamilyFiles.add(familyFile);
              }
            }

            for (var activeFile in activeFamilyFiles) {
              if (!patientFamilyFiles.any((e) => e.responseId == activeFile.responseId)) {
                patientFamilyFiles.add(activeFile);
              }
            }

            this.pendingFamilyFiles.clear();
            this.pendingFamilyFiles.addAll(pendingFamilyFiles);
          }

          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getAllPendingRecordsByResponseId() async {
    AppState appState = getIt<AppState>();
    final result = await medicalFileRepo.getAllPendingRecordsByResponseId(request: {'ResponseID': appState.getAuthenticatedUser()!.patientId ?? "0", "Status": 2});

    result.fold(
      // (failure) async => await errorHandlerService.handleError(failure: failure),
      (failure) async {
        log("Error in fetching pending family files: ${failure.message}");
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          if (apiResponse.data != null) {
            final List<FamilyFileResponseModelLists> tempPendingFamilyFiles = [];
            for (var element in apiResponse.data!) {
              if (element.status != null && element.status == FamilyFileEnum.pending.toInt || element.status == FamilyFileEnum.active.toInt) {
                tempPendingFamilyFiles.add(FamilyFileResponseModelLists(
                    id: element.id,
                    patientId: element.patientId,
                    patientName: element.patientName!,
                    isActive: element.status,
                    gender: element.gender,
                    responseId: element.patientId,
                    mobileNumber: element.mobileNumber,
                    age: element.age,
                    patientIdenficationNumber: element.patientIdenficationNumber,
                    relationship: element.relationship,
                    relationshipId: element.relationshipId,
                    relationshipN: element.relationshipN,
                    status: element.status,
                    statusDescription: element.statusDescription,
                    createdOn: element.createdOn,
                    editedOn: element.editedOn,
                    patientDataVerified: element.patientDataVerified,
                    regionId: element.regionId,
                    familyRegionId: element.familyRegionId,
                    genderDescription: element.genderDescription,
                    genderImage: element.genderImage,
                    emaiLAddress: element.emaiLAddress));
              }
            }
            // pendingFamilyFiles.addAll(tempPendingFamilyFiles.where((element) => !pendingFamilyFiles.any((e) => e.responseId == element.responseId)));
            pendingFamilyFiles.addAll(tempPendingFamilyFiles.where((element) => !pendingFamilyFiles.any((e) => e.patientId == element.patientId)));
          }
          notifyListeners();
        }
      },
    );
  }

  Future<void> switchFamilyFiles({Function(dynamic)? onSuccess, int? responseID, int? patientID, String? phoneNumber, Function(String)? onError}) async {
    authVM.phoneNumberController.text = phoneNumber!.startsWith("0") ? phoneNumber.replaceFirst("0", "") : phoneNumber;

    await authVM.checkActivationCode(
      activationCode: '0000',
      otpTypeEnum: OTPTypeEnum.sms,
      onWrongActivationCode: (String? str) {},
      responseID: responseID,
      isFormFamilyFile: false,
      isSwitchUser: true,
      patientID: patientID,
    );
  }




  Future<void> addFamilyFile({required OTPTypeEnum otpTypeEnum}) async {
    LoaderBottomSheet.showLoader();
    AuthenticationViewModel authVM = getIt.get<AuthenticationViewModel>();
    NavigationService navigationService = getIt.get<NavigationService>();
    FamilyFileRequest request =
        await RequestUtils.getAddFamilyRequest(nationalIDorFile: authVM.nationalIdController.text, mobileNo: authVM.phoneNumberController.text, countryCode: authVM.selectedCountrySignup.countryCode);

    final resultEither = await medicalFileRepo.addFamilyFile(request: request.toJson());
    resultEither.fold((failure) async => await errorHandlerService.handleError(failure: failure), (apiResponse) async {
      if (apiResponse.messageStatus == 2) {
        print("=======");
        LoaderBottomSheet.hideLoader();
        _dialogService.showErrorBottomSheet(
            message: apiResponse.errorMessage!,
            onOkPressed: () {
              navigationService.pop();
            });
      } else if (apiResponse.messageStatus == 1) {
        if (apiResponse.data != null) {
          request.isPatientExcluded = apiResponse.data["IsPatientExcluded"];
          request.responseID = apiResponse.data["ReponseID"];
          LoaderBottomSheet.hideLoader();
          _dialogService.showExceptionBottomSheet(
              message: apiResponse.data["Message"],
              onOkPressed: () {
                navigationService.pop();
                authVM.sendActivationCode(
                    otpTypeEnum: otpTypeEnum,
                    nationalIdOrFileNumber: request.sharedPatientIdentificationId!,
                    phoneNumber: request.sharedPatientMobileNumber!,
                    isForRegister: false,
                    isExcludedUser: apiResponse.data['IsPatientExcluded'],
                    responseID: apiResponse.data["ReponseID"],
                    isNeedLoading: true,
                    isFormFamilyFile: true);
              },
              onCancelPressed: () {
                navigationService.pop();
              });
        }
      }
    });
  }

  Future<void> handleFamilyFileRequestOTPVerification() async {
    LoaderBottomSheet.showLoader();
    if (!_appState.getIsChildLoggedIn) {
      await getFamilyFiles(status: 0);
      await getAllPendingRecordsByResponseId();
    }

    LoaderBottomSheet.hideLoader();
  }

  Future<void> removeFileFromFamilyMembers({int? id}) async {
    NavigationService navigationService = getIt.get<NavigationService>();
    _dialogService.showExceptionBottomSheet(
        message: "Remove this member?",
        onOkPressed: () async {
          LoaderBottomSheet.showLoader();
          final result = await medicalFileRepo.removeFamilyFile(id: id);
          result.fold(
            (failure) async => await errorHandlerService.handleError(failure: failure),
            (apiResponse) {
              if (apiResponse.messageStatus == 2) {
                LoaderBottomSheet.hideLoader();
                _dialogService.showErrorBottomSheet(
                    message: apiResponse.errorMessage!,
                    onOkPressed: () {
                      navigationService.pop();
                    });
              } else if (apiResponse.messageStatus == 1) {
                patientFamilyFiles.removeWhere((element) => element.id == id);
                getFamilyFiles();
                getAllPendingRecordsByResponseId();
                LoaderBottomSheet.hideLoader();
                notifyListeners();
                navigationService.pop();
              }
            },
          );
        },
        onCancelPressed: () {
          navigationService.pop();
        });
  }

  Future<void> getPatientMedicalReportAppointmentsList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    patientMedicalReportAppointmentHistoryList.clear();
    notifyListeners();

    final result = await medicalFileRepo.getPatientAppointmentsForMedicalReport();

    result.fold(
      (failure) async {
        onError!(failure.message);
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          patientMedicalReportAppointmentHistoryList = apiResponse.data!;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> insertRequestForMedicalReport({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await medicalFileRepo.insertRequestForMedicalReport(appointmentHistoryResponseModel: patientMedicalReportSelectedAppointment!);

    result.fold(
      (failure) async {
        onError!(failure.message);
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> acceptRejectFileFromFamilyMembers({int? id, int? status}) async {
    NavigationService navigationService = getIt.get<NavigationService>();
    LoaderBottomSheet.showLoader();
    final result = await medicalFileRepo.acceptRejectFamilyFile(id: id, status: status);
    result.fold(
      (failure) async => await errorHandlerService.handleError(failure: failure),
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          LoaderBottomSheet.hideLoader();
          // _dialogService.showErrorBottomSheet(
          //     message: apiResponse.errorMessage!,
          //     onOkPressed: () {
          //       navigationService.pop();
          //     });
        } else if (apiResponse.messageStatus == 1) {
          // FamilyFileResponseModelLists moveProfile = pendingFamilyFiles.firstWhere((element) => element.id == patientID);
          // moveProfile.status = 3;
          // moveProfile.statusDescription = "Approved";
          // patientFamilyFiles.add(moveProfile);
          pendingFamilyFiles.removeWhere((element) => element.id == id);
          //TODO: Call Api Here To Load Family Members
          getFamilyFiles(status: 0);
          getAllPendingRecordsByResponseId();
          LoaderBottomSheet.hideLoader();
          onFamilyFileTabChange(0);
        }
      },
    );
  }
}
