"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generatePatientHash = generatePatientHash;
exports.extractPatientInfoFromOCR = extractPatientInfoFromOCR;
const openai_1 = require("@langchain/openai");
const crypto_1 = require("crypto");
const parser_1 = require("./parser");
const prompt_1 = require("./prompt");
const MAX_RETRIES = 3;
/**
 * Generates a deterministic patient identifier hash from first name, last name, and DOB.
 * Returns null if any required field is missing.
 *
 * @param firstName - Patient's first name
 * @param lastName - Patient's last name
 * @param dob - Patient's date of birth (YYYY-MM-DD)
 * @returns SHA-256 hash or null if fields are missing
 */
function generatePatientHash(firstName, lastName, dob) {
    if (firstName == null || lastName == null || dob == null) {
        return null;
    }
    // Normalize: lowercase, trim whitespace
    const normalizedFirstName = firstName.toLowerCase().trim();
    const normalizedLastName = lastName.toLowerCase().trim();
    const normalizedDob = dob.trim();
    // Create a deterministic string to hash
    const dataToHash = `${normalizedFirstName}|${normalizedLastName}|${normalizedDob}`;
    // Generate SHA-256 hash
    return (0, crypto_1.createHash)('sha256').update(dataToHash).digest('hex');
}
/**
 * Extracts patient information from OCR text using an LLM.
 *
 * Uses GPT-4o-mini for cost-effective extraction with good accuracy.
 * Includes retry logic for parsing failures.
 *
 * @param config - Configuration including API key and OCR text
 * @returns Extracted patient information with identifier hash
 */
async function extractPatientInfoFromOCR(config) {
    var _a;
    const { apiKey, ocrText } = config;
    // Initialize the model
    const model = new openai_1.ChatOpenAI({
        modelName: 'gpt-4o-mini-2024-07-18',
        openAIApiKey: apiKey,
        temperature: 0, // Deterministic output for data extraction
        maxRetries: 5,
        timeout: 60000, // 60 second timeout for potentially long documents
    });
    // Format the prompt with the OCR text
    const prompt = await prompt_1.systemPrompt.format({
        ocrText,
    });
    // Create the chain with structured output parsing
    const chain = model.pipe(parser_1.parser);
    // Retry logic for LLM calls
    let result = null;
    let lastError = null;
    for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
        try {
            result = (await chain.invoke(prompt, {
                runName: 'DocumoExtractPatientInfo',
            }));
            break; // Success, exit retry loop
        }
        catch (error) {
            lastError = error instanceof Error ? error : new Error(String(error));
            // Continue to next retry
        }
    }
    if (result == null) {
        throw new Error(`Failed to extract patient information after ${MAX_RETRIES} attempts: ${(_a = lastError === null || lastError === void 0 ? void 0 : lastError.message) !== null && _a !== void 0 ? _a : 'Unknown error'}`);
    }
    // Generate the patient identifier hash
    const patient_identifier_hash = generatePatientHash(result.patient_first_name, result.patient_last_name, result.patient_dob);
    return {
        ...result,
        patient_identifier_hash,
    };
}
//# sourceMappingURL=extractPatientInfoFromOCR.js.map