"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.findFutureAppointment = void 0;
const lodash_1 = require("lodash");
const extensions_core_1 = require("@awell-health/extensions-core");
const date_fns_1 = require("date-fns");
const addEventLog_1 = require("../../../../src/lib/awell/addEventLog");
const config_1 = require("./config");
const getFutureAppointments_1 = require("./getFutureAppointments");
const findAppointmentsWithLLM_1 = require("../../lib/findAppointmentsWithLLM/findAppointmentsWithLLM");
const createOpenAIModel_1 = require("../../../../src/lib/llm/openai/createOpenAIModel");
const constants_1 = require("../../../../src/lib/llm/openai/constants");
const utils_1 = require("../../../../src/utils");
const extractDatesFromInstructions_1 = require("../../lib/extractDatesFromInstructions/extractDatesFromInstructions");
exports.findFutureAppointment = {
    key: 'findFutureAppointment',
    category: extensions_core_1.Category.EHR_INTEGRATIONS,
    title: '✨ Find Future Appointment',
    description: 'Find a future appointment in Elation.',
    fields: config_1.fields,
    previewable: true,
    supports_automated_retries: true,
    dataPoints: config_1.dataPoints,
    onEvent: async ({ payload, onComplete, onError, helpers }) => {
        // 1. Validate input
        const { prompt, patientId } = config_1.FieldsValidationSchema.parse(payload.fields);
        // 2. Get future appointments (scheduled or confirmed) first
        const appointments = await (0, getFutureAppointments_1.getFutureAppointments)(payload.settings, patientId);
        // Early return if no appointments found - no need to go to LLMs
        if (appointments.length === 0) {
            await onComplete({
                data_points: {
                    appointment: undefined,
                    appointmentExists: 'false',
                    explanation: 'No future appointments found',
                },
            });
            return;
        }
        // 3. Initialize OpenAI model with metadata and callbacks
        const { model, metadata, callbacks } = await (0, createOpenAIModel_1.createOpenAIModel)({
            settings: {}, // we use built-in API key for OpenAI
            helpers,
            payload,
            modelType: constants_1.OPENAI_MODELS.GPT4o,
        });
        // 4. Extract date information from the prompt
        const { from, to, instructions } = await (0, extractDatesFromInstructions_1.extractDatesFromInstructions)({
            model,
            prompt,
            metadata,
            callbacks,
        });
        // 5. Find matching appointments with LLM
        const { appointmentIds, explanation } = await (0, findAppointmentsWithLLM_1.findAppointmentsWithLLM)({
            model,
            appointments,
            prompt: (0, lodash_1.defaultTo)(instructions, prompt),
            metadata,
            callbacks,
        });
        const htmlExplanation = await (0, utils_1.markdownToHtml)(explanation);
        // 6. Filter appointments based on both LLM selection and date range
        const filteredAppointments = appointments.filter((appointment) => appointmentIds.includes(appointment.id) &&
            ((0, lodash_1.isNil)(from) ||
                (0, date_fns_1.isAfter)((0, date_fns_1.parseISO)(appointment.scheduled_date), (0, date_fns_1.parseISO)(from))) &&
            ((0, lodash_1.isNil)(to) ||
                (0, date_fns_1.isBefore)((0, date_fns_1.parseISO)(appointment.scheduled_date), (0, date_fns_1.parseISO)(to))));
        const filteredAppointmentIds = filteredAppointments.map((appointment) => appointment.id);
        // Handle case where no appointments were found after filtering
        if (filteredAppointmentIds.length === 0) {
            await onComplete({
                data_points: {
                    appointment: undefined,
                    appointmentExists: 'false',
                    explanation: htmlExplanation,
                },
                events: [
                    (0, addEventLog_1.addActivityEventLog)({
                        message: `Number of future scheduled or confirmed appointments: ${appointments.length}\n
            Appointments data: ${JSON.stringify(appointments, null, 2)}\n
            Found appointment: none\n
            Explanation: ${htmlExplanation}`,
                    }),
                ],
            });
            return;
        }
        // 7. If appointments were found, return the first matching appointment
        const matchedAppointmentId = filteredAppointmentIds[0];
        const foundAppointment = filteredAppointments[0];
        await onComplete({
            data_points: {
                appointment: !(0, lodash_1.isNil)(matchedAppointmentId)
                    ? JSON.stringify(foundAppointment)
                    : undefined,
                explanation: htmlExplanation,
                appointmentExists: !(0, lodash_1.isNil)(matchedAppointmentId) ? 'true' : 'false',
            },
            events: [
                (0, addEventLog_1.addActivityEventLog)({
                    message: `Number of future scheduled or confirmed appointments: ${appointments.length}\n
          Appointments data: ${JSON.stringify(appointments, null, 2)}\n
          Found appointment: ${(0, lodash_1.isNil)(foundAppointment) ? 'none' : foundAppointment === null || foundAppointment === void 0 ? void 0 : foundAppointment.id}\n
          Explanation: ${htmlExplanation}`,
                }),
            ],
        });
    },
};
//# sourceMappingURL=findFutureAppointment.js.map