import 'dart:io';

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/immediate_livecare/models/resp_models/get_livecare_clinic_schedule_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_clinics_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_fees_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_patient_livecare_history_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';

abstract class ImmediateLiveCareRepo {
  Future<Either<Failure, GenericApiModel<List<GetLiveCareClinicListResponseModel>>>> getLiveCareImmediateClinicsList(int age, int genderID, {Function(dynamic)? onSuccess, Function(String)? onError});

  Future<Either<Failure, GenericApiModel<List<LiveCareClinicScheduleResponse>>>> getLiveCareImmediateClinicSchedule(int age, int genderID, int serviceID,
      {Function(dynamic)? onSuccess, Function(String)? onError});

  Future<Either<Failure, GenericApiModel<LiveCareImmediateAppointmentFeesList>>> getLiveCareImmediateAppointmentFees(int age, int genderID, int serviceID,
      {Function(dynamic)? onSuccess, Function(String)? onError});

  Future<Either<Failure, GenericApiModel<dynamic>>> addNewCallRequestForImmediateLiveCare(
      int age, int gender, int serviceID, String clientRequestID, int callTypeID, bool isPharma, String deviceToken, String voipToken,
      {Function(dynamic)? onSuccess, Function(String)? onError});

  Future<Either<Failure, GenericApiModel<List<PatientLiveCareHistory>>>> getPatientLiveCareHistory({Function(dynamic)? onSuccess, Function(String)? onError});

  Future<Either<Failure, GenericApiModel<dynamic>>> addInsuranceUpdateRequestForLiveCare(String name, String mobileNumber, String fileNumber,
      {Function(dynamic)? onSuccess, Function(String)? onError});
}

class ImmediateLiveCareRepoImp implements ImmediateLiveCareRepo {
  final ApiClient apiClient;
  final LoggerService loggerService;

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

  @override
  Future<Either<Failure, GenericApiModel<List<GetLiveCareClinicListResponseModel>>>> getLiveCareImmediateClinicsList(int age, int genderID,
      {Function(dynamic)? onSuccess, Function(String)? onError}) async {
    Map<String, dynamic> mapDevice = {
      "Age": age,
      "Gender": genderID,
    };

    try {
      GenericApiModel<List<GetLiveCareClinicListResponseModel>>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_LIVECARE_CLINICS,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
          onError!(error);
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            final list = response['PatientER_GetClinicsList'];

            final clinicsList = list.map((item) => GetLiveCareClinicListResponseModel.fromJson(item as Map<String, dynamic>)).toList().cast<GetLiveCareClinicListResponseModel>();

            apiResponse = GenericApiModel<List<GetLiveCareClinicListResponseModel>>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: clinicsList,
            );
          } 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<LiveCareImmediateAppointmentFeesList>>> getLiveCareImmediateAppointmentFees(int age, int genderID, int serviceID,
      {Function(dynamic)? onSuccess, Function(String)? onError}) async {
    Map<String, dynamic> mapDevice = {
      "Age": age,
      "Gender": genderID,
      "ServiceID": serviceID,
    };

    try {
      GenericApiModel<LiveCareImmediateAppointmentFeesList>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_ER_APPOINTMENT_FEES,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
          // onError!(error);
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            final respObject = response['GetERAppointmentFeesList'];

            final liveCareFeesObj = LiveCareImmediateAppointmentFeesList.fromJson(respObject);

            apiResponse = GenericApiModel<LiveCareImmediateAppointmentFeesList>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: liveCareFeesObj,
            );
          } 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>> addNewCallRequestForImmediateLiveCare(
      int age, int gender, int serviceID, String clientRequestID, int callTypeID, bool isPharma, String deviceToken, String voipToken,
      {Function(dynamic p1)? onSuccess, Function(String p1)? onError}) async {
    Map<String, dynamic> mapDevice = {
      "IsPharmacy": isPharma,
      "ErServiceID": serviceID,
      "ClientRequestID": clientRequestID,
      "DeviceToken": deviceToken,
      "VoipToken": voipToken,
      "IsFlutter": true,
      "DeviceType": Platform.isIOS ? 'iOS' : 'Android',
      "Age": age,
      "Gender": gender,
      "IsVoip": Platform.isIOS ? true : false,
      "CallTypeID": callTypeID
    };

    try {
      GenericApiModel<dynamic>? apiResponse;
      Failure? failure;
      await apiClient.post(
        ADD_NEW_CALL_FOR_PATIENT_ER,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
          // onError!(error);
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            apiResponse = GenericApiModel<dynamic>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: true,
            );
          } 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<PatientLiveCareHistory>>>> getPatientLiveCareHistory({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    Map<String, dynamic> mapDevice = {};

    try {
      GenericApiModel<List<PatientLiveCareHistory>>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_LIVECARE_HISTORY,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
          onError!(error);
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            final list = response['ErRequestHistoryList'];

            final liveCareHistoryList = list.map((item) => PatientLiveCareHistory.fromJson(item as Map<String, dynamic>)).toList().cast<PatientLiveCareHistory>();

            apiResponse = GenericApiModel<List<PatientLiveCareHistory>>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: liveCareHistoryList,
            );
          } 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<LiveCareClinicScheduleResponse>>>> getLiveCareImmediateClinicSchedule(int age, int genderID, int serviceID,
      {Function(dynamic p1)? onSuccess, Function(String p1)? onError}) async {
    Map<String, dynamic> mapDevice = {
      "Age": age,
      "Gender": genderID,
      "ServiceID": serviceID,
    };

    try {
      GenericApiModel<List<LiveCareClinicScheduleResponse>>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_LIVECARE_CLINIC_TIMING,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
          // onError!(error);
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            final respObject = response['PatientER_GetClinicsServiceTimingsList'];
            final liveCareScheduleObj = respObject.map((item) => LiveCareClinicScheduleResponse.fromJson(item as Map<String, dynamic>)).toList().cast<LiveCareClinicScheduleResponse>();

            apiResponse = GenericApiModel<List<LiveCareClinicScheduleResponse>>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: liveCareScheduleObj,
            );
          } 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>> addInsuranceUpdateRequestForLiveCare(String name, String mobileNumber, String fileNumber,
      {Function(dynamic p1)? onSuccess, Function(String p1)? onError}) async {
    Map<String, dynamic> mapDevice = {
      "PatientName": name,
      "MobileNumber": mobileNumber,
      "FileNumber": fileNumber,
    };

    try {
      GenericApiModel<dynamic>? apiResponse;
      Failure? failure;
      await apiClient.post(
        ADD_LIVECARE_INSURANCE_UPDATE_REQUEST,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
          // onError!(error);
        },
        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()));
    }
  }
}
