import { injectEvent } from "../../core/injector";

import {
  AmbulanceCatalog,
  AmbulanceProperties,
  EmergencyMgmtCatalogType,
  EmergencyMgmtEventType,
  EROCatalog,
  IncidentProperties,
} from "./typings";
import CfExceptionHandler from "../../core/CfExceptionHandler";
import { isISOLocal } from "../../utils";
import {
  validateAndSaveAmbulanceCatalog,
  validateAndSaveEROCatalog,
} from "./EmergencyMgmtCatalogValidator";

const logIngestEvent = async (
  eventType: EmergencyMgmtEventType,
  properties: IncidentProperties | AmbulanceProperties,
  sendNow = false,
  eventTime?: string
) => {
  let checkProps = true;

  switch (eventType) {
    case EmergencyMgmtEventType.Incident:
      checkProps = validateIncidentEvent(properties as IncidentProperties);
      break;

    case EmergencyMgmtEventType.Ambulance: {
      const props = properties as AmbulanceProperties;
      checkProps = validateAmbulanceEvent(props);
      break;
    }

    default:
      return; // Exit early if eventType is unrecognized
  }

  if (!checkProps) {
    return; // Exit if the properties validation failed
  }
  injectEvent(eventType, properties.action, properties, sendNow, "", eventTime);
};

const validateIncidentEvent = (properties: IncidentProperties): boolean => {
  if (!properties.action) {
    new CfExceptionHandler().throwAndLogError(
      EmergencyMgmtEventType.Incident,
      "invalid incident action"
    );
    return false;
  } else if (!properties.incident_id) {
    new CfExceptionHandler().throwAndLogError(
      EmergencyMgmtEventType.Incident,
      "invalid incident details id"
    );
    return false;
  } else if (!properties.type) {
    new CfExceptionHandler().throwAndLogError(
      EmergencyMgmtEventType.Incident,
      "invalid incident details type"
    );
    return false;
  } else if (
    properties.chief_complaints_list &&
    properties.chief_complaints_list.some((item) => item === "")
  ) {
    new CfExceptionHandler().throwAndLogError(
      EmergencyMgmtEventType.Incident,
      "invalid incident chief_complaints_list item"
    );
    return false;
  } else if (!properties.site_id && !properties.country) {
    new CfExceptionHandler().throwAndLogError(
      EmergencyMgmtEventType.Incident,
      "Either site_id or country must be provided"
    );
    return false;
  }
  return true;
};

const validateAmbulanceEvent = (properties: AmbulanceProperties): boolean => {
  if (!properties.action) {
    new CfExceptionHandler().throwAndLogError(
      EmergencyMgmtEventType.Ambulance,
      "invalid incident action"
    );
    return false;
  } else if (
    !properties.ambulance_id.trim() ||
    !properties.type.trim() ||
    !properties.driver_id.trim()
  ) {
    new CfExceptionHandler().throwAndLogError(
      EmergencyMgmtEventType.Ambulance,
      "Invalid ambulance item: id, type, and driver_id are required"
    );
    return false;
  } else if (properties.gps_datetime && !isISOLocal(properties.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"
    );
    return false;
  } else if (!properties.pickup_site_id && !properties.pickup_country) {
    new CfExceptionHandler().throwAndLogError(
      EmergencyMgmtEventType.Ambulance,
      "Invalid pickup address: either site_id or country must be provided"
    );
    return false;
  } else if (
    !properties.destination_site_id &&
    !properties.destination_country
  ) {
    new CfExceptionHandler().throwAndLogError(
      EmergencyMgmtEventType.Ambulance,
      "Invalid destination address: either site_id or country must be provided"
    );
    return false;
  } else if (!properties.denial_reason) {
    new CfExceptionHandler().throwAndLogError(
      EmergencyMgmtEventType.Ambulance,
      "Invalid denial_details: denial reason is required"
    );
    return false;
  }
  return true;
};

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

export default {
  logIngestEvent,
  logCatalogEvent,
};
