import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.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/features/my_appointments/models/resp_models/patient_appointment_share_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';

import '../../core/utils/doctor_response_mapper.dart' show DoctorMapper;

class MyAppointmentsViewModel extends ChangeNotifier {
  int selectedTabIndex = 0;

  MyAppointmentsRepo myAppointmentsRepo;
  ErrorHandlerService errorHandlerService;
  AppState appState;

  bool isMyAppointmentsLoading = false;
  bool isAppointmentPatientShareLoading = false;
  bool isTimeLineAppointmentsLoading = false;
  bool isPatientMyDoctorsLoading = false;

  bool isAppointmentDataToBeLoaded = true;

  List<PatientAppointmentHistoryResponseModel> patientAppointmentsHistoryList = [];

  List<PatientAppointmentHistoryResponseModel> patientUpcomingAppointmentsHistoryList = [];
  List<PatientAppointmentHistoryResponseModel> patientArrivedAppointmentsHistoryList = [];

  List<PatientAppointmentHistoryResponseModel> patientTimelineAppointmentsList = [];

  List<PatientAppointmentHistoryResponseModel> patientMyDoctorsList = [];

  PatientAppointmentShareResponseModel? patientAppointmentShareResponseModel;

  MyAppointmentsViewModel({required this.myAppointmentsRepo, required this.errorHandlerService, required this.appState});

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

  initAppointmentsViewModel() {
    if (isAppointmentDataToBeLoaded) {
      patientAppointmentsHistoryList.clear();
      patientUpcomingAppointmentsHistoryList.clear();
      patientArrivedAppointmentsHistoryList.clear();
      patientTimelineAppointmentsList.clear();
      isMyAppointmentsLoading = true;
      isTimeLineAppointmentsLoading = true;
      patientMyDoctorsList.clear();
      isPatientMyDoctorsLoading = true;
    }
    isAppointmentPatientShareLoading = true;
    notifyListeners();
  }

  setIsAppointmentsHistoryLoading(bool val) {
    isMyAppointmentsLoading = val;
    notifyListeners();
  }

  setIsPatientAppointmentShareLoading(bool val) {
    isAppointmentPatientShareLoading = val;
    notifyListeners();
  }

  setIsPatientTimeLineAppointmentLoading(bool val) {
    isTimeLineAppointmentsLoading = val;
    notifyListeners();
  }

  setIsPatientMyDoctorsLoading(bool val) {
    isPatientMyDoctorsLoading = val;
    notifyListeners();
  }

  setIsAppointmentDataToBeLoaded(bool val) {
    isAppointmentDataToBeLoaded = val;
    notifyListeners();
  }

  setAppointmentReminder(bool value, PatientAppointmentHistoryResponseModel item) {
    int index = patientAppointmentsHistoryList.indexOf(item);
    if (index != -1) {
      patientAppointmentsHistoryList[index].hasReminder = value;
      notifyListeners();
    }
  }

  Future<void> getPatientAppointments(bool isActiveAppointment, bool isArrivedAppointments, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
    if (!isAppointmentDataToBeLoaded) return;

    patientAppointmentsHistoryList.clear();
    patientUpcomingAppointmentsHistoryList.clear();
    patientArrivedAppointmentsHistoryList.clear();

    final result = await myAppointmentsRepo.getPatientAppointments(isActiveAppointment: isActiveAppointment, isArrivedAppointments: isArrivedAppointments);
    final resultArrived = await myAppointmentsRepo.getPatientAppointments(isActiveAppointment: false, isArrivedAppointments: true);

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

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

    patientAppointmentsHistoryList.addAll(patientUpcomingAppointmentsHistoryList);
    patientAppointmentsHistoryList.addAll(patientArrivedAppointmentsHistoryList);

    print('Upcoming Appointments: ${patientUpcomingAppointmentsHistoryList.length}');
    print('Arrived Appointments: ${patientArrivedAppointmentsHistoryList.length}');
    print('All Appointments: ${patientAppointmentsHistoryList.length}');
  }

  Future<void> getPatientShareAppointment(int projectID, int clinicID, String appointmentNo, bool isLiveCareAppointment, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await myAppointmentsRepo.getPatientShareAppointment(projectID: projectID, clinicID: clinicID, appointmentNo: appointmentNo, isLiveCareAppointment: isLiveCareAppointment);

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

  Future<void> addAdvanceNumberRequest(
      {required String advanceNumber, required String paymentReference, required String appointmentNo, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await myAppointmentsRepo.addAdvanceNumberRequest(advanceNumber: advanceNumber, paymentReference: paymentReference, appointmentNo: appointmentNo);

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

  Future<void> generateAppointmentQR(
      {required int clinicID, required int projectID, required String appointmentNo, required int isFollowUp, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await myAppointmentsRepo.generateAppointmentQR(clinicID: clinicID, projectID: projectID, appointmentNo: appointmentNo, isFollowUp: isFollowUp);

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

  Future<void> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await myAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);

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

  Future<void> confirmAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await myAppointmentsRepo.confirmAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);

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

  Future<void> createAdvancePayment(
      {required String paymentMethodName,
      required int projectID,
      required int clinicID,
      required String appointmentNo,
      required num payedAmount,
      required String paymentReference,
      required String patientID,
      required int patientType,
      Function(dynamic)? onSuccess,
      Function(String)? onError}) async {
    final result = await myAppointmentsRepo.createAdvancePayment(
        paymentMethodName: paymentMethodName,
        projectID: projectID,
        clinicID: clinicID,
        appointmentNo: appointmentNo,
        payedAmount: payedAmount,
        paymentReference: paymentReference,
        patientID: patientID,
        patientType: patientType);

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

  Future<void> sendCheckInNfcRequest(
      {required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel,
      required String scannedCode,
      required int checkInType,
      Function(dynamic)? onSuccess,
      Function(String)? onError}) async {
    final result = await myAppointmentsRepo.sendCheckInNfcRequest(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, scannedCode: scannedCode, checkInType: checkInType);

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

  Future<void> getPatientMyDoctors({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    if (!isAppointmentDataToBeLoaded) return;
    final result = await myAppointmentsRepo.getPatientDoctorsList();

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

  Future<void> insertLiveCareVIDARequest(
      {required clientRequestID, required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await myAppointmentsRepo.insertLiveCareVIDARequest(clientRequestID: clientRequestID, patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);

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