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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/radiology/models/resp_models/patient_radiology_response_model.dart';
import 'package:hmg_patient_app_new/features/radiology/models/resp_models/radiology_ai_analysis_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';

abstract class RadiologyRepo {
  Future<Either<Failure, GenericApiModel<List<PatientRadiologyResponseModel>>>> getPatientRadiologyOrders();

  Future<Either<Failure, GenericApiModel<String>>> getRadiologyImage({required PatientRadiologyResponseModel patientRadiologyResponseModel});

  Future<Either<Failure, GenericApiModel<String>>> getRadiologyReportPDF(
      {required PatientRadiologyResponseModel patientRadiologyResponseModel, required AuthenticatedUser authenticatedUser});

  Future<Either<Failure, GenericApiModel<List<PatientRadiologyResponseModel>>>> getPatientRadiologyOrderByAppointment({required num appointmentNo, required num projectID});

  Future<Either<Failure, GenericApiModel<RadiologyAiAnalysisResponse>>> getRadiologyAiAnalysis({required String reportData,  required int langId,});
}

class RadiologyRepoImp implements RadiologyRepo {
  final ApiClient apiClient;
  final LoggerService loggerService;

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

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

    try {
      GenericApiModel<List<PatientRadiologyResponseModel>>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_PATIENT_ORDERS,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          List<PatientRadiologyResponseModel> radOrders = [];
          try {
            if (response['FinalRadiologyList'] != null && response['FinalRadiologyList'].length != 0) {
              final list = response['FinalRadiologyList'];
              radOrders = list
                  .map((item) => PatientRadiologyResponseModel.fromJson(item as Map<String, dynamic>))
                  .toList()
                  .cast<PatientRadiologyResponseModel>();
            } else {
              final list = response['FinalRadiologyListAPI'];
              if(list != null && list.length != 0) {
                radOrders = list
                    .map((item) => PatientRadiologyResponseModel.fromJson(item as Map<String, dynamic>))
                    .toList()
                    .cast<PatientRadiologyResponseModel>();
              }
            }

            // Check if radOrders is empty and set failure
            if (radOrders.isEmpty) {
              failure = ServerFailure(errorMessage ?? "No radiology orders found");
              return;
            }

            apiResponse = GenericApiModel<List<PatientRadiologyResponseModel>>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: radOrders,
            );
          } 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>>> getRadiologyImage({required PatientRadiologyResponseModel patientRadiologyResponseModel}) async {
    Map<String, dynamic> mapDevice = {
      "InvoiceNo": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? "0" : patientRadiologyResponseModel.invoiceNo,
      "InvoiceNo_VP": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? patientRadiologyResponseModel.invoiceNo : "0",
      "LineItemNo": patientRadiologyResponseModel.invoiceLineItemNo,
      "ProjectID": patientRadiologyResponseModel.projectID!,
      "InvoiceType": patientRadiologyResponseModel.invoiceType!,
      "ExamId": patientRadiologyResponseModel.examId ?? "",
    };

    try {
      GenericApiModel<String>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_RAD_IMAGE_URL,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            apiResponse = GenericApiModel<String>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: response["Data"],
            );
          } 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>>> getRadiologyReportPDF(
      {required PatientRadiologyResponseModel patientRadiologyResponseModel, required AuthenticatedUser authenticatedUser}) async {
    Map<String, dynamic> mapDevice = {
      "InvoiceNo": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? 0 : patientRadiologyResponseModel.invoiceNo,
      "InvoiceNo_VP": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? patientRadiologyResponseModel.invoiceNo : 0,
      // "LineItemNo": patientRadiologyResponseModel.invoiceLineItemNo,
      "InvoiceLineItemNo": patientRadiologyResponseModel.invoiceLineItemNo,
      "ProjectID": patientRadiologyResponseModel.projectID!,
      "InvoiceType": patientRadiologyResponseModel.invoiceType!,
      "SetupID": patientRadiologyResponseModel.setupID!,
      // "ExamId": patientRadiologyResponseModel.examId ?? "",
      "IsDownload": true,
      'ClinicName': patientRadiologyResponseModel.clinicDescription,
      'DateofBirth': authenticatedUser.dateofBirth,
      'DoctorName': patientRadiologyResponseModel.doctorName,
      'OrderDate':
          '${patientRadiologyResponseModel.orderDate!.year}-${patientRadiologyResponseModel.orderDate!.month}-${patientRadiologyResponseModel.orderDate!.day}',
      'PatientIditificationNum': authenticatedUser.patientIdentificationNo,
      'PatientMobileNumber': authenticatedUser.mobileNumber,
      'PatientName': "${authenticatedUser.firstName!} ${authenticatedUser.lastName!}",
      'ProjectName': patientRadiologyResponseModel.projectName,
      'RadResult': patientRadiologyResponseModel.reportData,
      "To": authenticatedUser.emailAddress
    };

    try {
      GenericApiModel<String>? apiResponse;
      Failure? failure;
      await apiClient.post(
        SEND_RAD_REPORT_EMAIL,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            apiResponse = GenericApiModel<String>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: response["Base64Data"],
            );
          } 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<PatientRadiologyResponseModel>>>> getPatientRadiologyOrderByAppointment({required num appointmentNo, required num projectID}) async {
    Map<String, dynamic> mapDevice = {
      "AppointmentNo": appointmentNo,
      "ProjectID": projectID,
    };

    try {
      GenericApiModel<List<PatientRadiologyResponseModel>>? apiResponse;
      Failure? failure;
      await apiClient.post(
        GET_PATIENT_ORDERS,
        body: mapDevice,
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          List<PatientRadiologyResponseModel> radOrders = [];
          try {
            if (response['FinalRadiologyList'] != null && response['FinalRadiologyList'].length != 0) {
              final list = response['FinalRadiologyList'];
              radOrders = list.map((item) => PatientRadiologyResponseModel.fromJson(item as Map<String, dynamic>)).toList().cast<PatientRadiologyResponseModel>();
            } else {
              if (response['FinalRadiologyListAPI'] != null && response['FinalRadiologyListAPI'].length != 0) {
                final list = response['FinalRadiologyListAPI'];
                radOrders = list.map((item) => PatientRadiologyResponseModel.fromJson(item as Map<String, dynamic>)).toList().cast<PatientRadiologyResponseModel>();
              }
            }

            // Check if radOrders is empty and set failure
            if (radOrders.isEmpty) {
              // failure = ServerFailure(errorMessage ?? "No radiology orders found for this appointment");
              // return;
              radOrders= [];
            }

            apiResponse = GenericApiModel<List<PatientRadiologyResponseModel>>(
              messageStatus: messageStatus,
              statusCode: statusCode,
              errorMessage: null,
              data: radOrders,
            );
          } 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<RadiologyAiAnalysisResponse>>> getRadiologyAiAnalysis({required String reportData, required int langId}) async {
    Map<String, dynamic> payload = {
      "text": reportData,
      "language_id": langId
    };

    try {
      GenericApiModel<RadiologyAiAnalysisResponse>? apiResponse;
      Failure? failure;

      await apiClient.post(
        ApiConsts.getAiRadiologyAnalysis,
        body: payload,
        isExternal: true,
        isAllowAny: true,
        apiHeaders: {
          'Accept-Language': 'en-US,en;q=0.7',
          'Content-Type': 'application/json',
          'X-API-KEY': '9d9d2ac4c1fc302299dbb0fbb1b7fea1',
          'accept': 'application/json',
        },
        onFailure: (error, statusCode, {messageStatus, failureType}) {
          failure = failureType;
        },
        onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
          try {
            apiResponse = GenericApiModel<RadiologyAiAnalysisResponse>(
              messageStatus: 1,
              statusCode: statusCode,
              errorMessage: null,
              data: RadiologyAiAnalysisResponse.fromJson(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()));
    }
  }
}
