import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/inpatient_services/models/get_admission_info_response_model.dart';
import 'package:hmg_patient_app_new/features/inpatient_services/models/get_general_instructions_response_model.dart';
import 'package:hmg_patient_app_new/features/inpatient_services/models/get_inpatient_advance_requests_response_model.dart';
import 'package:hmg_patient_app_new/features/inpatient_services/models/get_medical_instructions_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';

abstract class InpatientServicesRepo {
  Future<Either<Failure, GenericApiModel<dynamic>>> checkIfIsInPatient();

  Future<Either<Failure, GenericApiModel<List<GetGeneralInstructions>>>> getGeneralInstructions({required int projectID});

  Future<Either<Failure, GenericApiModel<List<GetMedicalInstructions>>>> getMedicalInstructions({required int projectID});

  Future<Either<Failure, GenericApiModel<dynamic>>> getDischargeMedicationOrder({required GetAdmissionInfoResponseModel getAdmissionInfoResponseModel});

  Future<Either<Failure, GenericApiModel<dynamic>>> insertInPatientOrder(
      {required GetAdmissionInfoResponseModel getAdmissionInfoResponseModel,
      required int typeID,
      required String patientName,
      required String patientNameAR,
      required String patientMobileNo,
      required String comments});

  Future<Either<Failure, GenericApiModel<dynamic>>> getInPatientAdvancePaymentRequests({
    required int projectID,
    required int admissionNo,
    required int admissionReqNo,
  });

  Future<Either<Failure, GenericApiModel<dynamic>>> getInPatientAdvancePaymentPaid({
    required int projectID,
    required int admissionNo,
    required int admissionReqNo,
  });
}

class InpatientServicesRepoImp implements InpatientServicesRepo {
  final ApiClient apiClient;
  final LoggerService loggerService;

  InpatientServicesRepoImp({required this.loggerService, required this.apiClient});

