import {injectEvent} from '../../core/injector'
import {ContentBlock} from '../Navigation/typings'
import {
    AmbulanceCatalog,
    AmbulanceProperties, EmergencyMgmtCatalogType,
    EmergencyMgmtEventType, EROCatalog, IncidentProperties,
} from './typings'
import EmergencyMgmtPropertiesTI from './typings-ti'
import {ICatalogRepository} from "../../core/repositories/catalog/CatalogRepository"
import CfExceptionHandler from "../../core/CfExceptionHandler";
import {isISOLocal} from "../../utils";

let catalogRepository: ICatalogRepository;

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

const logIngestEvent = async (eventType: EmergencyMgmtEventType,
                              properties: IncidentProperties | AmbulanceProperties,
                              sendNow = false) => {

    let checkProps: IncidentProperties | AmbulanceProperties | null = null;

    switch (eventType) {
        case EmergencyMgmtEventType.Incident:
            checkProps = validateIncidentEvent(properties as IncidentProperties);
            break;
        case EmergencyMgmtEventType.Ambulance:
            checkProps = validateAmbulanceEvent(properties as AmbulanceProperties);
            break;
        default:
            return; // Exit early if eventType is unrecognized
    }

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

    injectEvent(
        properties,
        [EmergencyMgmtPropertiesTI],
        eventType,
        ContentBlock.EmergencyMgmt,
        '',
        sendNow
    )
}

const validateIncidentEvent = (properties: IncidentProperties) => {
    if(!properties.action){
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Incident, 'invalid incident action')
    }else if(!properties.details){
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Incident, 'invalid incident details')
    }else if(!properties.details.id){
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Incident, 'invalid incident details id')
    }else if(!properties.details.type){
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Incident, 'invalid incident details type')
    }else if (properties.details.chief_complaints_list &&
        properties.details.chief_complaints_list.some(item => item.complaint === '')) {
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Incident, 'invalid incident chief_complaints_list item');
    }else if (properties.address && !properties.address.site_id && !properties.address.country) {
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Incident, 'Either site_id or country must be provided');
    }else if (properties.patient_list &&
        properties.patient_list.some(item => !item.id.trim())) {
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Incident, 'Invalid patient_list item: id is required');
    }else if (properties.ambulance_list &&
        properties.ambulance_list.some(item => !item.id.trim() || !item.type.trim() || !item.driver_id.trim())) {
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Incident, 'Invalid ambulance_list item: id, type, and driver_id are required');
    }else if (properties.ambulance_list &&
        properties.ambulance_list.some(item => item.gps_datetime && !isISOLocal(item.gps_datetime))) {
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Incident, 'Invalid ambulance gps_datetime: should be in ISO8601 format e.g. 1937-01-01T12:00:27.87+02:00');
    }
    return properties
}

const validateAmbulanceEvent = (properties: AmbulanceProperties) => {
    if(!properties.action){
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Ambulance, 'invalid incident action')
    }else if (properties.ambulance &&
        !properties.ambulance.id.trim() || !properties.ambulance.type.trim() || !properties.ambulance.driver_id.trim()) {
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Ambulance, 'Invalid ambulance item: id, type, and driver_id are required');
    }else if (properties.ambulance && properties.ambulance.gps_datetime && !isISOLocal(properties.ambulance.gps_datetime)) {
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Ambulance, 'Invalid ambulance gps_datetime: should be in ISO8601 format e.g. 1937-01-01T12:00:27.87+02:00');
    }else if (properties.ambulance.location &&
        !properties.ambulance.location.site_id.trim() && !properties.ambulance.location.country.trim()) {
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Ambulance, 'Invalid ambulance item: either site_id or country must be provided');
    }else if (properties.pickup_address && !properties.pickup_address.site_id && !properties.pickup_address.country) {
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Ambulance, 'Invalid pickup address: either site_id or country must be provided');
    }else if (properties.destination_address && !properties.destination_address.site_id && !properties.destination_address.country) {
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Ambulance, 'Invalid destination address: either site_id or country must be provided');
    }else if (properties.denial_details && !properties.denial_details.reason) {
        new CfExceptionHandler().throwAndLogError(EmergencyMgmtEventType.Ambulance, 'Invalid denial_details: denial reason is required');
    }
    return properties
}

const logCatalogEvent = (catalogType: EmergencyMgmtCatalogType, properties: EROCatalog | AmbulanceCatalog): void => {
    switch (catalogType) {
        case EmergencyMgmtCatalogType.ERO:
            catalogRepository.injectERO(properties as EROCatalog);
            break;
        case EmergencyMgmtCatalogType.Ambulance:
            catalogRepository.injectAmbulance(properties as AmbulanceCatalog);
            break;
        default:
            return; // Exit early if eventType is unrecognized
    }
}

export default {
    logIngestEvent,
    logCatalogEvent,
    init
}
