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/contact_us/models/req_models/request_insert_coc_item.dart';
import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_hmg_locations.dart';
import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_patient_ic_projects.dart';
import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_status_coc_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/logger_service.dart';

abstract class ContactUsRepo {
  Future<Either<Failure, GenericApiModel<List<GetHMGLocationsModel>>>> getHMGLocations();

  Future<Either<Failure, GenericApiModel<List<GetPatientICProjectsModel>>>> getLiveChatProjectsList();

  Future<Either<Failure, GenericApiModel<String>>> getChatRequestID({required String name, required String mobileNo, required String workGroup});

  Future<Either<Failure, GenericApiModel<dynamic>>> insertCOCItem({required RequestInsertCOCItem requestInsertCOCItem, PatientAppointmentHistoryResponseModel? patientSelectedAppointment});

  Future<Either<Failure, GenericApiModel<List<COCItem>>>> getStatusForCOC(String identificationNo, String mobileNo, {Function(dynamic)? onSuccess, Function(String)? onError});
}

class ContactUsRepoImp implements ContactUsRepo {
  final ApiClient apiClient;
  final LoggerService loggerService;

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

  @override
  Future<Either<Failure, GenericApiModel<List<GetHMGLocationsModel>>>> getHMGLocations() async {
    Map<String, dynamic> mapDevice = {};

    try {
      GenericApiModel<List<GetHMGLocationsModel>>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_FINDUS_REQUEST,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            final list = response['ListHMGLocation'];
            final hmgLocations = list.map((item) => GetHMGLocationsModel.fromJson(item as Map<String, dynamic>)).toList().cast<GetHMGLocationsModel>();

            apiResponse = GenericApiModel<List<GetHMGLocationsModel>>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: hmgLocations,
            );
          } 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<GetPatientICProjectsModel>>>> getLiveChatProjectsList() async {
    Map<String, dynamic> mapDevice = {};

    try {
      GenericApiModel<List<GetPatientICProjectsModel>>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_LIVECHAT_REQUEST,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            final list = response['List_PatientICProjects'];
            final liveChatProjectsList = list.map((item) => GetPatientICProjectsModel.fromJson(item as Map<String, dynamic>)).toList().cast<GetPatientICProjectsModel>();

            apiResponse = GenericApiModel<List<GetPatientICProjectsModel>>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: liveChatProjectsList,
            );
          } 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<String>>> getChatRequestID({required String name, required String mobileNo, required String workGroup}) async {
    Map<String, dynamic> body = {};
    body['Name'] = name;
    body['MobileNo'] = mobileNo;
    body['WorkGroup'] = workGroup;

    try {
      GenericApiModel<String>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_LIVECHAT_REQUEST_ID,
        body: body,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            final requestId = response['RequestId'] as String;

            apiResponse = GenericApiModel<String>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: requestId,
            );
          } 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<dynamic>>> insertCOCItem({required RequestInsertCOCItem requestInsertCOCItem, PatientAppointmentHistoryResponseModel? patientSelectedAppointment}) async {
    final Map<String, dynamic> body = requestInsertCOCItem.toJson();

    if (patientSelectedAppointment != null) {
      body['AppoinmentNo'] = patientSelectedAppointment.appointmentNo;
      body['AppointmentDate'] = patientSelectedAppointment.appointmentDate;
      body['ClinicID'] = patientSelectedAppointment.clinicID;
      body['ClinicName'] = patientSelectedAppointment.clinicName;
      body['DoctorID'] = patientSelectedAppointment.doctorID;
      body['DoctorName'] = patientSelectedAppointment.doctorNameObj;
      body['ProjectName'] = patientSelectedAppointment.projectName;
    }

    try {
      GenericApiModel<dynamic>? apiResponse;
      Failure? failure;
      await apiClient.post(
        SEND_FEEDBACK,
        body: body,
        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<COCItem>>>> getStatusForCOC(String identificationNo, String mobileNo, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
    Map<String, dynamic> body = {};
    body['IdentificationNo'] = identificationNo;
    body['MobileNo'] = mobileNo;
    body['Searching_type'] = 1;

    try {
      GenericApiModel<List<COCItem>>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_STATUS_FOR_COCO,
        body: body,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            final list = response['ListCOCItems'];
            final cocItemsList = list.map((item) => COCItem.fromJson(item as Map<String, dynamic>)).toList().cast<COCItem>();

            apiResponse = GenericApiModel<List<COCItem>>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: cocItemsList,
            );
          } 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()));
    }
  }
}