  @override
  Future<Either<Failure, GenericApiModel>> checkIfIsInPatient() async {
    Map<String, dynamic> mapDevice = {"IsActiveAppointment": false};

    try {
      GenericApiModel<dynamic>? apiResponse;
      Failure? failure;
      await apiClient.post(
        CHECK_IF_PATIENT_ADMITTED,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            apiResponse = GenericApiModel<dynamic>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: response,
            );
          } catch (e) {
            failure = DataParsingFailure(e.toString());
          }
        },
      );
      if (failure != null) return Left(failure!);
      if (apiResponse == null) return Left(ServerFailure("Unknown error"));
      return Right(apiResponse!);
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, GenericApiModel<List<GetGeneralInstructions>>>> getGeneralInstructions({required int projectID}) async {
    Map<String, dynamic> mapDevice = {"ProjectID": projectID};

    try {
      GenericApiModel<List<GetGeneralInstructions>>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_GENERAL_INSTRUCTIONS,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            List<GetGeneralInstructions> getGeneralInstructionsList = [];
            response['generalInstructions'].forEach((v) {
              getGeneralInstructionsList.add(GetGeneralInstructions.fromJson(v));
            });

            apiResponse = GenericApiModel<List<GetGeneralInstructions>>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: getGeneralInstructionsList,
            );
          } catch (e) {
            failure = DataParsingFailure(e.toString());
          }
        },
      );
      if (failure != null) return Left(failure!);
      if (apiResponse == null) return Left(ServerFailure("Unknown error"));
      return Right(apiResponse!);
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, GenericApiModel<List<GetMedicalInstructions>>>> getMedicalInstructions({required int projectID}) async {
    Map<String, dynamic> mapDevice = {"ProjectID": projectID};

    try {
      GenericApiModel<List<GetMedicalInstructions>>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_MEDICAL_INSTRUCTIONS,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            List<GetMedicalInstructions> getMedicalInstructionsList = [];
            response['MedicalInstruction'].forEach((v) {
              getMedicalInstructionsList.add(GetMedicalInstructions.fromJson(v));
            });

            apiResponse = GenericApiModel<List<GetMedicalInstructions>>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: getMedicalInstructionsList,
            );
          } catch (e) {
            failure = DataParsingFailure(e.toString());
          }
        },
      );
      if (failure != null) return Left(failure!);
      if (apiResponse == null) return Left(ServerFailure("Unknown error"));
      return Right(apiResponse!);
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, GenericApiModel>> getDischargeMedicationOrder({required GetAdmissionInfoResponseModel getAdmissionInfoResponseModel}) async {
    Map<String, dynamic> mapDevice = {
      "ProjectID": getAdmissionInfoResponseModel.projectID,
      "ClinicID": getAdmissionInfoResponseModel.clinicID,
      "DoctorID": getAdmissionInfoResponseModel.doctorID,
      "AdmissionNo": getAdmissionInfoResponseModel.admissionNo
    };

    try {
      GenericApiModel<dynamic>? apiResponse;
      Failure? failure;
      await apiClient.post(INPATIENT_DISCHARGE_MEDICATIONS, body: mapDevice, onFailure: (error, statusCode, {messageStatus, failureType}) {
        failure = failureType;
      }, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
        try {
          apiResponse = GenericApiModel<dynamic>(
            messageStatus: messageStatus,
            statusCode: statusCode,
            errorMessage: null,
            data: response,
          );
        } catch (e) {
          failure = DataParsingFailure(e.toString());
        }
      }, isAllowAny: true);
      if (failure != null) return Left(failure!);
      if (apiResponse == null) return Left(ServerFailure("Unknown error"));
      return Right(apiResponse!);
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, GenericApiModel>> insertInPatientOrder(
      {required GetAdmissionInfoResponseModel getAdmissionInfoResponseModel,
      required int typeID,
      required String patientName,
      required String patientNameAR,
      required String patientMobileNo,
      required String comments}) async {
    Map<String, dynamic> mapDevice = {
      "ProjectID": getAdmissionInfoResponseModel.projectID,
      "TypeID": typeID,
      "RoomNo": getAdmissionInfoResponseModel.roomID,
      "GenderId": 2,
      "AdmissionNo": getAdmissionInfoResponseModel.admissionNo,
      "prescriptionNo": 250420,
      "patientName": patientName,
      "patientNameN": patientNameAR,
      "PatientMobileNumber": patientMobileNo,
      "comments": comments
    };

    try {
      GenericApiModel<dynamic>? apiResponse;
      Failure? failure;
      await apiClient.post(INSERT_INPATIENT_ORDER, body: mapDevice, onFailure: (error, statusCode, {messageStatus, failureType}) {
        failure = failureType;
      }, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
        try {
          apiResponse = GenericApiModel<dynamic>(
            messageStatus: messageStatus,
            statusCode: statusCode,
            errorMessage: null,
            data: response,
          );
        } catch (e) {
          failure = DataParsingFailure(e.toString());
        }
      }, isAllowAny: true);
      if (failure != null) return Left(failure!);
      if (apiResponse == null) return Left(ServerFailure("Unknown error"));
      return Right(apiResponse!);
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, GenericApiModel>> getInPatientAdvancePaymentRequests({required int projectID, required int admissionNo, required int admissionReqNo}) async {
    Map<String, dynamic> mapDevice = {
      "ProjectID": projectID,
      "AdmissionReqNo": admissionReqNo,
      "AdmissionNo": admissionNo,
    };

    try {
      GenericApiModel<dynamic>? apiResponse;
      Failure? failure;
      await apiClient.post(GET_INPATIENT_ADVANCE_PAYMENT_REQUESTS, body: mapDevice, onFailure: (error, statusCode, {messageStatus, failureType}) {
        failure = failureType;
      }, onSuccess: (res, statusCode, {messageStatus, errorMessage}) {
        try {
          apiResponse = GenericApiModel<dynamic>(
            messageStatus: messageStatus,
            statusCode: statusCode,
            errorMessage: null,
            data: res,
          );
        } catch (e) {
          failure = DataParsingFailure(e.toString());
        }
      }, isAllowAny: true);
      if (failure != null) return Left(failure!);
      if (apiResponse == null) return Left(ServerFailure("Unknown error"));
      return Right(apiResponse!);
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, GenericApiModel>> getInPatientAdvancePaymentPaid({required int projectID, required int admissionNo, required int admissionReqNo}) async {
    Map<String, dynamic> mapDevice = {
      "ProjectID": projectID,
      "AdmissionReqNo": admissionReqNo,
      "AdmissionNo": admissionNo,
    };

    try {
      GenericApiModel<dynamic>? apiResponse;
      Failure? failure;
      await apiClient.post(GET_INPATIENT_PAID_ADVANCE_PAYMENT, body: mapDevice, onFailure: (error, statusCode, {messageStatus, failureType}) {
        failure = failureType;
      }, onSuccess: (res, statusCode, {messageStatus, errorMessage}) {
        try {
          apiResponse = GenericApiModel<dynamic>(
            messageStatus: messageStatus,
            statusCode: statusCode,
            errorMessage: null,
            data: res,
          );
        } catch (e) {
          failure = DataParsingFailure(e.toString());
        }
      }, isAllowAny: true);
      if (failure != null) return Left(failure!);
      if (apiResponse == null) return Left(ServerFailure("Unknown error"));
      return Right(apiResponse!);
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }
}
