import PatientMgmtPropertiesTI from './typings-ti'

import {injectEvent} from "../../core/injector"
import {ICatalogRepository} from "../../core/repositories/catalog/CatalogRepository"
import {
    AppointmentProperties,
    EncounterProperties,
    HcwCatalogModel,
    PatientCatalogModel,
    PatientProperties,
    PatientMgmtCatalogType,
    PatientMgmtEventType,
} from "./typings"
import CfExceptionHandler from "../../core/CfExceptionHandler";
import {ContentBlock} from "../Navigation/typings";
import {setToUndefinedIfNull} from "../../utils";

let catalogRepository: ICatalogRepository;

/**
 * Private function to inject repositories
 *
 * @ignore
 */
const init = (
    injectedCatalogRepository: ICatalogRepository
) => {
    catalogRepository = injectedCatalogRepository
}

/**
 * logPatientModuleEvent is to log the selection of the module selected by the user in the app.
 */
const logIngestEvent = async (eventType: PatientMgmtEventType,
                              properties: PatientProperties | EncounterProperties | AppointmentProperties,
                              sendNow = false) => {

    let checkProps: PatientProperties | EncounterProperties | AppointmentProperties | null = null;

    switch (eventType) {
        case PatientMgmtEventType.Patient:
            checkProps = validatePatientEvent(properties as PatientProperties);
            break;
        case PatientMgmtEventType.Encounter:
            checkProps = validateEncounterEvent(properties as EncounterProperties);
            break;
        case PatientMgmtEventType.Appointment:
            checkProps = validateAppointmentEvent(properties as AppointmentProperties);
            break;
        default:
            return; // Exit early if eventType is unrecognized
    }

    if (!checkProps) {
        return; // Exit if the properties validation failed
    }

    injectEvent (
        properties,
        [PatientMgmtPropertiesTI],
        eventType,
        ContentBlock.PatientMgmt,
        '',
        sendNow
    )
}



const validatePatientEvent = (properties: PatientProperties) => {

    if (properties.patient_id == undefined || properties.patient_id == '') {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Patient, 'patient id required')
        return null
    } else if (properties.site_id == undefined || properties.site_id == '') {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Patient, 'site_id is required')
        return null
    } else if (properties.action == undefined) {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Patient, 'action is required')
        return null
    } else if (properties.category == undefined) {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Patient, 'category is required')
        return null
    } else if (properties.type == undefined) {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Patient, 'type is required')
        return null
    }

    properties = setToUndefinedIfNull(properties, ['sub_type', 'biometric_list', 'pregnancy_details', 'registration_date'])

    if (properties.is_from_gho == undefined) {
        properties.is_from_gho = false
    }

    return properties
}

const validateEncounterEvent = (properties: EncounterProperties) => {


    if (properties.patient_id == undefined || properties.patient_id == '') {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Encounter, 'encounter id required')
        return null
    } else if (properties.site_id == undefined || properties.site_id == '') {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Encounter, 'site_id is required')
        return null
    } else if (properties.action == undefined) {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Encounter, 'action is required')
        return null
    } else if (properties.category == undefined) {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Encounter, 'category is required')
        return null
    } else if (properties.type == undefined) {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Encounter, 'type is required')
        return null
    } else if (properties.sub_type == undefined) {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Encounter, 'sub_type is required')
        return null
    } else if (properties.encounter_summary == undefined) {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Encounter, 'encounter_summary is required')
        return null
    }

    properties.encounter_summary = setToUndefinedIfNull(properties.encounter_summary,
        ['appointment_id', 'main_complaints_list', 'prev_diagnosis_status_list', 'diagnosis_status_list',
            'prev_treatment_plan', 'treatment_plan', 'diagnostic_elements', 'pregnancy_details',
            'counseling_list', 'remarks', 'is_followup_id', 'is_referral_id', 'has_followup', 'has_referral'])


    return properties
}

const validateAppointmentEvent = (properties: AppointmentProperties) => {

    if (properties.patient_id == undefined || properties.patient_id == '') {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Appointment, 'Patient ID is required')
        return null
    } else if (properties.site_id == undefined || properties.patient_id == '') {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Appointment, 'site ID is required')
        return null
    } else if (properties.action == undefined) {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Appointment, 'action is required')
        return null
    } else if (properties.appointment == undefined) {
        new CfExceptionHandler().throwAndLogError(PatientMgmtEventType.Appointment, 'appointment object is required')
        return null
    }

    properties.appointment = setToUndefinedIfNull(properties.appointment, ['update', 'missed'])

    return properties
}


const logCatalogEvent = (catalogType: PatientMgmtCatalogType,
                         catalogModel: HcwCatalogModel | PatientCatalogModel) => {
    switch (catalogType) {
        case PatientMgmtCatalogType.UserHcw:
            catalogRepository.injectHCW(catalogModel as HcwCatalogModel)
            break;
        case PatientMgmtCatalogType.Patient:
            catalogRepository.injectPatient(catalogModel as PatientCatalogModel)
            break;
    }
}

export default {
    init,
    logIngestEvent,
    logCatalogEvent
}
