<cfcomponent displayname="Bulk Import AI API" hint="REST API for bulk importing patient data into AI tables" output="true">
    
    <!--- Add CORS headers --->
    <cfheader name="Access-Control-Allow-Origin" value="*">
    <cfheader name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE">
    <cfheader name="Access-Control-Allow-Headers" value="Content-Type, Authorization">
    
    <!--- Set password encryption key (same as main application) --->
    <cfset this.passwordEncryptKey = "WTq8zYcZfaWVvMncigHqwQ==" />
    
    <!--- Email notification recipients --->
    <cfset this.notificationEmails = "velmurugan@myhomecarebiz.com,melissa@myhomecarebiz.com,janice.l@myhomecarebiz.com" />
    
    <!--- Set datasource name (fallback if Application scope not available) --->
    <cfif not isDefined("Application.DataSrc")>
        <cfset Application.DataSrc = "hhapowerpath" />
    </cfif>
    
    <!--- Validate Basic Authentication --->
    <cffunction name="validateBasicAuth" access="private" returntype="struct" hint="Validate HTTP Basic Authentication">
        <cfargument name="appkey" required="yes" hint="appkey">
        <cfargument name="agency_id" required="no" default="0" hint="Agency ID for logging">
        <cfargument name="emp_id" required="no" default="0" hint="Employee ID for logging">
        <cfargument name="patient_id" required="no" default="0" hint="Patient ID for auth generation">
        
        <cfset var result = {
            "valid": false,
            "message": "Authentication required",
            "agency_db": "",
            "emp_id": 0
        } />
        
        <cftry>
           
            <cfset var agencyKey = trim("" & arguments.agency_id) />
            <cfset var patientKey = trim("" & arguments.patient_id) />
            <cfset var expectedKey = "" />

            <cfif len(agencyKey) AND len(patientKey)>
                <cfset expectedKey = agencyKey & "_" & patientKey />
            </cfif>

            <cfif len(expectedKey) AND appkey EQ expectedKey>
                <!--- Authentication successful --->
                <cfheader statuscode="200" statustext="success">
                <cfset result.valid = true />
                <cfset result.message = "Authentication successful" />
                
                <!--- Send success email notification 
                <cftry>
                    <cfmail to="#this.notificationEmails#" 
                            from="success@myhomecarebiz.com" 
                            subject="Bulk Import AI API - Authentication Success" 
                            type="html">
                        <h3 style="color: green;">Bulk Import AI - Authentication Successful</h3>
                        <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                        <p><strong>Agency ID:</strong> #arguments.agency_id#</p>
                        <p><strong>Employee ID:</strong> #arguments.emp_id#</p>
                        <p><strong>IP Address:</strong> #CGI.REMOTE_ADDR#</p>
                        <p><strong>User Agent:</strong> #CGI.HTTP_USER_AGENT#</p>
                        <p><strong>expectedKey:</strong> #expectedKey#</p>
                        <hr>
                        <p><em>This is an automated notification from the Bulk Import AI API</em></p>
                    </cfmail>
                    <cfcatch type="any">
                     </cfcatch>
                </cftry>--->
            <cfelse>   
                <cfheader statuscode="401" statustext="Unauthorized">
                <cfset result.message = "Invalid username or password" />
                
                <!--- Send authentication failure email notification --->
                <cftry>
                    <cfmail to="#this.notificationEmails#" 
                            from="error@myhomecarebiz.com" 
                            subject="Bulk Import AI API - AUTHENTICATION FAILED" 
                            type="html">
                        <h3 style="color: red;">Bulk Import AI - Authentication Failed!</h3>
                        <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                        <p><strong>Reason:</strong> Invalid API Key</p>
                        <p><strong>Agency ID:</strong> #arguments.agency_id#</p>
                        <p><strong>Employee ID:</strong> #arguments.emp_id#</p>
                        <p><strong>IP Address:</strong> #CGI.REMOTE_ADDR#</p>
                        <p><strong>User Agent:</strong> #CGI.HTTP_USER_AGENT#</p>
                        <p><strong>Provided Key (masked):</strong> #Left(arguments.appkey, 10)#***</p>
                        <hr>
                        <p style="color: red;"><strong>Security Alert:</strong> Unauthorized access attempt detected.</p>
                        <hr>
                        <p><em>This is an automated security notification from the Bulk Import AI API</em></p>
                    </cfmail>
                    <cfcatch type="any">
                        <!--- Silently fail if email notification fails --->
                    </cfcatch>
                </cftry>
                
                <cfreturn result />
            </cfif>
            
            

            <cfcatch type="any">
                <cfheader statuscode="500" statustext="Internal Server Error">
                <cfset result.valid = false />
                <cfset result.message = "Authentication error: " & cfcatch.message />
                
                <!--- Send authentication error email notification --->
                <cftry>
                    <cfmail to="#this.notificationEmails#" 
                            from="error@myhomecarebiz.com" 
                            subject="Bulk Import AI API - AUTHENTICATION ERROR" 
                            type="html">
                        <h3 style="color: red;">Bulk Import AI - Authentication Error!</h3>
                        <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                        <p><strong>Agency ID:</strong> #arguments.agency_id#</p>
                        <p><strong>Employee ID:</strong> #arguments.emp_id#</p>
                        <p><strong>IP Address:</strong> #CGI.REMOTE_ADDR#</p>
                        <p><strong>User Agent:</strong> #CGI.HTTP_USER_AGENT#</p>
                        <hr>
                        <h4 style="color: red;">Error Details:</h4>
                        <p><strong>Error Type:</strong> #cfcatch.type#</p>
                        <p><strong>Error Message:</strong> #cfcatch.message#</p>
                        <p><strong>Error Detail:</strong> #cfcatch.detail#</p>
                        <cfif structKeyExists(cfcatch, "TagContext") and arrayLen(cfcatch.TagContext) gt 0>
                            <p><strong>File:</strong> #cfcatch.TagContext[1].template#</p>
                            <p><strong>Line:</strong> #cfcatch.TagContext[1].line#</p>
                        </cfif>
                        <hr>
                        <h4>Stack Trace:</h4>
                        <pre>#cfcatch.stacktrace#</pre>
                        <hr>
                        <p><em>This is an automated error notification from the Bulk Import AI API</em></p>
                    </cfmail>
                    <cfcatch>
                        <!--- Silently fail if error email notification fails --->
                    </cfcatch>
                </cftry>
            </cfcatch>
        </cftry>
         <cfreturn result />
    </cffunction>
    
    <!--- Helper function to parse date --->
    <cffunction name="parseDate" access="private" returntype="any" hint="Parse date string to valid date or null">
        <cfargument name="dateString" required="yes" hint="Date string to parse">
        
        <cfif len(trim(arguments.dateString)) eq 0>
            <cfreturn "" />
        </cfif>
        
        <cftry>
            <!--- Try to parse MM/DD/YYYY format --->
            <cfif find("/", arguments.dateString)>
                <cfset var dateParts = listToArray(arguments.dateString, "/") />
                <cfif arrayLen(dateParts) eq 3>
                    <cfset var month = dateParts[1] />
                    <cfset var day = dateParts[2] />
                    <cfset var year = dateParts[3] />
                    <cfreturn createDate(year, month, day) />
                </cfif>
            </cfif>
            
            <!--- Try standard date parsing --->
            <cfif isDate(arguments.dateString)>
                <cfreturn parseDateTime(arguments.dateString) />
            </cfif>
            
            <cfcatch type="any">
                <cfreturn "" />
            </cfcatch>
        </cftry>
        
        <cfreturn "" />
    </cffunction>
    
    <!--- Helper to safely attempt decryption using application key --->
    <cffunction name="maybeDecrypt" access="private" returntype="any" hint="Attempt to decrypt hex-encoded AES values; fall back to original on failure">
        <cfargument name="value" required="yes" hint="Value to decrypt">
        <cfargument name="expectNumeric" required="no" default="false" hint="Whether the decrypted result must be numeric">
        
        <cfset var decryptedValue = arguments.value />
        <cfset var trimmedValue = "" />
        
        <cfif NOT len(trim(arguments.value))>
            <cfreturn arguments.value />
        </cfif>
        
        <cfif NOT structKeyExists(Application, "enckey") OR NOT len(Application.enckey)>
            <cfreturn arguments.value />
        </cfif>
        
        <cfset trimmedValue = trim(arguments.value) />
        
        <cftry>
            <cfset decryptedValue = decrypt(trimmedValue, Application.enckey, "AES", "Hex") />
            
            <cfif arguments.expectNumeric AND NOT isNumeric(decryptedValue)>
                <cfreturn arguments.value />
            </cfif>
            
            <cfreturn decryptedValue />
            <cfcatch type="any">
                <cfreturn arguments.value />
            </cfcatch>
        </cftry>
    </cffunction>
    
    <!--- Map patients_ai short Race to full OASIS checkbox text for pPatients (#10101) --->
    <cffunction name="mapRaceToOasisFull" access="private" returntype="string">
        <cfargument name="shortVal" type="string" required="true" />
        <cfset var s = trim(arguments.shortVal) />
        <cfif len(s) EQ 0><cfreturn "" /></cfif>
        <cfif left(s, 2) EQ "A."><cfreturn "A. White" /></cfif>
        <cfif left(s, 2) EQ "B."><cfreturn "B. Black or African American" /></cfif>
        <cfif left(s, 2) EQ "C."><cfreturn "C. American Indian or Alaska Native" /></cfif>
        <cfif left(s, 2) EQ "D."><cfreturn "D. Asian Indian" /></cfif>
        <cfif left(s, 2) EQ "E."><cfreturn "E. Chinese" /></cfif>
        <cfif left(s, 2) EQ "F."><cfreturn "F. Filipino" /></cfif>
        <cfif left(s, 2) EQ "G."><cfreturn "G. Japanese" /></cfif>
        <cfif left(s, 2) EQ "H."><cfreturn "H. Korean" /></cfif>
        <cfif left(s, 2) EQ "I."><cfreturn "I. Vietnamese" /></cfif>
        <cfif left(s, 2) EQ "J."><cfreturn "J. Other Asian" /></cfif>
        <cfif left(s, 2) EQ "K."><cfreturn "K. Native Hawaiian" /></cfif>
        <cfif left(s, 2) EQ "L."><cfreturn "L. Guamanian or Chamorro" /></cfif>
        <cfif left(s, 2) EQ "M."><cfreturn "M. Samoan" /></cfif>
        <cfif left(s, 2) EQ "N."><cfreturn "N. Other Pacific Islander" /></cfif>
        <cfif left(s, 2) EQ "X."><cfreturn "X. Patient unable to respond" /></cfif>
        <cfif left(s, 2) EQ "Y."><cfreturn "Y. Patient declines to respond" /></cfif>
        <cfif left(s, 2) EQ "Z."><cfreturn "Z. None of the above" /></cfif>
        <cfif uCase(s) EQ "PLACEHOLDER"><cfreturn "PLACEHOLDER" /></cfif>

        <cfset var u = uCase(s) />
        <cfif u EQ "A" OR u EQ "WHITE"><cfreturn "A. White" /></cfif>

        <!--- #10127 explicit rule: black -> B --->
        <cfif u EQ "B" OR findNoCase("BLACK", s) GT 0 OR findNoCase("AFRICAN AM", s) GT 0><cfreturn "B. Black or African American" /></cfif>

        <cfif u EQ "C" OR findNoCase("AMERICAN INDIAN", s) GT 0 OR findNoCase("ALASKA NATIVE", s) GT 0 OR findNoCase("AMERICAN I", s) GT 0><cfreturn "C. American Indian or Alaska Native" /></cfif>

        <cfif u EQ "D" OR findNoCase("ASIAN INDIAN", s) GT 0 OR findNoCase("ASIAN INDI", s) GT 0><cfreturn "D. Asian Indian" /></cfif>

        <cfif u EQ "E" OR findNoCase("CHINESE", s) GT 0><cfreturn "E. Chinese" /></cfif>
        <cfif u EQ "F" OR findNoCase("FILIPINO", s) GT 0><cfreturn "F. Filipino" /></cfif>
        <cfif u EQ "G" OR findNoCase("JAPANESE", s) GT 0><cfreturn "G. Japanese" /></cfif>
        <cfif u EQ "H" OR findNoCase("KOREAN", s) GT 0><cfreturn "H. Korean" /></cfif>
        <cfif u EQ "I" OR findNoCase("VIETNAMESE", s) GT 0><cfreturn "I. Vietnamese" /></cfif>

        <!--- #10127 explicit rule: generic asian -> J --->
        <cfif u EQ "J" OR findNoCase("OTHER ASIAN", s) GT 0 OR (findNoCase("ASIAN", s) GT 0 AND findNoCase("ASIAN INDI", s) EQ 0)><cfreturn "J. Other Asian" /></cfif>

        <cfif u EQ "K" OR findNoCase("NATIVE HAWAIIAN", s) GT 0 OR findNoCase("NATIVE HAW", s) GT 0><cfreturn "K. Native Hawaiian" /></cfif>
        <cfif u EQ "L" OR findNoCase("GUAMANIAN", s) GT 0 OR findNoCase("CHAMORRO", s) GT 0><cfreturn "L. Guamanian or Chamorro" /></cfif>
        <cfif u EQ "M" OR findNoCase("SAMOAN", s) GT 0><cfreturn "M. Samoan" /></cfif>
        <cfif u EQ "N" OR findNoCase("PACIFIC ISLANDER", s) GT 0><cfreturn "N. Other Pacific Islander" /></cfif>
        <cfif u EQ "X" OR findNoCase("UNABLE TO RESPOND", s) GT 0><cfreturn "X. Patient unable to respond" /></cfif>
        <cfif u EQ "Y" OR findNoCase("DECLINES TO RESPOND", s) GT 0 OR findNoCase("DECLINED", s) GT 0><cfreturn "Y. Patient declines to respond" /></cfif>
        <cfif u EQ "Z" OR findNoCase("NONE OF THE ABOVE", s) GT 0 OR u EQ "NONE"><cfreturn "Z. None of the above" /></cfif>

        <!--- #10127 explicit rule: no direct match -> PLACEHOLDER --->
        <cfreturn "PLACEHOLDER" />
    </cffunction>
    <!--- Map patients_ai short Ethnicity to full OASIS radio text for pPatients (#10101); e.g. "1" = first radio --->
    <cffunction name="mapEthnicityToOasisFull" access="private" returntype="string">
        <cfargument name="shortVal" type="string" required="true" />
        <cfset var s = trim(arguments.shortVal) />
        <cfif len(s) EQ 0><cfreturn arguments.shortVal /></cfif>
        <cfif left(s, 2) EQ "A." OR left(s, 2) EQ "B." OR left(s, 2) EQ "C." OR left(s, 2) EQ "D." OR left(s, 2) EQ "E." OR left(s, 2) EQ "X." OR left(s, 2) EQ "Y."><cfreturn s /></cfif>
        <cfset var u = uCase(left(s, 1)) />
        <cfif u EQ "1" OR u EQ "A"><cfreturn "A. No, not of Hispanic, Latino/a, or Spanish origin" /></cfif>
        <cfif u EQ "2" OR u EQ "B"><cfreturn "B. Yes, Mexican, Mexican American, Chicano/a" /></cfif>
        <cfif u EQ "3" OR u EQ "C"><cfreturn "C. Yes, Puerto Rican" /></cfif>
        <cfif u EQ "4" OR u EQ "D"><cfreturn "D. Yes, Cuban" /></cfif>
        <cfif u EQ "5" OR u EQ "E"><cfreturn "E. Yes, Another Hispanic, Latino, or Spanish origin" /></cfif>
        <cfif u EQ "X"><cfreturn "X. Patient unable to respond" /></cfif>
        <cfif u EQ "Y"><cfreturn "Y. Patient declines to respond" /></cfif>
        <cfif uCase(s) EQ "PLACEHOLDER"><cfreturn "PLACEHOLDER" /></cfif>
        <cfreturn s />
    </cffunction>
    
    <!--- Helper: Send success email notification --->
    <cffunction name="sendSuccessEmail" access="private" returntype="void" hint="Send success email notification">
        <cfargument name="insertedPatientID" type="numeric" required="yes">
        <cfargument name="patientAction" type="string" required="yes">
        <cfargument name="insertedContactID" type="numeric" required="yes">
        <cfargument name="contactInserted" type="boolean" required="yes">
        <cfargument name="insertedPayerID" type="numeric" required="yes">
        <cfargument name="payerInserted" type="boolean" required="yes">
        <cfargument name="insertedAdmitID" type="numeric" required="yes">
        <cfargument name="admitInserted" type="boolean" required="yes">
        <cfargument name="medicationCount" type="numeric" required="yes">
        <cfargument name="problemCount" type="numeric" required="yes">
        <cfargument name="errors" type="array" required="yes">
        <cfargument name="agencyID" type="numeric" required="yes">
        <cfargument name="empID" type="numeric" required="yes">
        <cfargument name="patientID" type="numeric" required="yes">
        <cfargument name="assessmentID" type="numeric" required="yes">
        <cfargument name="websiteName" type="string" required="yes">
        <cfargument name="extractedJSONString" type="string" required="yes">
        <cfargument name="originalAgencyID" type="string" required="yes">
        <cfargument name="originalEmpID" type="string" required="yes">
        <cfargument name="originalPatientID" type="string" required="yes">
        <cfargument name="originalAssessmentID" type="string" required="yes">
        <cfargument name="originalAppKey" type="string" required="yes">
        <cfargument name="decryptedAgencyID" type="string" required="yes">
        <cfargument name="decryptedEmpID" type="string" required="yes">
        <cfargument name="decryptedPatientID" type="string" required="yes">
        <cfargument name="decryptedAssessmentID" type="string" required="yes">
        <cfargument name="decryptedAppKey" type="string" required="yes">
        <cfargument name="agency_db" type="string" required="yes">
        
        <cftry>
            <cfmail to="#this.notificationEmails#" 
                    from="success@myhomecarebiz.com" 
                    subject="Bulk Import AI API - Success: Patient AI ID #arguments.insertedPatientID#" 
                    type="html">
                <h3 style="color: green;">Bulk Import AI - Patient Data Imported Successfully!</h3>
                <p><strong>Agency ID:</strong> #arguments.agencyID#</p>
                <p><strong>Employee ID:</strong> #arguments.empID#</p>
                <p><strong>Patient ID:</strong> #arguments.patientID#</p>
                <p><strong>Assessment ID:</strong> #arguments.assessmentID#</p>
                <cfif len(trim(arguments.websiteName)) gt 0>
                    <p><strong>Website:</strong> #arguments.websiteName#</p>
                </cfif>
                <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                <hr>
                <h4>Encryption IDs and AppKeys:</h4>
                <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse; width: 100%;">
                    <tr style="background-color: ##f0f0f0;">
                        <th style="text-align: left;">Field</th>
                        <th style="text-align: left;">Original (Encrypted)</th>
                        <th style="text-align: left;">Decrypted Value</th>
                        <th style="text-align: left;">Was Encrypted</th>
                    </tr>
                    <tr>
                        <td><strong>Agency_ID</strong></td>
                        <td><code>#htmlEditFormat(arguments.originalAgencyID)#</code></td>
                        <td><code>#htmlEditFormat(arguments.decryptedAgencyID)#</code></td>
                        <td>#iif(arguments.decryptedAgencyID NEQ arguments.originalAgencyID, DE('Yes'), DE('No'))#</td>
                    </tr>
                    <tr>
                        <td><strong>Emp_ID</strong></td>
                        <td><code>#htmlEditFormat(arguments.originalEmpID)#</code></td>
                        <td><code>#htmlEditFormat(arguments.decryptedEmpID)#</code></td>
                        <td>#iif(arguments.decryptedEmpID NEQ arguments.originalEmpID, DE('Yes'), DE('No'))#</td>
                    </tr>
                    <tr>
                        <td><strong>Patient_ID</strong></td>
                        <td><code>#htmlEditFormat(arguments.originalPatientID)#</code></td>
                        <td><code>#htmlEditFormat(arguments.decryptedPatientID)#</code></td>
                        <td>#iif(arguments.decryptedPatientID NEQ arguments.originalPatientID, DE('Yes'), DE('No'))#</td>
                    </tr>
                    <tr>
                        <td><strong>Assessment_ID</strong></td>
                        <td><code>#htmlEditFormat(arguments.originalAssessmentID)#</code></td>
                        <td><code>#htmlEditFormat(arguments.decryptedAssessmentID)#</code></td>
                        <td>#iif(arguments.decryptedAssessmentID NEQ arguments.originalAssessmentID, DE('Yes'), DE('No'))#</td>
                    </tr>
                    <tr>
                        <td><strong>appkey</strong></td>
                        <td><code>#htmlEditFormat(arguments.originalAppKey)#</code></td>
                        <td><code>#htmlEditFormat(arguments.decryptedAppKey)#</code></td>
                        <td>#iif(len(arguments.decryptedAppKey) GT 0 AND arguments.decryptedAppKey NEQ arguments.originalAppKey, DE('Yes'), DE('No'))#</td>
                    </tr>
                </table>
                <cfif structKeyExists(Application, "enckey") AND len(Application.enckey)>
                    <p><strong>Encryption Key Available:</strong> Yes (Length: #len(Application.enckey)#)</p>
                <cfelse>
                    <p><strong>Encryption Key Available:</strong> No</p>
                </cfif>
                <hr>
                <h4>Import Results:</h4>
                <ul>
                    <li><strong>Patient AI ID:</strong> #arguments.insertedPatientID# (#arguments.patientAction#)</li>
                    <cfif arguments.insertedContactID gt 0>
                        <li><strong>Emergency Contact:</strong> #iif(arguments.contactInserted, DE('Inserted'), DE('Updated'))# (ID: #arguments.insertedContactID#)</li>
                    </cfif>
                    <cfif arguments.insertedPayerID gt 0>
                        <li><strong>Payer/Subscriber:</strong> #iif(arguments.payerInserted, DE('Inserted'), DE('Updated'))# (ID: #arguments.insertedPayerID#)</li>
                    </cfif>
                    <cfif arguments.insertedAdmitID gt 0>
                        <li><strong>Admission Record:</strong> #iif(arguments.admitInserted, DE('Inserted'), DE('Updated'))# (ID: #arguments.insertedAdmitID#)</li>
                    </cfif>
                    <cfif arguments.medicationCount gt 0>
                        <li><strong>Medications:</strong> #arguments.medicationCount# record(s) inserted</li>
                    </cfif>
                    <cfif arguments.problemCount gt 0>
                        <li><strong>Problems/Diagnoses:</strong> #arguments.problemCount# record(s) inserted/updated</li>
                    </cfif>
                </ul>
                <cfif len(trim(arguments.extractedJSONString)) gt 0>
                    <hr>
                    <h4>Extracted Data (JSON):</h4>
                    <pre style="white-space: pre-wrap; font-family: monospace;">#htmlEditFormat(arguments.extractedJSONString)#</pre>
                </cfif>
                <cfif arrayLen(arguments.errors) gt 0>
                    <hr>
                    <h4 style="color: orange;">Partial Errors:</h4>
                    <ul>
                        <cfloop array="#arguments.errors#" index="err">
                            <li style="color: orange;">#err#</li>
                        </cfloop>
                    </ul>
                </cfif>
                <hr>
                <h4>Debug Information:</h4>
                <ul>
                    <li><strong>Datasource:</strong> #Application.DataSrc#</li>
                    <li><strong>Agency Database:</strong> #arguments.agency_db#</li>
                    <li><strong>Transaction Status:</strong> Committed Successfully</li>
                </ul>
                <hr>
                <p><em>This is an automated notification from the Bulk Import AI API</em></p>
            </cfmail>
            <cfcatch type="any">
                <!--- Silently fail if email notification fails --->
            </cfcatch>
        </cftry>
    </cffunction>
    
    <!--- Helper: Send error email notification --->
    <cffunction name="sendErrorEmail" access="private" returntype="void" hint="Send error email notification">
        <cfargument name="error" type="any" required="yes">
        <cfargument name="agencyID" type="numeric" required="yes">
        <cfargument name="empID" type="numeric" required="yes">
        <cfargument name="patientID" type="numeric" required="yes">
        <cfargument name="assessmentID" type="numeric" required="yes">
        <cfargument name="websiteName" type="string" required="yes">
        <cfargument name="extractedJSONString" type="string" required="yes">
        <cfargument name="originalAgencyID" type="string" required="yes">
        <cfargument name="originalEmpID" type="string" required="yes">
        <cfargument name="originalPatientID" type="string" required="yes">
        <cfargument name="originalAssessmentID" type="string" required="yes">
        <cfargument name="originalAppKey" type="string" required="yes">
        <cfargument name="decryptedAgencyID" type="string" required="yes">
        <cfargument name="decryptedEmpID" type="string" required="yes">
        <cfargument name="decryptedPatientID" type="string" required="yes">
        <cfargument name="decryptedAssessmentID" type="string" required="yes">
        <cfargument name="decryptedAppKey" type="string" required="yes">
        <cfargument name="insertedPatientID" type="numeric" required="yes">
        <cfargument name="medicationCount" type="numeric" required="yes">
        <cfargument name="problemCount" type="numeric" required="yes">
        <cfargument name="errors" type="array" required="yes">
        
        <cfset var errorType = structKeyExists(arguments.error, "type") ? arguments.error.type : "Unknown" />
        <cfset var errorMessage = structKeyExists(arguments.error, "message") ? arguments.error.message : "Unknown error" />
        <cfset var errorDetail = structKeyExists(arguments.error, "detail") ? arguments.error.detail : "" />
        <cfset var errorStacktrace = structKeyExists(arguments.error, "stacktrace") ? arguments.error.stacktrace : "" />
        <cfset var errorTagContext = structKeyExists(arguments.error, "TagContext") ? arguments.error.TagContext : [] />
        
        <cftry>
            <cfmail to="#this.notificationEmails#" 
                    from="error@myhomecarebiz.com" 
                    subject="Bulk Import AI API - ERROR: Agency #arguments.agencyID#" 
                    type="html">
                <h3 style="color: red;">Bulk Import AI - Patient Data Import Failed!</h3>
                <p><strong>Agency ID:</strong> #arguments.agencyID#</p>
                <p><strong>Employee ID:</strong> #arguments.empID#</p>
                <p><strong>Patient ID:</strong> #arguments.patientID#</p>
                <p><strong>Assessment ID:</strong> #arguments.assessmentID#</p>
                <cfif len(trim(arguments.websiteName)) gt 0>
                    <p><strong>Website:</strong> #arguments.websiteName#</p>
                </cfif>
                <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                <hr>
                <h4>Error Information:</h4>
                <p><strong>Error Type:</strong> #errorType#</p>
                <p><strong>Error Message:</strong> #errorMessage#</p>
                <p><strong>Error Detail:</strong> #errorDetail#</p>
                <cfif arrayLen(errorTagContext) gt 0>
                    <p><strong>File:</strong> #errorTagContext[1].template#</p>
                    <p><strong>Line:</strong> #errorTagContext[1].line#</p>
                </cfif>
                <hr>
                <h4>Encryption IDs and AppKeys:</h4>
                <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse; width: 100%;">
                    <tr style="background-color: ##f0f0f0;">
                        <th style="text-align: left;">Field</th>
                        <th style="text-align: left;">Original (Encrypted)</th>
                        <th style="text-align: left;">Decrypted Value</th>
                        <th style="text-align: left;">Was Encrypted</th>
                    </tr>
                    <tr>
                        <td><strong>Agency_ID</strong></td>
                        <td><code>#htmlEditFormat(arguments.originalAgencyID)#</code></td>
                        <td><code>#htmlEditFormat(arguments.decryptedAgencyID)#</code></td>
                        <td>#iif(arguments.decryptedAgencyID NEQ arguments.originalAgencyID, DE('Yes'), DE('No'))#</td>
                    </tr>
                    <tr>
                        <td><strong>Emp_ID</strong></td>
                        <td><code>#htmlEditFormat(arguments.originalEmpID)#</code></td>
                        <td><code>#htmlEditFormat(arguments.decryptedEmpID)#</code></td>
                        <td>#iif(arguments.decryptedEmpID NEQ arguments.originalEmpID, DE('Yes'), DE('No'))#</td>
                    </tr>
                    <tr>
                        <td><strong>Patient_ID</strong></td>
                        <td><code>#htmlEditFormat(arguments.originalPatientID)#</code></td>
                        <td><code>#htmlEditFormat(arguments.decryptedPatientID)#</code></td>
                        <td>#iif(arguments.decryptedPatientID NEQ arguments.originalPatientID, DE('Yes'), DE('No'))#</td>
                    </tr>
                    <tr>
                        <td><strong>Assessment_ID</strong></td>
                        <td><code>#htmlEditFormat(arguments.originalAssessmentID)#</code></td>
                        <td><code>#htmlEditFormat(arguments.decryptedAssessmentID)#</code></td>
                        <td>#iif(arguments.decryptedAssessmentID NEQ arguments.originalAssessmentID, DE('Yes'), DE('No'))#</td>
                    </tr>
                    <tr>
                        <td><strong>appkey</strong></td>
                        <td><code>#htmlEditFormat(arguments.originalAppKey)#</code></td>
                        <td><code>#htmlEditFormat(arguments.decryptedAppKey)#</code></td>
                        <td>#iif(len(arguments.decryptedAppKey) GT 0 AND arguments.decryptedAppKey NEQ arguments.originalAppKey, DE('Yes'), DE('No'))#</td>
                    </tr>
                </table>
                <cfif structKeyExists(Application, "enckey") AND len(Application.enckey)>
                    <p><strong>Encryption Key Available:</strong> Yes (Length: #len(Application.enckey)#)</p>
                <cfelse>
                    <p><strong>Encryption Key Available:</strong> No</p>
                </cfif>
                <hr>
                <h4>Partial Import Results (before error):</h4>
                <ul>
                    <li><strong>Patient AI ID:</strong> #arguments.insertedPatientID#</li>
                    <li><strong>Medications:</strong> #arguments.medicationCount# record(s)</li>
                    <li><strong>Problems/Diagnoses:</strong> #arguments.problemCount# record(s)</li>
                </ul>
                <cfif arrayLen(arguments.errors) gt 0>
                    <hr>
                    <h4>Previous Errors:</h4>
                    <ul>
                        <cfloop array="#arguments.errors#" index="err">
                            <li style="color: orange;">#err#</li>
                        </cfloop>
                    </ul>
                </cfif>
                <cfif len(trim(arguments.extractedJSONString)) gt 0>
                    <hr>
                    <h4>Extracted Data (JSON):</h4>
                    <pre style="white-space: pre-wrap; font-family: monospace;">#htmlEditFormat(arguments.extractedJSONString)#</pre>
                </cfif>
                <hr>
                <h4>Stack Trace:</h4>
                <pre style="white-space: pre-wrap; font-family: monospace;">#htmlEditFormat(errorStacktrace)#</pre>
                <hr>
                <p><em>This is an automated error notification from the Bulk Import AI API</em></p>
            </cfmail>
            <cfcatch type="any">
                <!--- Silently fail if email notification fails --->
            </cfcatch>
        </cftry>
    </cffunction>
    
    <!--- Helper: Send exception email for processPatientData --->
    <cffunction name="sendProcessPatientDataExceptionEmail" access="private" returntype="void" hint="Send email notification for processPatientData exceptions">
        <cfargument name="error" type="any" required="yes">
        <cfargument name="agencyID" type="numeric" required="yes">
        <cfargument name="empID" type="numeric" required="yes">
        <cfargument name="patientID" type="numeric" required="yes">
        <cfargument name="agency_db" type="string" required="yes">
        <cfargument name="data" type="struct" required="yes">
        
        <cfset var errorType = structKeyExists(arguments.error, "type") ? arguments.error.type : "Unknown" />
        <cfset var errorMessage = structKeyExists(arguments.error, "message") ? arguments.error.message : "Unknown error" />
        <cfset var errorDetail = structKeyExists(arguments.error, "detail") ? arguments.error.detail : "" />
        <cfset var errorStacktrace = structKeyExists(arguments.error, "stacktrace") ? arguments.error.stacktrace : "" />
        <cfset var errorTagContext = structKeyExists(arguments.error, "TagContext") ? arguments.error.TagContext : [] />
        
        <cftry>
            <cfmail to="#this.notificationEmails#" 
                    from="error@myhomecarebiz.com" 
                    subject="Bulk Import AI API - processPatientData Exception Error" 
                    type="html">
                <h3 style="color: red;">processPatientData Exception Error</h3>
                <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                <p><strong>Agency ID:</strong> #arguments.agencyID#</p>
                <p><strong>Employee ID:</strong> #arguments.empID#</p>
                <p><strong>Patient ID:</strong> #arguments.patientID#</p>
                <p><strong>Agency Database:</strong> #arguments.agency_db#</p>
                <hr>
                <h4>Error Information:</h4>
                <p><strong>Error Type:</strong> #errorType#</p>
                <p><strong>Error Message:</strong> #errorMessage#</p>
                <p><strong>Error Detail:</strong> #errorDetail#</p>
                <cfif arrayLen(errorTagContext) gt 0>
                    <p><strong>File:</strong> #errorTagContext[1].template#</p>
                    <p><strong>Line:</strong> #errorTagContext[1].line#</p>
                </cfif>
                <hr>
                <h4>Input Data (pPatient):</h4>
                <cfif structKeyExists(arguments.data, "pPatient")>
                    <pre style="white-space: pre-wrap; font-family: monospace; background-color: ##f5f5f5; padding: 10px;">#htmlEditFormat(serializeJSON(arguments.data.pPatient))#</pre>
                <cfelse>
                    <p>No pPatient data provided</p>
                </cfif>
                <hr>
                <h4>Stack Trace:</h4>
                <pre style="white-space: pre-wrap; font-family: monospace; background-color: ##f5f5f5; padding: 10px;">#htmlEditFormat(errorStacktrace)#</pre>
                <hr>
                <p><em>This is an automated error notification from the Bulk Import AI API</em></p>
            </cfmail>
            <cfcatch type="any">
                <!--- Silently fail if email notification fails --->
            </cfcatch>
        </cftry>
    </cffunction>
    
    <!--- Helper: Send generic module exception email --->
    <cffunction name="sendModuleExceptionEmail" access="private" returntype="void" hint="Send email notification for module exceptions">
        <cfargument name="moduleName" type="string" required="yes">
        <cfargument name="error" type="any" required="yes">
        <cfargument name="agencyID" type="numeric" required="yes">
        <cfargument name="empID" type="numeric" required="yes">
        <cfargument name="patientID" type="numeric" required="yes">
        <cfargument name="agency_db" type="string" required="yes">
        <cfargument name="inputData" type="any" required="no" default="">
        
        <cfset var errorType = structKeyExists(arguments.error, "type") ? arguments.error.type : "Unknown" />
        <cfset var errorMessage = structKeyExists(arguments.error, "message") ? arguments.error.message : "Unknown error" />
        <cfset var errorDetail = structKeyExists(arguments.error, "detail") ? arguments.error.detail : "" />
        <cfset var errorStacktrace = structKeyExists(arguments.error, "stacktrace") ? arguments.error.stacktrace : "" />
        <cfset var errorTagContext = structKeyExists(arguments.error, "TagContext") ? arguments.error.TagContext : [] />
        
        <cftry>
            <cfmail to="#this.notificationEmails#" 
                    from="error@myhomecarebiz.com" 
                    subject="Bulk Import AI API - #arguments.moduleName# Exception Error" 
                    type="html">
                <h3 style="color: red;">#arguments.moduleName# Exception Error</h3>
                <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                <p><strong>Module:</strong> #arguments.moduleName#</p>
                <p><strong>Agency ID:</strong> #arguments.agencyID#</p>
                <p><strong>Employee ID:</strong> #arguments.empID#</p>
                <p><strong>Patient ID:</strong> #arguments.patientID#</p>
                <p><strong>Agency Database:</strong> #arguments.agency_db#</p>
                <hr>
                <h4>Error Information:</h4>
                <p><strong>Error Type:</strong> #errorType#</p>
                <p><strong>Error Message:</strong> #errorMessage#</p>
                <p><strong>Error Detail:</strong> #errorDetail#</p>
                <cfif arrayLen(errorTagContext) gt 0>
                    <p><strong>File:</strong> #errorTagContext[1].template#</p>
                    <p><strong>Line:</strong> #errorTagContext[1].line#</p>
                </cfif>
                <cfif isStruct(arguments.inputData) AND NOT structIsEmpty(arguments.inputData)>
                    <hr>
                    <h4>Input Data:</h4>
                    <pre style="white-space: pre-wrap; font-family: monospace; background-color: ##f5f5f5; padding: 10px;">#htmlEditFormat(serializeJSON(arguments.inputData))#</pre>
                </cfif>
                <hr>
                <h4>Stack Trace:</h4>
                <pre style="white-space: pre-wrap; font-family: monospace; background-color: ##f5f5f5; padding: 10px;">#htmlEditFormat(errorStacktrace)#</pre>
                <hr>
                <p><em>This is an automated error notification from the Bulk Import AI API</em></p>
            </cfmail>
            <cfcatch type="any">
                <!--- Silently fail if email notification fails --->
            </cfcatch>
        </cftry>
    </cffunction>
    
    <!--- Helper: Send update action email --->
    <cffunction name="sendUpdateActionEmail" access="private" returntype="void" hint="Send email notification for update query actions">
        <cfargument name="action" type="string" required="yes">
        <cfargument name="table" type="string" required="yes">
        <cfargument name="recordID" type="string" required="yes">
        <cfargument name="agencyID" type="numeric" required="yes">
        <cfargument name="empID" type="numeric" required="yes">
        <cfargument name="patientID" type="numeric" required="yes">
        <cfargument name="agency_db" type="string" required="yes">
        <cfargument name="querySQL" type="string" required="yes">
        <cfargument name="rowsAffected" type="numeric" required="no" default="0">
        
        <cftry>
            <cfmail to="#this.notificationEmails#" 
                    from="update@myhomecarebiz.com" 
                    subject="Bulk Import AI API - Update Action: #arguments.action# on #arguments.table#" 
                    type="html">
                <h3 style="color: blue;">Update Action Notification</h3>
                <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                <p><strong>Action:</strong> #arguments.action#</p>
                <p><strong>Table:</strong> #arguments.table#</p>
                <p><strong>Record ID:</strong> #arguments.recordID#</p>
                <p><strong>Agency ID:</strong> #arguments.agencyID#</p>
                <p><strong>Employee ID:</strong> #arguments.empID#</p>
                <p><strong>Patient ID:</strong> #arguments.patientID#</p>
                <p><strong>Agency Database:</strong> #arguments.agency_db#</p>
                <cfif arguments.rowsAffected gt 0>
                    <p><strong>Rows Affected:</strong> #arguments.rowsAffected#</p>
                </cfif>
                <hr>
                <h4>SQL Query:</h4>
                <pre style="white-space: pre-wrap; font-family: monospace; background-color: ##f5f5f5; padding: 10px;">#htmlEditFormat(arguments.querySQL)#</pre>
                <hr>
                <p><em>This is an automated notification from the Bulk Import AI API</em></p>
            </cfmail>
            <cfcatch type="any">
                <!--- Silently fail if email notification fails --->
            </cfcatch>
        </cftry>
    </cffunction>
    
    <!--- Helper: Log query for debugging --->
    <cffunction name="logQuery" access="private" returntype="void" hint="Log query for debugging purposes">
        <cfargument name="queryName" type="string" required="yes">
        <cfargument name="querySQL" type="string" required="yes">
        <cfargument name="queryResult" type="any" required="no">
        
        <!--- Store queries in request scope for email dumping --->
        <cfif not structKeyExists(request, "bulk_import_queries")>
            <cfset request.bulk_import_queries = [] />
        </cfif>
        
        <cfset var queryInfo = {
            name: arguments.queryName,
            sql: arguments.querySQL,
            timestamp: now(),
            hasResult: structKeyExists(arguments, "queryResult"),
            recordCount: structKeyExists(arguments, "queryResult") and isQuery(arguments.queryResult) ? arguments.queryResult.recordcount : 0
        } />
        
        <cfset arrayAppend(request.bulk_import_queries, queryInfo) />
    </cffunction>
    
    <!--- Helper: Send query dump email --->
    <cffunction name="sendQueryDumpEmail" access="private" returntype="void" hint="Send email with all queries executed">
        <cfargument name="agencyID" type="numeric" required="yes">
        <cfargument name="empID" type="numeric" required="yes">
        <cfargument name="patientID" type="numeric" required="yes">
        <cfargument name="agency_db" type="string" required="yes">
        
        <cftry>
            <cfif structKeyExists(request, "bulk_import_queries") and arrayLen(request.bulk_import_queries) gt 0>
                <cfmail to="#this.notificationEmails#" 
                        from="queries@myhomecarebiz.com" 
                        subject="Bulk Import AI API - Query Dump: Patient ID #arguments.patientID#" 
                        type="html">
                    <h3 style="color: green;">Query Dump - All Executed Queries</h3>
                    <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                    <p><strong>Agency ID:</strong> #arguments.agencyID#</p>
                    <p><strong>Employee ID:</strong> #arguments.empID#</p>
                    <p><strong>Patient ID:</strong> #arguments.patientID#</p>
                    <p><strong>Agency Database:</strong> #arguments.agency_db#</p>
                    <p><strong>Total Queries:</strong> #arrayLen(request.bulk_import_queries)#</p>
                    <hr>
                    <h4>All Queries:</h4>
                    <cfloop array="#request.bulk_import_queries#" index="queryInfo">
                        <div style="margin-bottom: 20px; border: 1px solid ##ddd; padding: 10px; background-color: ##f9f9f9;">
                            <p><strong>Query Name:</strong> #queryInfo.name#</p>
                            <p><strong>Timestamp:</strong> #DateFormat(queryInfo.timestamp, 'mm/dd/yyyy')# #TimeFormat(queryInfo.timestamp, 'HH:mm:ss')#</p>
                            <cfif queryInfo.hasResult>
                                <p><strong>Record Count:</strong> #queryInfo.recordCount#</p>
                            </cfif>
                            <p><strong>SQL:</strong></p>
                            <pre style="white-space: pre-wrap; font-family: monospace; background-color: ##fff; padding: 10px; border: 1px solid ##ccc; overflow-x: auto;">#htmlEditFormat(queryInfo.sql)#</pre>
                        </div>
                    </cfloop>
                    <hr>
                    <p><em>This is an automated query dump from the Bulk Import AI API</em></p>
                </cfmail>
            </cfif>
            <cfcatch type="any">
                <!--- Silently fail if email notification fails --->
            </cfcatch>
        </cftry>
    </cffunction>
    
    <!--- Helper function to process patient data --->
    <!--- NOTE: All exceptions in this function will send email notifications --->
    <cffunction name="processPatientData" access="private" returntype="struct" hint="Process patient data insertion/update">
        <cfargument name="data" required="yes" type="struct" />
        <cfargument name="agency_db" required="yes" type="string" />
        <cfargument name="created_by" required="yes" type="numeric" />
        <cfargument name="patient_id" required="yes" type="numeric" />
        
        <cfset var result = {"insertedPatientID" = 0, "patientAction" = "none", "errors" = []} />
        
        <!--- Initialize all patient variables to avoid undefined errors --->
        <cfset var ptFirst = "" />
        <cfset var ptMiddle = "" />
        <cfset var ptLast = "" />
        <cfset var ptSuffix = "" />
        <cfset var ptStreet = "" />
        <cfset var ptCity = "" />
        <cfset var ptState = "" />
        <cfset var ptZip = "" />
        <cfset var ptPhone = "" />
        <cfset var ptGender = "" />
        <cfset var ptRace = "" />
        <cfset var m0140Ethnic = "" />
        <cfset var ptLanguage = "" />
        <cfset var ptInterpreter = "" />
        <cfset var ptAllergies = "" />
        <cfset var ptSSN = "" />
        <cfset var ptEmail = "" />
        <cfset var ptSpecificConcerns = "" />
        <cfset var ptAgyID = "" />
        <cfset var ptDOB = "" />
        <cfset var pPatient = {} />
        <cfset var pPayer = {} />
        
        <!--- Check if data is nested under pPatient or if it's at the root level --->
        <cfif structKeyExists(data, "pPatient")>
            <cfset pPatient = data.pPatient />
            <cfset pPayer = structKeyExists(data, "pPayer") ? data.pPayer : {} />
        <cfelseif structKeyExists(data, "Pt_Street") OR structKeyExists(data, "Pt_First")>
            <!--- Data is at root level, use it directly --->
            <cfset pPatient = data />
            <cfset pPayer = structKeyExists(data, "pPayer") ? data.pPayer : {} />
        </cfif>
        
        <!--- Extract DOB if available; support MM-DD-YYYY, MM/DD/YYYY, YYYY-MM-DD --->
        <cfif structKeyExists(pPatient, "Pt_DOB") AND len(trim(pPatient.Pt_DOB)) GT 0>
            <cfset var dobStr = trim(pPatient.Pt_DOB) />
            <cftry>
                <!--- Try parseDate first --->
                <cfset ptDOB = parseDate(dobStr) />
                <cfcatch>
                    <cftry>
                        <cfset ptDOB = parseDateTime(dobStr) />
                        <cfcatch>
                            <!--- Manual parse: YYYY-MM-DD vs MM-DD-YYYY / MM/DD/YYYY --->
                            <cfset var dobParts = listToArray(reReplace(dobStr, "[/\-]", ",", "ALL"), ",") />
                            <cfif arrayLen(dobParts) GTE 3>
                                <cfset var yr = 0 /><cfset var mo = 0 /><cfset var dy = 0 />
                                <cfif val(dobParts[1]) GT 31>
                                    <cfset yr = val(dobParts[1]) /><cfset mo = val(dobParts[2]) /><cfset dy = val(dobParts[3]) />
                                <cfelse>
                                    <cfset mo = val(dobParts[1]) /><cfset dy = val(dobParts[2]) /><cfset yr = val(dobParts[3]) />
                                </cfif>
                                <cfif yr GTE 1900 AND yr LTE 2100 AND mo GTE 1 AND mo LTE 12 AND dy GTE 1 AND dy LTE 31>
                                    <cfset ptDOB = createDate(yr, mo, dy) />
                                <cfelse>
                                    <cfset ptDOB = "" />
                                </cfif>
                            <cfelse>
                                <cfset ptDOB = "" />
                            </cfif>
                        </cfcatch>
                    </cftry>
                </cfcatch>
            </cftry>
        </cfif>
        
        <!--- Extract all patient data from pPatient structure (before any queries) --->
        <cfif NOT structIsEmpty(pPatient)>
            <cfset ptFirst = structKeyExists(pPatient, "Pt_First") ? trim(pPatient.Pt_First) : "" />
            <cfset ptMiddle = structKeyExists(pPatient, "Pt_Middle") ? trim(pPatient.Pt_Middle) : "" />
            <cfset ptLast = structKeyExists(pPatient, "Pt_Last") ? trim(pPatient.Pt_Last) : "" />
            <cfset ptSuffix = structKeyExists(pPatient, "Pt_Suffix") ? trim(pPatient.Pt_Suffix) : "" />
            <cfset ptStreet = structKeyExists(pPatient, "Pt_Street") ? left(trim(pPatient.Pt_Street), 255) : "" />
            <cfset ptCity = structKeyExists(pPatient, "Pt_City") ? left(trim(pPatient.Pt_City), 100) : "" />
            <cfset ptState = structKeyExists(pPatient, "Pt_State") ? left(trim(pPatient.Pt_State), 2) : "" />
            <cfset ptZip = structKeyExists(pPatient, "Pt_Zip") ? left(trim(pPatient.Pt_Zip), 20) : "" />
            <cfset ptPhone = structKeyExists(pPatient, "Pt_Phone") ? left(trim(pPatient.Pt_Phone), 50) : "" />
            <cfset ptGender = structKeyExists(pPatient, "Pt_Gender") ? left(trim(pPatient.Pt_Gender), 1) : "" />
            <cfset ptRace = structKeyExists(pPatient, "Pt_Race") ? left(trim(pPatient.Pt_Race), 10) : "" />
            <!--- M0140_ETHNIC: patients_ai column is often VARCHAR(1); map or truncate to avoid "Data too long" --->
            <cfset var rawEthnic = structKeyExists(pPatient, "M0140_ETHNIC") ? trim(pPatient.M0140_ETHNIC) : "" />
            <cfif len(rawEthnic) GT 1>
                <cfif findNoCase("not hispanic", rawEthnic) GT 0 OR findNoCase("non-hispanic", rawEthnic) GT 0>
                    <cfset m0140Ethnic = "2" />
                <cfelseif findNoCase("hispanic", rawEthnic) GT 0>
                    <cfset m0140Ethnic = "1" />
                <cfelse>
                    <cfset m0140Ethnic = left(rawEthnic, 1) />
                </cfif>
            <cfelse>
                <cfset m0140Ethnic = rawEthnic />
            </cfif>
            <cfset ptLanguage = structKeyExists(pPatient, "Pt_language") ? trim(pPatient.Pt_language) : "" />
            <cfset ptInterpreter = structKeyExists(pPatient, "Interpreter") ? trim(pPatient.Interpreter) : "" />
            <cfset ptAllergies = structKeyExists(pPatient, "Allergies") ? trim(pPatient.Allergies) : "" />
            <cfset ptSSN = structKeyExists(pPatient, "Pt_SSN") ? trim(pPatient.Pt_SSN) : "" />
            <!--- Sanitize SSN: remove all non-digit characters and limit to 9 digits --->
            <cfif len(ptSSN) GT 0>
                <!--- Remove all non-digit characters (dashes, spaces, etc.) --->
                <cfset ptSSN = reReplace(ptSSN, "[^0-9]", "", "ALL") />
                <!--- Limit to 9 digits (standard SSN length) --->
                <cfif len(ptSSN) GT 9>
                    <!--- If longer than 9 digits, take only first 9 (likely data corruption/concatenation) --->
                    <cfset ptSSN = left(ptSSN, 9) />
                </cfif>
                <!--- If empty after cleaning or not exactly 9 digits, set to empty string --->
                <cfif len(ptSSN) NEQ 9>
                    <cfset ptSSN = "" />
                </cfif>
            </cfif>
            <cfset ptEmail = structKeyExists(pPatient, "Email") ? trim(pPatient.Email) : "" />
            <cfset ptSpecificConcerns = structKeyExists(pPatient, "Specific_Concerns") ? trim(pPatient.Specific_Concerns) : "" />
            <cfset ptAgyID = structKeyExists(pPatient, "Pt_Agy_ID") ? trim(pPatient.Pt_Agy_ID) : "" />
            <!--- Extract pAssessment fields (if provided) --->
            <cfset var a_F181 = "" />
            <cfset var a_F149 = "" />
            <cfset var a_F150 = "" />
            <cfset var a_F70  = "" />
            <cfset var a_F151 = "" />
            <cfset var a_F253 = "" />
            <cfset var a_F138 = "" />
            <cfset var a_F139 = "" />
            <cfset var a_F141 = "" />
            <cfset var a_F154 = "" />
            <cfif structKeyExists(data, "pAssessment") AND isStruct(data.pAssessment)>
                <cfset var pA = data.pAssessment />
                <cfset a_F181 = structKeyExists(pA, "F181") ? trim(pA.F181) : "" />
                <cfset a_F149 = structKeyExists(pA, "F149") ? trim(pA.F149) : "" />
                <cfset a_F150 = structKeyExists(pA, "F150") ? trim(pA.F150) : "" />
                <cfset a_F70  = structKeyExists(pA, "F70")  ? trim(pA.F70)  : "" />
                <cfset a_F151 = structKeyExists(pA, "F151") ? trim(pA.F151) : "" />
                <cfset a_F253 = structKeyExists(pA, "F253") ? trim(pA.F253) : "" />
                <cfset a_F138 = structKeyExists(pA, "F138") ? trim(pA.F138) : "" />
                <cfset a_F139 = structKeyExists(pA, "F139") ? trim(pA.F139) : "" />
                <cfset a_F141 = structKeyExists(pA, "F141") ? trim(pA.F141) : "" />
                <cfset a_F154 = structKeyExists(pA, "F154") ? trim(pA.F154) : "" />
                <!--- Normalize F181 to yyyy-mm-dd if possible --->
                <cfif len(a_F181) GT 0>
                    <cftry>
                        <cfset var parsedF181 = parseDate(a_F181) />
                        <cfset a_F181 = DateFormat(parsedF181, "yyyy-mm-dd") />
                    <cfcatch>
                        <cfset a_F181 = "" />
                    </cfcatch>
                    </cftry>
                </cfif>
            </cfif>
        </cfif>
        
        <cfif NOT structIsEmpty(pPatient)>
            
            <cftry>
                <cfset var checkSQL = "SELECT pt_ai_id FROM #agency_db#.patients_ai WHERE status = 0" />
                <cfif val(patient_id) gt 0>
                    <cfset checkSQL = checkSQL & " AND Patient_ID = " & val(patient_id) />
                <cfelse>
                    <cfset checkSQL = checkSQL & " AND Pt_First = '" & (structKeyExists(pPatient, 'Pt_First') ? pPatient.Pt_First : '') & "' AND Pt_Last = '" & (structKeyExists(pPatient, 'Pt_Last') ? pPatient.Pt_Last : '') & "'" />
                    <cfif len(trim(ptDOB)) gt 0>
                        <cfset checkSQL = checkSQL & " AND Pt_DOB = '" & ptDOB & "'" />
                    </cfif>
                </cfif>
                <cfset checkSQL = checkSQL & " ORDER BY pt_ai_id DESC LIMIT 1" />
                <cfquery name="CheckExistingPatient" datasource="#Application.DataSrc#">
                    SELECT pt_ai_id FROM #agency_db#.patients_ai WHERE status = 0
                    <cfif val(patient_id) gt 0>
                        AND Patient_ID = <cfqueryparam value="#val(patient_id)#" cfsqltype="cf_sql_integer">
                    <cfelse>
                        AND Pt_First = <cfqueryparam value="#structKeyExists(pPatient, 'Pt_First') ? pPatient.Pt_First : ''#" cfsqltype="cf_sql_varchar">
                        AND Pt_Last = <cfqueryparam value="#structKeyExists(pPatient, 'Pt_Last') ? pPatient.Pt_Last : ''#" cfsqltype="cf_sql_varchar">
                        <cfif len(trim(ptDOB)) gt 0>AND Pt_DOB = <cfqueryparam value="#ptDOB#" cfsqltype="cf_sql_date"></cfif>
                    </cfif>
                    ORDER BY pt_ai_id DESC LIMIT 1
                </cfquery>
               <!--- <cfset logQuery("CheckExistingPatient", checkSQL, CheckExistingPatient) /> --->
                
                <cfif CheckExistingPatient.recordcount gt 0>
                    <cfset result.insertedPatientID = CheckExistingPatient.pt_ai_id />
                    <cfset result.patientAction = "updated" />
                    <cfset var updateSQL = "UPDATE #agency_db#.patients_ai SET Pt_First = ?, Pt_Last = ?, Pt_DOB = ?, Pt_Gender = ?, Payer_Name = ?, policy_id_no = ?, Pt_Street = ?, Pt_City = ?, Pt_State = ?, Pt_Zip = ?, Pt_Phone = ?, Pt_Race = ?, M0140_ETHNIC = ?, Pt_language = ?, Interpreter = ?, Allergies = ?, Pt_SSN = ?, Email = ?, Specific_Concerns = ?, modified_date = ?, modified_by = ? WHERE pt_ai_id = ? AND status = 0" />
                    <cfquery name="Updatepatients_ai" datasource="#Application.DataSrc#" result="updateResult">
                        UPDATE #agency_db#.patients_ai SET
                            Pt_First = <cfqueryparam value="#ptFirst#" cfsqltype="cf_sql_varchar" null="#len(ptFirst) eq 0#">,
                            Pt_Last = <cfqueryparam value="#ptLast#" cfsqltype="cf_sql_varchar" null="#len(ptLast) eq 0#">,
                            Pt_DOB = <cfqueryparam value="#ptDOB#" cfsqltype="cf_sql_date" null="#len(trim(ptDOB)) eq 0#">,
                            Pt_Gender = <cfqueryparam value="#ptGender#" cfsqltype="cf_sql_varchar" null="#len(ptGender) eq 0#">,
                            Payer_Name = <cfqueryparam value="#structKeyExists(pPayer, 'Pay_Name') ? pPayer.Pay_Name : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Pay_Name') or len(trim(pPayer.Pay_Name)) eq 0#">,
                            policy_id_no = <cfqueryparam value="#structKeyExists(pPayer, 'Sub_HIC') ? pPayer.Sub_HIC : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Sub_HIC') or len(trim(pPayer.Sub_HIC)) eq 0#">,
                            Pt_Street = <cfqueryparam value="#ptStreet#" cfsqltype="cf_sql_varchar" null="#len(ptStreet) eq 0#">,
                            Pt_City = <cfqueryparam value="#ptCity#" cfsqltype="cf_sql_varchar" null="#len(ptCity) eq 0#">,
                            Pt_State = <cfqueryparam value="#ptState#" cfsqltype="cf_sql_varchar" null="#len(ptState) eq 0#">,
                            Pt_Zip = <cfqueryparam value="#ptZip#" cfsqltype="cf_sql_varchar" null="#len(ptZip) eq 0#">,
                            Pt_Phone = <cfqueryparam value="#ptPhone#" cfsqltype="cf_sql_varchar" null="#len(ptPhone) eq 0#">,
                            Pt_Race = <cfqueryparam value="#ptRace#" cfsqltype="cf_sql_varchar" null="#len(ptRace) eq 0#">,
                            M0140_ETHNIC = <cfqueryparam value="#m0140Ethnic#" cfsqltype="cf_sql_varchar" null="#len(m0140Ethnic) eq 0#">,
                            Pt_language = <cfqueryparam value="#ptLanguage#" cfsqltype="cf_sql_varchar" null="#len(ptLanguage) eq 0#">,
                            Interpreter = <cfqueryparam value="#ptInterpreter#" cfsqltype="cf_sql_varchar" null="#len(ptInterpreter) eq 0#">,
                            Allergies = <cfqueryparam value="#ptAllergies#" cfsqltype="cf_sql_varchar" null="#len(ptAllergies) eq 0#">,
                            Pt_SSN = <cfqueryparam value="#ptSSN#" cfsqltype="cf_sql_varchar" null="#len(ptSSN) eq 0#">,
                            Email = <cfqueryparam value="#ptEmail#" cfsqltype="cf_sql_varchar" null="#len(ptEmail) eq 0#">,
                            Specific_Concerns = <cfqueryparam value="#ptSpecificConcerns#" cfsqltype="cf_sql_varchar" null="#len(ptSpecificConcerns) eq 0#">,
                            F181 = <cfqueryparam value="#a_F181#" cfsqltype="cf_sql_date" null="#len(a_F181) eq 0#">,
                            F149 = <cfqueryparam value="#a_F149#" cfsqltype="cf_sql_varchar" null="#len(a_F149) eq 0#">,
                            F150 = <cfqueryparam value="#a_F150#" cfsqltype="cf_sql_varchar" null="#len(a_F150) eq 0#">,
                            F70  = <cfqueryparam value="#a_F70#"  cfsqltype="cf_sql_varchar" null="#len(a_F70) eq 0#">,
                            F151 = <cfqueryparam value="#a_F151#" cfsqltype="cf_sql_varchar" null="#len(a_F151) eq 0#">,
                            F253 = <cfqueryparam value="#a_F253#" cfsqltype="cf_sql_varchar" null="#len(a_F253) eq 0#">,
                            F138 = <cfqueryparam value="#a_F138#" cfsqltype="cf_sql_varchar" null="#len(a_F138) eq 0#">,
                            F139 = <cfqueryparam value="#a_F139#" cfsqltype="cf_sql_varchar" null="#len(a_F139) eq 0#">,
                            F141 = <cfqueryparam value="#a_F141#" cfsqltype="cf_sql_varchar" null="#len(a_F141) eq 0#">,
                            F154 = <cfqueryparam value="#a_F154#" cfsqltype="cf_sql_varchar" null="#len(a_F154) eq 0#">,
                            modified_date = <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                            modified_by = <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">
                        WHERE pt_ai_id = <cfqueryparam value="#result.insertedPatientID#" cfsqltype="cf_sql_integer"> AND status = 0
                    </cfquery>
                <cfelse>
                    <cfset var insertSQL = "INSERT INTO #agency_db#.patients_ai (Pt_First, Pt_Last, Pt_DOB, Pt_Gender, Payer_ID, Payer_Name, policy_id_no, Pt_Street, Pt_City, Pt_State, Pt_Zip, Pt_Phone, Pt_Race, M0140_ETHNIC, Pt_language, Interpreter, Allergies, Pt_SSN, Email, Specific_Concerns, start_of_care_date, start_of_care_type, status, created_date, created_by, modified_date, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" />
                    <cftry>
                        <cfquery name="InsertPatient" datasource="#Application.DataSrc#" result="patientResult">
                            INSERT INTO #agency_db#.patients_ai (
                                Pt_First, Pt_Last, Pt_DOB, Pt_Gender, Payer_ID, Payer_Name, policy_id_no,
                                Pt_Street, Pt_City, Pt_State, Pt_Zip, Pt_Phone,
                                Pt_Race, M0140_ETHNIC, Pt_language, Interpreter, Allergies, Pt_SSN, Email, Specific_Concerns,
                                F181, F149, F150, F70, F151, F253, F138, F139, F141, F154,
                                start_of_care_date, start_of_care_type, status, created_date, created_by,
                                modified_date, modified_by
                            ) VALUES (
                                <cfqueryparam value="#ptFirst#" cfsqltype="cf_sql_varchar" null="#len(ptFirst) eq 0#">,
                                <cfqueryparam value="#ptLast#" cfsqltype="cf_sql_varchar" null="#len(ptLast) eq 0#">,
                                <cfqueryparam value="#ptDOB#" cfsqltype="cf_sql_date" null="#len(trim(ptDOB)) eq 0#">,
                                <cfqueryparam value="#ptGender#" cfsqltype="cf_sql_varchar" null="#len(ptGender) eq 0#">,
                                <cfqueryparam value="0" cfsqltype="cf_sql_integer">,
                                <cfqueryparam value="#structKeyExists(pPayer, 'Pay_Name') ? pPayer.Pay_Name : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Pay_Name') or len(trim(pPayer.Pay_Name)) eq 0#">,
                                <cfqueryparam value="#structKeyExists(pPayer, 'Sub_HIC') ? pPayer.Sub_HIC : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Sub_HIC') or len(trim(pPayer.Sub_HIC)) eq 0#">,
                                <cfqueryparam value="#ptStreet#" cfsqltype="cf_sql_varchar" null="#len(ptStreet) eq 0#">,
                                <cfqueryparam value="#ptCity#" cfsqltype="cf_sql_varchar" null="#len(ptCity) eq 0#">,
                                <cfqueryparam value="#ptState#" cfsqltype="cf_sql_varchar" null="#len(ptState) eq 0#">,
                                <cfqueryparam value="#ptZip#" cfsqltype="cf_sql_varchar" null="#len(ptZip) eq 0#">,
                                <cfqueryparam value="#ptPhone#" cfsqltype="cf_sql_varchar" null="#len(ptPhone) eq 0#">,
                                <cfqueryparam value="#ptRace#" cfsqltype="cf_sql_varchar" null="#len(ptRace) eq 0#">,
                                <cfqueryparam value="#m0140Ethnic#" cfsqltype="cf_sql_varchar" null="#len(m0140Ethnic) eq 0#">,
                                <cfqueryparam value="#ptLanguage#" cfsqltype="cf_sql_varchar" null="#len(ptLanguage) eq 0#">,
                                <cfqueryparam value="#ptInterpreter#" cfsqltype="cf_sql_varchar" null="#len(ptInterpreter) eq 0#">,
                                <cfqueryparam value="#ptAllergies#" cfsqltype="cf_sql_varchar" null="#len(ptAllergies) eq 0#">,
                                <cfqueryparam value="#ptSSN#" cfsqltype="cf_sql_varchar" null="#len(ptSSN) eq 0#">,
                                <cfqueryparam value="#ptEmail#" cfsqltype="cf_sql_varchar" null="#len(ptEmail) eq 0#">,
                                <cfqueryparam value="#ptSpecificConcerns#" cfsqltype="cf_sql_varchar" null="#len(ptSpecificConcerns) eq 0#">,
                                <cfqueryparam value="#a_F181#" cfsqltype="cf_sql_date" null="#len(a_F181) eq 0#">,
                                <cfqueryparam value="#a_F149#" cfsqltype="cf_sql_varchar" null="#len(a_F149) eq 0#">,
                                <cfqueryparam value="#a_F150#" cfsqltype="cf_sql_varchar" null="#len(a_F150) eq 0#">,
                                <cfqueryparam value="#a_F70#"  cfsqltype="cf_sql_varchar" null="#len(a_F70) eq 0#">,
                                <cfqueryparam value="#a_F151#" cfsqltype="cf_sql_varchar" null="#len(a_F151) eq 0#">,
                                <cfqueryparam value="#a_F253#" cfsqltype="cf_sql_varchar" null="#len(a_F253) eq 0#">,
                                <cfqueryparam value="#a_F138#" cfsqltype="cf_sql_varchar" null="#len(a_F138) eq 0#">,
                                <cfqueryparam value="#a_F139#" cfsqltype="cf_sql_varchar" null="#len(a_F139) eq 0#">,
                                <cfqueryparam value="#a_F141#" cfsqltype="cf_sql_varchar" null="#len(a_F141) eq 0#">,
                                <cfqueryparam value="#a_F154#" cfsqltype="cf_sql_varchar" null="#len(a_F154) eq 0#">,
                                <cfqueryparam value="#now()#" cfsqltype="cf_sql_date">,
                                <cfqueryparam value="" cfsqltype="cf_sql_varchar" null="#true#">,
                                <cfqueryparam value="0" cfsqltype="cf_sql_tinyint">,
                                <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                                <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">,
                                <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                                <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">
                            )
                        </cfquery>
                        <!--- Get the generated key - try different property names for compatibility --->
                        <cfif structKeyExists(patientResult, "GENERATEDKEY")>
                            <cfset result.insertedPatientID = patientResult.GENERATEDKEY />
                        <cfelseif structKeyExists(patientResult, "GENERATED_KEY")>
                            <cfset result.insertedPatientID = patientResult.GENERATED_KEY />
                        <cfelseif structKeyExists(patientResult, "IDENTITYCOL")>
                            <cfset result.insertedPatientID = patientResult.IDENTITYCOL />
                        <cfelse>
                            <!--- Fallback: query for the last inserted ID --->
                            <cfquery name="GetLastID" datasource="#Application.DataSrc#">
                                SELECT LAST_INSERT_ID() AS last_id
                            </cfquery>
                            <cfif GetLastID.recordcount GT 0>
                                <cfset result.insertedPatientID = GetLastID.last_id />
                            </cfif>
                        </cfif>
                        <!--- Only log if InsertPatient query was successful and variable exists --->
                        <cfif isDefined("InsertPatient")>
                            <cftry>
                                <cfset logQuery("InsertPatient", insertSQL, InsertPatient) />
                                <cfcatch>
                                    <!--- Silently fail if logQuery fails --->
                                </cfcatch>
                            </cftry>
                        </cfif>
                        <cfcatch>
                            <!--- If query fails, provide more detailed error information --->
                            <cfset var errorDetails = "Database Error: " & cfcatch.message />
                            <cfif structKeyExists(cfcatch, "detail")>
                                <cfset errorDetails = errorDetails & " | Detail: " & cfcatch.detail />
                            </cfif>
                            <cfif structKeyExists(cfcatch, "sql")>
                                <cfset errorDetails = errorDetails & " | SQL: " & left(cfcatch.sql, 500) />
                            </cfif>
                            <cfthrow message="Patient insert failed: #errorDetails#" detail="#cfcatch.message#" />
                        </cfcatch>
                    </cftry>
                </cfif>
                
                <cfif result.insertedPatientID gt 0 AND val(patient_id) gt 0>
                    <cftry>
                        <cfset var ensureSQL = "UPDATE #agency_db#.patients_ai SET Patient_ID = " & val(patient_id) & ", modified_date = NOW(), modified_by = " & created_by & " WHERE pt_ai_id = " & result.insertedPatientID & " AND (Patient_ID IS NULL OR Patient_ID = 0) AND status = 0" />
                        <cfquery name="EnsurePatientID" datasource="#Application.DataSrc#" result="ensureResult">
                            UPDATE #agency_db#.patients_ai SET Patient_ID = <cfqueryparam value="#val(patient_id)#" cfsqltype="cf_sql_integer">,
                                modified_date = <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                                modified_by = <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">
                            WHERE pt_ai_id = <cfqueryparam value="#result.insertedPatientID#" cfsqltype="cf_sql_integer">
                              AND (Patient_ID IS NULL OR Patient_ID = 0) AND status = 0
                        </cfquery>
                        <cfcatch type="any">
                            <!--- Extract agency ID from agency_db (format: agency_XXX) --->
                            <cfset var agencyIDFromDB = 0 />
                            <cfif find("agency_", agency_db) GT 0>
                                <cfset agencyIDFromDB = val(listLast(agency_db, "_")) />
                            </cfif>
                            <!--- Send exception email --->
                            <cfset sendProcessPatientDataExceptionEmail(
                                error = cfcatch,
                                agencyID = agencyIDFromDB,
                                empID = created_by,
                                patientID = val(patient_id),
                                agency_db = agency_db,
                                data = data
                            ) />
                            <cfset arrayAppend(result.errors, "Ensure Patient_ID failed: " & cfcatch.message) />
                        </cfcatch>
                    </cftry>
                    
                    <!--- Update pPatients table directly with pPatient data --->
                    <!--- NOTE: All fields from pPatient section will be updated into pPatients table --->
                    <!--- If Vertex API data is available, it will override: Medical Record Number, Address, DOB, Gender, Allergies --->
                    <cftry>
                        <!--- Check if Vertex API patient data is available (from request scope or data structure) --->
                        <cfset var hasVertexData = false />
                        <cfset var vertexPatient = {} />
                        
                        <!--- Check request scope first (from sync process) --->
                        <cfif structKeyExists(request, "vertex_api_patient_data") AND isStruct(request.vertex_api_patient_data) AND NOT structIsEmpty(request.vertex_api_patient_data)>
                            <cfset vertexPatient = request.vertex_api_patient_data />
                            <cfset hasVertexData = true />
                        <!--- Check if Vertex API data is in the data structure --->
                        <cfelseif structKeyExists(data, "vertex_api_patient_data") AND isStruct(data.vertex_api_patient_data) AND NOT structIsEmpty(data.vertex_api_patient_data)>
                            <cfset vertexPatient = data.vertex_api_patient_data />
                            <cfset hasVertexData = true />
                        </cfif>
                        
                        <!--- Patient data has already been extracted above, but override with Vertex API data if available --->
                        
                        <!--- OVERRIDE with Vertex API data for REQUIRED fields (if available) --->
                        <cfif hasVertexData>
                            <!--- Medical Record Number (Pt_Agy_ID) - MUST from Vertex API --->
                            <cfif structKeyExists(vertexPatient, "Pt_Agy_ID") AND len(trim(vertexPatient.Pt_Agy_ID)) GT 0>
                                <cfset ptAgyID = trim(vertexPatient.Pt_Agy_ID) />
                            <cfelseif structKeyExists(vertexPatient, "Medical_Record_Number") AND len(trim(vertexPatient.Medical_Record_Number)) GT 0>
                                <cfset ptAgyID = trim(vertexPatient.Medical_Record_Number) />
                            <cfelseif structKeyExists(vertexPatient, "MRN") AND len(trim(vertexPatient.MRN)) GT 0>
                                <cfset ptAgyID = trim(vertexPatient.MRN) />
                            </cfif>
                            
                            <!--- Address - MUST from Vertex API --->
                            <cfif structKeyExists(vertexPatient, "Pt_Street") AND len(trim(vertexPatient.Pt_Street)) GT 0>
                                <cfset ptStreet = trim(vertexPatient.Pt_Street) />
                            </cfif>
                            <cfif structKeyExists(vertexPatient, "Pt_City") AND len(trim(vertexPatient.Pt_City)) GT 0>
                                <cfset ptCity = trim(vertexPatient.Pt_City) />
                            </cfif>
                            <cfif structKeyExists(vertexPatient, "Pt_State") AND len(trim(vertexPatient.Pt_State)) GT 0>
                                <cfset ptState = trim(vertexPatient.Pt_State) />
                            </cfif>
                            <cfif structKeyExists(vertexPatient, "Pt_Zip") AND len(trim(vertexPatient.Pt_Zip)) GT 0>
                                <cfset ptZip = trim(vertexPatient.Pt_Zip) />
                            </cfif>
                            
                            <!--- DOB - MUST from Vertex API --->
                            <cfif structKeyExists(vertexPatient, "Pt_DOB") AND len(trim(vertexPatient.Pt_DOB)) GT 0>
                                <cftry>
                                    <cfset ptDOB = parseDate(vertexPatient.Pt_DOB) />
                                    <cfcatch>
                                        <!--- If parsing fails, try parseDateTime --->
                                        <cftry>
                                            <cfset ptDOB = parseDateTime(vertexPatient.Pt_DOB) />
                                            <cfcatch>
                                                <cfset ptDOB = "" />
                                            </cfcatch>
                                        </cftry>
                                    </cfcatch>
                                </cftry>
                            </cfif>
                            
                            <!--- Gender - MUST from Vertex API --->
                            <cfif structKeyExists(vertexPatient, "Pt_Gender") AND len(trim(vertexPatient.Pt_Gender)) GT 0>
                                <cfset ptGender = trim(vertexPatient.Pt_Gender) />
                            </cfif>
                            
                            <!--- Allergies - MUST from Vertex API --->
                            <cfif structKeyExists(vertexPatient, "Allergies") AND len(trim(vertexPatient.Allergies)) GT 0>
                                <cfset ptAllergies = trim(vertexPatient.Allergies) />
                            </cfif>
                        </cfif>
                        
                        <!--- Convert gender format if needed (M -> "1 - Male", F -> "2 - Female") --->
                        <cfif len(ptGender) GT 0>
                            <cfset var genderUpper = uCase(ptGender) />
                            <cfif genderUpper EQ "M" OR genderUpper EQ "MALE" OR findNoCase("male", genderUpper) GT 0>
                                <cfset ptGender = "1 - Male" />
                            <cfelseif genderUpper EQ "F" OR genderUpper EQ "FEMALE" OR findNoCase("female", genderUpper) GT 0>
                                <cfset ptGender = "2 - Female" />
                            </cfif>
                        </cfif>
                        
                        <!--- Check if patient exists in pPatients table --->
                        <!--- CONDITION 1: If pPatient record is already populated with Pt_First and Pt_Last, DO NOT CREATE/UPDATE pPatient --->
                        <cfset var checkPPatientsSQL = "SELECT Patient_ID, Pt_First, Pt_Last FROM #agency_db#.pPatients WHERE Patient_ID = " & val(patient_id) & " AND status IN (0,1,4) LIMIT 1" />
                        <cfquery name="CheckPPatients" datasource="#Application.DataSrc#">
                            SELECT Patient_ID, Pt_First, Pt_Last
                            FROM #agency_db#.pPatients
                            WHERE Patient_ID = <cfqueryparam value="#val(patient_id)#" cfsqltype="cf_sql_integer">
                            AND status IN (0,1,4)
                            LIMIT 1
                        </cfquery>
                        
                        <!--- Check if Pt_First and Pt_Last are already populated --->
                        <cfset var skipPPatientUpdate = false />
                        <cfif CheckPPatients.recordcount GT 0>
                            <cfset var existingPtFirst = trim(CheckPPatients.Pt_First) />
                            <cfset var existingPtLast = trim(CheckPPatients.Pt_Last) />
                            <!--- If both Pt_First and Pt_Last are already populated (not empty), skip update --->
                            <cfif len(existingPtFirst) GT 0 AND len(existingPtLast) GT 0>
                                <cfset skipPPatientUpdate = true />
                            </cfif>
                        </cfif>
                        
                        <cfif CheckPPatients.recordcount GT 0 AND NOT skipPPatientUpdate>
                            <!--- Update existing pPatients record (only if Pt_First and Pt_Last are not already populated) --->
                            <!--- NOTE: Pt_First, Pt_Last, and Pt_Gender are NOT synced from patients_ai - they must be manually entered --->
                            <!--- #10101: Map patients_ai short Race/Ethnicity to full OASIS text for pPatients so General Information shows correct checkboxes --->
                            <cfset var ptRaceOasis = mapRaceToOasisFull(ptRace) />
                            <cfset var m0140EthnicOasis = mapEthnicityToOasisFull(m0140Ethnic) />
                            <cfset var updatePPatientsSQL = "UPDATE #agency_db#.pPatients SET Pt_Middle = ?, Pt_Suffix = ?, Pt_Street = ?, Pt_City = ?, Pt_State = ?, Pt_Zip = ?, Pt_Phone = ?, Pt_DOB = ?, Pt_Agy_ID = ?, Pt_Race = ?, M0140_ETHNIC = ?, Pt_language = ?, Interpreter = ?, Allergies = ?, Pt_SSN = ?, Email = ?, Specific_Concerns = ?, Record_Mod_Date = ?, Record_Mod_By = ? WHERE Patient_ID = ? AND status IN (0,1,4)" />
                            <cfquery name="UpdatePPatients" datasource="#Application.DataSrc#" result="updatePPatientsResult">
                                UPDATE #agency_db#.pPatients SET
                                    Pt_Middle = <cfqueryparam value="#ptMiddle#" cfsqltype="cf_sql_varchar" null="#len(ptMiddle) eq 0#">,
                                    Pt_Suffix = <cfqueryparam value="#ptSuffix#" cfsqltype="cf_sql_varchar" null="#len(ptSuffix) eq 0#">,
                                    Pt_Street = <cfqueryparam value="#ptStreet#" cfsqltype="cf_sql_varchar" null="#len(ptStreet) eq 0#">,
                                    Pt_City = <cfqueryparam value="#ptCity#" cfsqltype="cf_sql_varchar" null="#len(ptCity) eq 0#">,
                                    Pt_State = <cfqueryparam value="#ptState#" cfsqltype="cf_sql_varchar" null="#len(ptState) eq 0#">,
                                    Pt_Zip = <cfqueryparam value="#ptZip#" cfsqltype="cf_sql_varchar" null="#len(ptZip) eq 0#">,
                                    Pt_Phone = <cfqueryparam value="#ptPhone#" cfsqltype="cf_sql_varchar" null="#len(ptPhone) eq 0#">,
                                    Pt_DOB = <cfqueryparam value="#ptDOB#" cfsqltype="cf_sql_date" null="#len(trim(ptDOB)) eq 0#">,
                                    Pt_Agy_ID = <cfqueryparam value="#ptAgyID#" cfsqltype="cf_sql_varchar" null="#len(ptAgyID) eq 0#">,
                                    Pt_Race = <cfqueryparam value="#ptRaceOasis#" cfsqltype="cf_sql_varchar" null="#len(ptRaceOasis) eq 0#">,
                                    M0140_ETHNIC = <cfqueryparam value="#m0140EthnicOasis#" cfsqltype="cf_sql_varchar" null="#len(m0140EthnicOasis) eq 0#">,
                                    Pt_language = <cfqueryparam value="#ptLanguage#" cfsqltype="cf_sql_varchar" null="#len(ptLanguage) eq 0#">,
                                    Interpreter = <cfqueryparam value="#ptInterpreter#" cfsqltype="cf_sql_varchar" null="#len(ptInterpreter) eq 0#">,
                                    Allergies = <cfqueryparam value="#ptAllergies#" cfsqltype="cf_sql_varchar" null="#len(ptAllergies) eq 0#">,
                                    Pt_SSN = <cfqueryparam value="#ptSSN#" cfsqltype="cf_sql_varchar" null="#len(ptSSN) eq 0#">,
                                    Email = <cfqueryparam value="#ptEmail#" cfsqltype="cf_sql_varchar" null="#len(ptEmail) eq 0#">,
                                    Specific_Concerns = <cfqueryparam value="#ptSpecificConcerns#" cfsqltype="cf_sql_varchar" null="#len(ptSpecificConcerns) eq 0#">,
                                    Record_Mod_Date = <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                                    Record_Mod_By = <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">
                                WHERE Patient_ID = <cfqueryparam value="#val(patient_id)#" cfsqltype="cf_sql_integer">
                                AND status IN (0,1,4)
                            </cfquery>
                            <!--- <cfset sendUpdateActionEmail(
                                action = "UPDATE pPatients",
                                table = "#agency_db#.pPatients",
                                recordID = val(patient_id),
                                agencyID = val(patient_id),
                                empID = created_by,
                                patientID = val(patient_id),
                                agency_db = agency_db,
                                querySQL = updatePPatientsSQL,
                                rowsAffected = updatePPatientsResult.recordcount
                            ) /> --->
                        </cfif>
                        <cfcatch type="any">
                            <!--- Extract agency ID from agency_db (format: agency_XXX) --->
                            <cfset var agencyIDFromDB = 0 />
                            <cfif find("agency_", agency_db) GT 0>
                                <cfset agencyIDFromDB = val(listLast(agency_db, "_")) />
                            </cfif>
                            <!--- Send exception email --->
                            <cfset sendProcessPatientDataExceptionEmail(
                                error = cfcatch,
                                agencyID = agencyIDFromDB,
                                empID = created_by,
                                patientID = val(patient_id),
                                agency_db = agency_db,
                                data = data
                            ) />
                            <cfset arrayAppend(result.errors, "Update pPatients table failed: " & cfcatch.message) />
                        </cfcatch>
                    </cftry>
                </cfif>
                
                <cfcatch type="any">
                    <!--- Extract agency ID from agency_db (format: agency_XXX) --->
                    <cfset var agencyIDFromDB = 0 />
                    <cfif find("agency_", agency_db) GT 0>
                        <cfset agencyIDFromDB = val(listLast(agency_db, "_")) />
                    </cfif>
                    <!--- Send exception email for main processPatientData error --->
                    <cfset sendProcessPatientDataExceptionEmail(
                        error = cfcatch,
                        agencyID = agencyIDFromDB,
                        empID = created_by,
                        patientID = val(patient_id),
                        agency_db = agency_db,
                        data = data
                    ) />
                    <cfset var errDetail = cfcatch.message />
                    <cfif structKeyExists(cfcatch, "detail") AND len(trim(cfcatch.detail))>
                        <cfset errDetail = errDetail & " | " & cfcatch.detail />
                    </cfif>
                    <cfif structKeyExists(cfcatch, "sql") AND len(trim(cfcatch.sql))>
                        <cfset errDetail = errDetail & " | SQL: " & left(reReplace(cfcatch.sql, "[ \s]+", " ", "ALL"), 300) />
                    </cfif>
                    <cfset arrayAppend(result.errors, "Patient insert/update failed: " & errDetail) />
                    <cfthrow message="Patient insert/update failed: #errDetail#" detail="#errDetail#" />
                </cfcatch>
            </cftry>
        </cfif>
        
        <cfreturn result />
    </cffunction>

    <!--- Helper function to process medications --->
    <cffunction name="processMedications" access="private" returntype="struct" hint="Process medication data insertion">
        <cfargument name="medications" required="yes" type="array" />
        <cfargument name="patientID" required="yes" type="numeric" />
        <cfargument name="patientAIID" required="yes" type="numeric" />
        <cfargument name="agency_db" required="yes" type="string" />
        <cfargument name="created_by" required="yes" type="numeric" />
        
        <cfset var result = {"medicationCount" = 0, "medicationIDs" = [], "errors" = []} />
        
        <cfloop array="#medications#" index="med">
            <cftry>
                <cfset var medDrugName = structKeyExists(med, "Drug_Name") ? med.Drug_Name : (structKeyExists(med, "medication") ? med.medication : "") />
                <!--- Truncate Drug_Name to 255 characters to match VARCHAR(255) column definition --->
                <cfif len(medDrugName) GT 255>
                    <cfset medDrugName = left(medDrugName, 255) />
                </cfif>
                <cfset var medRoute = structKeyExists(med, "Route") ? med.Route : (structKeyExists(med, "route") ? med.route : "") />
                <!--- Truncate Route to 100 characters to match VARCHAR(100) column definition --->
                <cfif len(medRoute) GT 100>
                    <cfset medRoute = left(medRoute, 100) />
                </cfif>
                <cfset var medFreq = structKeyExists(med, "Freq") ? med.Freq : (structKeyExists(med, "frequency") ? med.frequency : "") />
                <!--- Truncate Freq to 100 characters to match VARCHAR(100) column definition --->
                <cfif len(medFreq) GT 100>
                    <cfset medFreq = left(medFreq, 100) />
                </cfif>
                <cfset var medNotes = structKeyExists(med, "Notes") ? med.Notes : (structKeyExists(med, "notes") ? med.notes : "") />
                <!--- Note: Notes is TEXT type, so no truncation needed --->
                <cfset var medDose = structKeyExists(med, "Dose") ? med.Dose : "" />
                <!--- Truncate Dose to 100 characters to match VARCHAR(100) column definition --->
                <cfif len(medDose) GT 100>
                    <cfset medDose = left(medDose, 100) />
                </cfif>
                <cfset var medDoseUnits = structKeyExists(med, "Dose_Units") ? med.Dose_Units : "" />
                <!--- Truncate Dose_Units to 50 characters to match VARCHAR(50) column definition --->
                <cfif len(medDoseUnits) GT 50>
                    <cfset medDoseUnits = left(medDoseUnits, 50) />
                </cfif>
                
                <!--- Backfill Dose_Units from alternate keys without discarding values like "/1 Tablet" --->
                <cfif NOT len(trim(medDoseUnits)) AND structKeyExists(med, "dose_units") AND len(trim(med.dose_units))>
                    <cfset medDoseUnits = trim(med.dose_units) />
                </cfif>
                
                <cfif NOT len(trim(medDoseUnits)) AND structKeyExists(med, "Dose/Units") AND len(trim(med["Dose/Units"]))>
                    <cfset medDoseUnits = trim(med["Dose/Units"]) />
                </cfif>

                <!--- If Dose is empty and Dose_Units starts with a numeric token, split once into Dose + Dose_Units --->
                <cfif NOT len(trim(medDose)) AND len(trim(medDoseUnits))>
                    <cfset var duSplit = trim(medDoseUnits) />
                    <cfset var duSplitFirst = listFirst(duSplit, " ") />
                    <cfset var duSplitRest = "" />
                    <cfif listLen(duSplit, " ") GT 1>
                        <cfset duSplitRest = listRest(duSplit, " ") />
                    </cfif>
                    <cfif reFind("^[0-9]+(?:\.[0-9]+)?(?:-[0-9]+(?:\.[0-9]+)?)?$", trim(duSplitFirst))>
                        <cfset medDose = trim(duSplitFirst) />
                        <cfif len(trim(duSplitRest))>
                            <cfset medDoseUnits = trim(duSplitRest) />
                        </cfif>
                    </cfif>
                </cfif>
                
                <cfif len(trim(medDoseUnits)) GT 0>
                    <cfset medDoseUnits = trim(medDoseUnits) />
                    <cfset duplicateUnitsPattern = "^(\d+(?:\.\d+)?(?:-\d+(?:\.\d+)?)?)\s+\1\s+(.+)$" />
                    <cfset unitsMatch = reFind(duplicateUnitsPattern, medDoseUnits, 1, true) />
                    <cfif unitsMatch.pos[1] GT 0 AND unitsMatch.pos[3] GT 0>
                        <cfset extractedDose = trim(mid(medDoseUnits, unitsMatch.pos[1], unitsMatch.len[1])) />
                        <cfset extractedUnits = trim(mid(medDoseUnits, unitsMatch.pos[3], unitsMatch.len[3])) />
                        <cfif NOT len(trim(medDose))><cfset medDose = extractedDose /></cfif>
                        <cfset medDoseUnits = extractedUnits />
                    </cfif>
                </cfif>
                
                <cfif len(trim(medDose)) GT 0>
                    <cfset medDose = trim(medDose) />
                    <cfset duplicateDosePattern = "^(\d+(?:\.\d+)?(?:-\d+(?:\.\d+)?)?)\s+\1(?:\s|$)" />
                    <cfset medDose = reReplace(medDose, duplicateDosePattern, "\1", "all") />
                    <cfset medDose = trim(medDose) />
                </cfif>
                
                <!--- Final cleanup: Remove leading number from Dose_Units if it matches Dose --->
                <cfif len(trim(medDoseUnits)) GT 0 AND len(trim(medDose)) GT 0>
                    <cfset medDoseUnits = trim(medDoseUnits) />
                    <cfset medDose = trim(medDose) />
                    <!--- Pattern: number (with optional decimal/range) at start + space + rest of text --->
                    <cfset singleNumberPattern = "^(\d+(?:\.\d+)?(?:-\d+(?:\.\d+)?)?)\s+(.+)$" />
                    <cfset singleMatch = reFind(singleNumberPattern, medDoseUnits, 1, true) />
                    <cfif singleMatch.pos[1] GT 0 AND singleMatch.pos[2] GT 0>
                        <cfset numberPart = trim(mid(medDoseUnits, singleMatch.pos[1], singleMatch.len[1])) />
                        <cfset unitsPart = trim(mid(medDoseUnits, singleMatch.pos[2], singleMatch.len[2])) />
                        <!--- If the leading number matches Dose, remove it from Dose_Units --->
                        <cfif numberPart EQ medDose>
                            <cfset medDoseUnits = unitsPart />
                        </cfif>
                    </cfif>
                </cfif>
                
                <!--- Additional cleanup: If Dose_Units still starts with a number that matches Dose after all processing --->
                <cfif len(trim(medDoseUnits)) GT 0 AND len(trim(medDose)) GT 0>
                    <cfset medDoseUnits = trim(medDoseUnits) />
                    <cfset medDose = trim(medDose) />
                    <!--- Check if Dose_Units starts with Dose value followed by space --->
                    <cfif left(medDoseUnits, len(medDose) + 1) EQ medDose & " ">
                        <cfset medDoseUnits = trim(right(medDoseUnits, len(medDoseUnits) - len(medDose) - 1)) />
                    </cfif>
                </cfif>
                
                <!--- Final truncation to ensure all fields fit database column limits --->
                <cfif len(medDrugName) GT 255>
                    <cfset medDrugName = left(medDrugName, 255) />
                </cfif>
                <cfif len(medDose) GT 100>
                    <cfset medDose = left(medDose, 100) />
                </cfif>
                <cfif len(medDoseUnits) GT 50>
                    <cfset medDoseUnits = left(medDoseUnits, 50) />
                </cfif>
                <cfif len(medRoute) GT 100>
                    <cfset medRoute = left(medRoute, 100) />
                </cfif>
                <cfif len(medFreq) GT 100>
                    <cfset medFreq = left(medFreq, 100) />
                </cfif>
                
                <cfquery name="InsertMed" datasource="#Application.DataSrc#" result="medResult">
                    INSERT INTO #agency_db#.ptmeds_ai (
                        Patient_ID, Patient_AI_ID, Drug_ID, Status, DateOrdered, DateDCed,
                        Drug_Name, Dose, Dose_Units, Route, Freq, Notes,
                        Date_Create, Created_by, Date_Change, Change_by, record_timestamp
                    ) VALUES (
                        <cfqueryparam value="#patientID#" cfsqltype="cf_sql_integer">,
                        <cfqueryparam value="#val(patientAIID)#" cfsqltype="cf_sql_integer">,
                        <cfqueryparam value="0" cfsqltype="cf_sql_integer" null="true">,
                        <cfqueryparam value="0" cfsqltype="cf_sql_tinyint">,
                        <cfqueryparam value="#structKeyExists(med, 'DateOrdered') ? parseDate(med.DateOrdered) : ''#" cfsqltype="cf_sql_date" null="#not structKeyExists(med, 'DateOrdered') or len(trim(parseDate(med.DateOrdered))) eq 0#">,
                        <cfqueryparam value="#structKeyExists(med, 'DateDCed') ? parseDate(med.DateDCed) : ''#" cfsqltype="cf_sql_date" null="#not structKeyExists(med, 'DateDCed') or len(trim(parseDate(med.DateDCed))) eq 0#">,
                        <cfqueryparam value="#medDrugName#" cfsqltype="cf_sql_varchar" null="#len(trim(medDrugName)) eq 0#">,
                        <cfqueryparam value="#medDose#" cfsqltype="cf_sql_varchar" null="#len(trim(medDose)) eq 0#">,
                        <cfqueryparam value="#medDoseUnits#" cfsqltype="cf_sql_varchar" null="#len(trim(medDoseUnits)) eq 0#">,
                        <cfqueryparam value="#medRoute#" cfsqltype="cf_sql_varchar" null="#len(trim(medRoute)) eq 0#">,
                        <cfqueryparam value="#medFreq#" cfsqltype="cf_sql_varchar" null="#len(trim(medFreq)) eq 0#">,
                        <cfqueryparam value="#medNotes#" cfsqltype="cf_sql_longvarchar" null="#len(trim(medNotes)) eq 0#">,
                        <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                        <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">,
                        <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                        <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">,
                        <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">
                    )
                </cfquery>
                
                <cfset arrayAppend(result.medicationIDs, medResult.GENERATED_KEY) />
                <cfset result.medicationCount++ />
                
                <cfcatch type="any">
                    <!--- Extract agency ID from agency_db (format: agency_XXX) --->
                    <cfset var agencyIDFromDB = 0 />
                    <cfif find("agency_", agency_db) GT 0>
                        <cfset agencyIDFromDB = val(listLast(agency_db, "_")) />
                    </cfif>
                    <!--- Send exception email --->
                    <cfset sendModuleExceptionEmail(
                        moduleName = "processMedications",
                        error = cfcatch,
                        agencyID = agencyIDFromDB,
                        empID = created_by,
                        patientID = patientID,
                        agency_db = agency_db,
                        inputData = med
                    ) />
                    <cfset arrayAppend(result.errors, "Medication insert failed: " & cfcatch.message) />
                </cfcatch>
            </cftry>
        </cfloop>
        
        <cfreturn result />
    </cffunction>

    <!--- Helper function to process contact data --->
    <cffunction name="processContactData" access="private" returntype="struct" hint="Process contact data insertion/update">
        <cfargument name="pPtContacts" required="yes" type="struct" />
        <cfargument name="patientAIID" required="yes" type="numeric" />
        <cfargument name="agency_db" required="yes" type="string" />
        <cfargument name="created_by" required="yes" type="numeric" />
        
        <cfset var result = {"insertedContactID" = 0, "contactInserted" = false, "errors" = []} />
        
        <cftry>
            <cfset var _firstName = structKeyExists(pPtContacts, 'First_Name') ? trim(pPtContacts.First_Name) : '' />
            <cfset var _lastName = structKeyExists(pPtContacts, 'Last_Name') ? trim(pPtContacts.Last_Name) : '' />
            <cfset var _relationship = structKeyExists(pPtContacts, 'Pt_Realtionship') ? trim(pPtContacts.Pt_Realtionship) : '' />
            <cfset var _telephone1 = structKeyExists(pPtContacts, 'Telephone1') ? trim(pPtContacts.Telephone1) : '' />
            
            <cfif len(_firstName) eq 0 AND len(_lastName) eq 0 AND len(_relationship) eq 0 AND len(_telephone1) eq 0>
                <!--- All key fields empty: ignore --->
            <cfelse>
                <cfquery name="CheckExistingContact" datasource="#Application.DataSrc#">
                    SELECT Contact_ID FROM #agency_db#.pt_contacts_ai
                    WHERE Patient_AI_ID = <cfqueryparam value="#patientAIID#" cfsqltype="cf_sql_integer">
                    AND First_Name = <cfqueryparam value="#structKeyExists(pPtContacts, 'First_Name') ? pPtContacts.First_Name : ''#" cfsqltype="cf_sql_varchar">
                    AND Last_Name = <cfqueryparam value="#structKeyExists(pPtContacts, 'Last_Name') ? pPtContacts.Last_Name : ''#" cfsqltype="cf_sql_varchar">
                    AND Status = 0 LIMIT 1
                </cfquery>
                
                <cfif CheckExistingContact.recordcount eq 0>
                    <cfquery name="InsertContact" datasource="#Application.DataSrc#" result="contactResult">
                        INSERT INTO #agency_db#.pt_contacts_ai (
                            Patient_AI_ID, First_Name, Last_Name, Relationship, Is_Emergency,
                            Email, Telephone1, Telephone2, Date_Create, Created_by,
                            Date_Change, Change_by, Status
                        ) VALUES (
                            <cfqueryparam value="#patientAIID#" cfsqltype="cf_sql_integer">,
                            <cfqueryparam value="#structKeyExists(pPtContacts, 'First_Name') ? pPtContacts.First_Name : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPtContacts, 'First_Name') or len(trim(pPtContacts.First_Name)) eq 0#">,
                            <cfqueryparam value="#structKeyExists(pPtContacts, 'Last_Name') ? pPtContacts.Last_Name : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPtContacts, 'Last_Name') or len(trim(pPtContacts.Last_Name)) eq 0#">,
                            <cfqueryparam value="#structKeyExists(pPtContacts, 'Pt_Realtionship') ? pPtContacts.Pt_Realtionship : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPtContacts, 'Pt_Realtionship') or len(trim(pPtContacts.Pt_Realtionship)) eq 0#">,
                            <cfqueryparam value="#structKeyExists(pPtContacts, 'Emergency') ? pPtContacts.Emergency : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPtContacts, 'Emergency') or len(trim(pPtContacts.Emergency)) eq 0#">,
                            <cfqueryparam value="#structKeyExists(pPtContacts, 'Contact_Email') ? pPtContacts.Contact_Email : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPtContacts, 'Contact_Email') or len(trim(pPtContacts.Contact_Email)) eq 0#">,
                            <cfqueryparam value="#structKeyExists(pPtContacts, 'Telephone1') ? pPtContacts.Telephone1 : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPtContacts, 'Telephone1') or len(trim(pPtContacts.Telephone1)) eq 0#">,
                            <cfqueryparam value="#structKeyExists(pPtContacts, 'Telephone2') ? pPtContacts.Telephone2 : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPtContacts, 'Telephone2') or len(trim(pPtContacts.Telephone2)) eq 0#">,
                            <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                            <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">,
                            <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                            <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">,
                            <cfqueryparam value="0" cfsqltype="cf_sql_tinyint">
                        )
                    </cfquery>
                    <cfset result.insertedContactID = contactResult.GENERATED_KEY />
                    <cfset result.contactInserted = true />
                <cfelse>
                    <cfset result.insertedContactID = CheckExistingContact.Contact_ID />
                    <cfquery name="UpdateContact" datasource="#Application.DataSrc#">
                        UPDATE #agency_db#.pt_contacts_ai SET
                            Relationship = <cfqueryparam value="#structKeyExists(pPtContacts, 'Pt_Realtionship') ? pPtContacts.Pt_Realtionship : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPtContacts, 'Pt_Realtionship') or len(trim(pPtContacts.Pt_Realtionship)) eq 0#">,
                            Is_Emergency = <cfqueryparam value="#structKeyExists(pPtContacts, 'Emergency') ? pPtContacts.Emergency : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPtContacts, 'Emergency') or len(trim(pPtContacts.Emergency)) eq 0#">,
                            Email = <cfqueryparam value="#structKeyExists(pPtContacts, 'Contact_Email') ? pPtContacts.Contact_Email : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPtContacts, 'Contact_Email') or len(trim(pPtContacts.Contact_Email)) eq 0#">,
                            Telephone1 = <cfqueryparam value="#structKeyExists(pPtContacts, 'Telephone1') ? pPtContacts.Telephone1 : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPtContacts, 'Telephone1') or len(trim(pPtContacts.Telephone1)) eq 0#">,
                            Telephone2 = <cfqueryparam value="#structKeyExists(pPtContacts, 'Telephone2') ? pPtContacts.Telephone2 : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPtContacts, 'Telephone2') or len(trim(pPtContacts.Telephone2)) eq 0#">,
                            Date_Change = <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                            Change_by = <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">
                        WHERE Contact_ID = <cfqueryparam value="#result.insertedContactID#" cfsqltype="cf_sql_integer"> AND Status = 0
                    </cfquery>
                </cfif>
            </cfif>
            <cfcatch type="any">
                <!--- Extract agency ID from agency_db (format: agency_XXX) --->
                <cfset var agencyIDFromDB = 0 />
                <cfif find("agency_", agency_db) GT 0>
                    <cfset agencyIDFromDB = val(listLast(agency_db, "_")) />
                </cfif>
                <!--- Send exception email --->
                <cfset sendModuleExceptionEmail(
                    moduleName = "processContactData",
                    error = cfcatch,
                    agencyID = agencyIDFromDB,
                    empID = created_by,
                    patientID = 0,
                    agency_db = agency_db,
                    inputData = pPtContacts
                ) />
                <cfset arrayAppend(result.errors, "Contact insert failed: " & cfcatch.message) />
            </cfcatch>
        </cftry>
        
        <cfreturn result />
    </cffunction>

    <!--- Helper function to process payer data --->
    <cffunction name="processPayerData" access="private" returntype="struct" hint="Process payer data insertion/update">
        <cfargument name="pPayer" required="yes" type="struct" />
        <cfargument name="patientAIID" required="yes" type="numeric" />
        <cfargument name="agency_db" required="yes" type="string" />
        <cfargument name="created_by" required="yes" type="numeric" />
        
        <cfset var result = {"insertedPayerID" = 0, "payerInserted" = false, "errors" = []} />
        
        <cftry>
            <cfset var _payName = structKeyExists(pPayer, 'Pay_Name') ? trim(pPayer.Pay_Name) : '' />
            <cfset var _subHic = structKeyExists(pPayer, 'Sub_HIC') ? trim(pPayer.Sub_HIC) : '' />
            <cfset var _rel = structKeyExists(pPayer, 'payer_Pt_Relationship') ? trim(pPayer.payer_Pt_Relationship) : '' />
            <cfset var _subFirst = structKeyExists(pPayer, 'Sub_First') ? trim(pPayer.Sub_First) : '' />
            <cfset var _subLast = structKeyExists(pPayer, 'Sub_Last') ? trim(pPayer.Sub_Last) : '' />
            
            <cfif len(_payName) eq 0 AND len(_subHic) eq 0 AND len(_rel) eq 0 AND len(_subFirst) eq 0 AND len(_subLast) eq 0>
                <!--- All pPayer fields empty: ignore --->
            <cfelse>
                <cfquery name="CheckExistingPayer" datasource="#Application.DataSrc#">
                    SELECT Payer_AI_ID FROM #agency_db#.pt_payer_ai
                    WHERE Patient_AI_ID = <cfqueryparam value="#patientAIID#" cfsqltype="cf_sql_integer">
                    AND Payer_Name = <cfqueryparam value="#structKeyExists(pPayer, 'Pay_Name') ? pPayer.Pay_Name : ''#" cfsqltype="cf_sql_varchar">
                    AND Status = 0 LIMIT 1
                </cfquery>
                
                <cfif CheckExistingPayer.recordcount eq 0>
                    <cfquery name="InsertPayer" datasource="#Application.DataSrc#" result="payerResult">
                        INSERT INTO #agency_db#.pt_payer_ai (
                            Patient_AI_ID, Payer_ID, Payer_Name, Policy_ID_No, Subscriber_HIC,
                            Subscriber_Relationship, Subscriber_First_Name, Subscriber_Last_Name,
                            Date_Create, Created_by, Date_Change, Change_by, Status
                        ) VALUES (
                            <cfqueryparam value="#patientAIID#" cfsqltype="cf_sql_integer">,
                            <cfqueryparam value="0" cfsqltype="cf_sql_integer" null="true">,
                            <cfqueryparam value="#structKeyExists(pPayer, 'Pay_Name') ? pPayer.Pay_Name : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Pay_Name') or len(trim(pPayer.Pay_Name)) eq 0#">,
                            <cfqueryparam value="#structKeyExists(pPayer, 'Sub_HIC') ? pPayer.Sub_HIC : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Sub_HIC') or len(trim(pPayer.Sub_HIC)) eq 0#">,
                            <cfqueryparam value="#structKeyExists(pPayer, 'Sub_HIC') ? pPayer.Sub_HIC : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Sub_HIC') or len(trim(pPayer.Sub_HIC)) eq 0#">,
                            <cfqueryparam value="#structKeyExists(pPayer, 'payer_Pt_Relationship') ? pPayer.payer_Pt_Relationship : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'payer_Pt_Relationship') or len(trim(pPayer.payer_Pt_Relationship)) eq 0#">,
                            <cfqueryparam value="#structKeyExists(pPayer, 'Sub_First') ? pPayer.Sub_First : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Sub_First') or len(trim(pPayer.Sub_First)) eq 0#">,
                            <cfqueryparam value="#structKeyExists(pPayer, 'Sub_Last') ? pPayer.Sub_Last : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Sub_Last') or len(trim(pPayer.Sub_Last)) eq 0#">,
                            <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                            <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">,
                            <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                            <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">,
                            <cfqueryparam value="0" cfsqltype="cf_sql_tinyint">
                        )
                    </cfquery>
                    <cfset result.insertedPayerID = payerResult.GENERATED_KEY />
                    <cfset result.payerInserted = true />
                <cfelse>
                    <cfset result.insertedPayerID = CheckExistingPayer.Payer_AI_ID />
                    <cfquery name="UpdatePayer" datasource="#Application.DataSrc#">
                        UPDATE #agency_db#.pt_payer_ai SET
                            Policy_ID_No = <cfqueryparam value="#structKeyExists(pPayer, 'Sub_HIC') ? pPayer.Sub_HIC : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Sub_HIC') or len(trim(pPayer.Sub_HIC)) eq 0#">,
                            Subscriber_HIC = <cfqueryparam value="#structKeyExists(pPayer, 'Sub_HIC') ? pPayer.Sub_HIC : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Sub_HIC') or len(trim(pPayer.Sub_HIC)) eq 0#">,
                            Subscriber_Relationship = <cfqueryparam value="#structKeyExists(pPayer, 'payer_Pt_Relationship') ? pPayer.payer_Pt_Relationship : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'payer_Pt_Relationship') or len(trim(pPayer.payer_Pt_Relationship)) eq 0#">,
                            Subscriber_First_Name = <cfqueryparam value="#structKeyExists(pPayer, 'Sub_First') ? pPayer.Sub_First : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Sub_First') or len(trim(pPayer.Sub_First)) eq 0#">,
                            Subscriber_Last_Name = <cfqueryparam value="#structKeyExists(pPayer, 'Sub_Last') ? pPayer.Sub_Last : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pPayer, 'Sub_Last') or len(trim(pPayer.Sub_Last)) eq 0#">,
                            Date_Change = <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                            Change_by = <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">
                        WHERE Payer_AI_ID = <cfqueryparam value="#result.insertedPayerID#" cfsqltype="cf_sql_integer"> AND Status = 0
                    </cfquery>
                </cfif>
            </cfif>
            <cfcatch type="any">
                <!--- Extract agency ID from agency_db (format: agency_XXX) --->
                <cfset var agencyIDFromDB = 0 />
                <cfif find("agency_", agency_db) GT 0>
                    <cfset agencyIDFromDB = val(listLast(agency_db, "_")) />
                </cfif>
                <!--- Send exception email --->
                <cfset sendModuleExceptionEmail(
                    moduleName = "processPayerData",
                    error = cfcatch,
                    agencyID = agencyIDFromDB,
                    empID = created_by,
                    patientID = 0,
                    agency_db = agency_db,
                    inputData = pPayer
                ) />
                <cfset arrayAppend(result.errors, "Payer insert failed: " & cfcatch.message) />
            </cfcatch>
        </cftry>
        
        <cfreturn result />
    </cffunction>

    <!--- Helper function to process admission data --->
    <cffunction name="processAdmissionData" access="private" returntype="struct" hint="Process admission data insertion/update">
        <cfargument name="pAdmit" required="yes" type="struct" />
        <cfargument name="patientAIID" required="yes" type="numeric" />
        <cfargument name="assessmentID" required="yes" type="numeric" />
        <cfargument name="agency_db" required="yes" type="string" />
        <cfargument name="created_by" required="yes" type="numeric" />
        <cfargument name="patient_id" required="no" type="numeric" default="0" />
        
        <cfset var result = {"insertedAdmitID" = 0, "admitInserted" = false, "errors" = []} />
        
        <cftry>
            <cfset var m0104Date = structKeyExists(pAdmit, "M0104_PHYSN_RFRL_DT") ? parseDate(pAdmit.M0104_PHYSN_RFRL_DT) : "" />
            <cfset var dateF2F = structKeyExists(pAdmit, "Date_F2F") ? parseDate(pAdmit.Date_F2F) : "" />
            <cfset var advDirectiveDate = structKeyExists(pAdmit, "Advance_DirectiveDate") ? parseDate(pAdmit.Advance_DirectiveDate) : "" />
            <cfset var advanceDirectiveForDB = structKeyExists(pAdmit, "Advance_Directive") ? trim(pAdmit.Advance_Directive) : "" />
            <cfif len(advanceDirectiveForDB) GT 100>
                <cfset advanceDirectiveForDB = left(advanceDirectiveForDB, 100) />
            </cfif>
            
            <cfquery name="CheckExistingAdmit" datasource="#Application.DataSrc#">
                SELECT Admit_ID FROM #agency_db#.pt_admit_ai
                WHERE Patient_AI_ID = <cfqueryparam value="#patientAIID#" cfsqltype="cf_sql_integer">
                AND Assmt_ID = <cfqueryparam value="#assessmentID#" cfsqltype="cf_sql_integer">
                AND Status = 0 LIMIT 1
            </cfquery>
            
            <cfif CheckExistingAdmit.recordcount eq 0>
                <cfquery name="InsertAdmit" datasource="#Application.DataSrc#" result="admitResult">
                    INSERT INTO #agency_db#.pt_admit_ai (
                        Patient_AI_ID, Assmt_ID, M0104_PHYSN_RFRL_DT, Date_F2F, Refer_Phys_ID,
                        Render_Phys_ID, MD_Clinical_Condition, MD_Homebound, Advance_Directive,
                        Advance_DirectiveDate, Code_Status, Date_Create, Created_by,
                        Date_Change, Change_by, Status
                    ) VALUES (
                        <cfqueryparam value="#patientAIID#" cfsqltype="cf_sql_integer">,
                        <cfqueryparam value="#assessmentID#" cfsqltype="cf_sql_integer">,
                        <cfqueryparam value="#m0104Date#" cfsqltype="cf_sql_date" null="#len(trim(m0104Date)) eq 0#">,
                        <cfqueryparam value="#dateF2F#" cfsqltype="cf_sql_date" null="#len(trim(dateF2F)) eq 0#">,
                        <cfqueryparam value="#structKeyExists(pAdmit, 'Refer_Phys_ID') ? pAdmit.Refer_Phys_ID : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pAdmit, 'Refer_Phys_ID') or len(trim(pAdmit.Refer_Phys_ID)) eq 0#">,
                        <cfqueryparam value="#structKeyExists(pAdmit, 'Render_Phys_ID') ? pAdmit.Render_Phys_ID : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pAdmit, 'Render_Phys_ID') or len(trim(pAdmit.Render_Phys_ID)) eq 0#">,
                        <cfqueryparam value="#structKeyExists(pAdmit, 'MD_Clinical_Condition') ? pAdmit.MD_Clinical_Condition : ''#" cfsqltype="cf_sql_longvarchar" null="#not structKeyExists(pAdmit, 'MD_Clinical_Condition') or len(trim(pAdmit.MD_Clinical_Condition)) eq 0#">,
                        <cfqueryparam value="#structKeyExists(pAdmit, 'MD_Homebound') ? pAdmit.MD_Homebound : ''#" cfsqltype="cf_sql_longvarchar" null="#not structKeyExists(pAdmit, 'MD_Homebound') or len(trim(pAdmit.MD_Homebound)) eq 0#">,
                        <cfqueryparam value="#advanceDirectiveForDB#" cfsqltype="cf_sql_varchar" null="#len(advanceDirectiveForDB) eq 0#">,
                        <cfqueryparam value="#advDirectiveDate#" cfsqltype="cf_sql_date" null="#len(trim(advDirectiveDate)) eq 0#">,
                        <cfqueryparam value="#structKeyExists(pAdmit, 'Code_Status') ? pAdmit.Code_Status : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pAdmit, 'Code_Status') or len(trim(pAdmit.Code_Status)) eq 0#">,
                        <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                        <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">,
                        <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                        <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">,
                        <cfqueryparam value="0" cfsqltype="cf_sql_tinyint">
                    )
                </cfquery>
                <cfset result.insertedAdmitID = admitResult.GENERATED_KEY />
                <cfset result.admitInserted = true />
            <cfelse>
                <cfset result.insertedAdmitID = CheckExistingAdmit.Admit_ID />
                <cfquery name="UpdateAdmit" datasource="#Application.DataSrc#">
                    UPDATE #agency_db#.pt_admit_ai SET
                        M0104_PHYSN_RFRL_DT = <cfqueryparam value="#m0104Date#" cfsqltype="cf_sql_date" null="#len(trim(m0104Date)) eq 0#">,
                        Date_F2F = <cfqueryparam value="#dateF2F#" cfsqltype="cf_sql_date" null="#len(trim(dateF2F)) eq 0#">,
                        Refer_Phys_ID = <cfqueryparam value="#structKeyExists(pAdmit, 'Refer_Phys_ID') ? pAdmit.Refer_Phys_ID : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pAdmit, 'Refer_Phys_ID') or len(trim(pAdmit.Refer_Phys_ID)) eq 0#">,
                        Render_Phys_ID = <cfqueryparam value="#structKeyExists(pAdmit, 'Render_Phys_ID') ? pAdmit.Render_Phys_ID : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pAdmit, 'Render_Phys_ID') or len(trim(pAdmit.Render_Phys_ID)) eq 0#">,
                        MD_Clinical_Condition = <cfqueryparam value="#structKeyExists(pAdmit, 'MD_Clinical_Condition') ? pAdmit.MD_Clinical_Condition : ''#" cfsqltype="cf_sql_longvarchar" null="#not structKeyExists(pAdmit, 'MD_Clinical_Condition') or len(trim(pAdmit.MD_Clinical_Condition)) eq 0#">,
                        MD_Homebound = <cfqueryparam value="#structKeyExists(pAdmit, 'MD_Homebound') ? pAdmit.MD_Homebound : ''#" cfsqltype="cf_sql_longvarchar" null="#not structKeyExists(pAdmit, 'MD_Homebound') or len(trim(pAdmit.MD_Homebound)) eq 0#">,
                        Advance_Directive = <cfqueryparam value="#advanceDirectiveForDB#" cfsqltype="cf_sql_varchar" null="#len(advanceDirectiveForDB) eq 0#">,
                        Advance_DirectiveDate = <cfqueryparam value="#advDirectiveDate#" cfsqltype="cf_sql_date" null="#len(trim(advDirectiveDate)) eq 0#">,
                        Code_Status = <cfqueryparam value="#structKeyExists(pAdmit, 'Code_Status') ? pAdmit.Code_Status : ''#" cfsqltype="cf_sql_varchar" null="#not structKeyExists(pAdmit, 'Code_Status') or len(trim(pAdmit.Code_Status)) eq 0#">,
                        Date_Change = <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                        Change_by = <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">
                    WHERE Admit_ID = <cfqueryparam value="#result.insertedAdmitID#" cfsqltype="cf_sql_integer"> AND Status = 0
                </cfquery>
            </cfif>
            <cfcatch type="any">
                <!--- Extract agency ID from agency_db (format: agency_XXX) --->
                <cfset var agencyIDFromDB = 0 />
                <cfif find("agency_", agency_db) GT 0>
                    <cfset agencyIDFromDB = val(listLast(agency_db, "_")) />
                </cfif>
                <!--- Send exception email --->
                <cfset sendModuleExceptionEmail(
                    moduleName = "processAdmissionData",
                    error = cfcatch,
                    agencyID = agencyIDFromDB,
                    empID = created_by,
                    patientID = val(patient_id),
                    agency_db = agency_db,
                    inputData = pAdmit
                ) />
                <cfset arrayAppend(result.errors, "Admission insert/update failed: " & cfcatch.message) />
            </cfcatch>
        </cftry>
        
        <!--- Update pAdmit table directly with pAdmit data --->
        <cfif result.insertedAdmitID gt 0 AND val(patient_id) gt 0>
            <cftry>
                <!--- Prepare admit data from pAdmit --->
                <cfset var m0104Date = structKeyExists(pAdmit, "M0104_PHYSN_RFRL_DT") ? parseDate(pAdmit.M0104_PHYSN_RFRL_DT) : "" />
                <cfset var dateF2F = structKeyExists(pAdmit, "Date_F2F") ? parseDate(pAdmit.Date_F2F) : "" />
                <cfset var advDirectiveDate = structKeyExists(pAdmit, "Advance_DirectiveDate") ? parseDate(pAdmit.Advance_DirectiveDate) : "" />
                <cfset var referPhysID = structKeyExists(pAdmit, "Refer_Phys_ID") ? trim(pAdmit.Refer_Phys_ID) : "" />
                <cfset var renderPhysID = structKeyExists(pAdmit, "Render_Phys_ID") ? trim(pAdmit.Render_Phys_ID) : "" />
                <cfset var mdClinicalCondition = structKeyExists(pAdmit, "MD_Clinical_Condition") ? trim(pAdmit.MD_Clinical_Condition) : "" />
                <cfset var mdHomebound = structKeyExists(pAdmit, "MD_Homebound") ? trim(pAdmit.MD_Homebound) : "" />
                <cfset var advanceDirective = structKeyExists(pAdmit, "Advance_Directive") ? trim(pAdmit.Advance_Directive) : "" />
                <cfset var codeStatus = structKeyExists(pAdmit, "Code_Status") ? trim(pAdmit.Code_Status) : "" />
                
                <!--- CONDITION 2: If a pAdmit record is already created for this patient, DO NOT CREATE/UPDATE pAdmit --->
                <cfquery name="CheckPAdmit" datasource="#Application.DataSrc#">
                    SELECT Admit_ID
                    FROM #agency_db#.pAdmit
                    WHERE Patient_ID = <cfqueryparam value="#val(patient_id)#" cfsqltype="cf_sql_integer">
                    AND Status = 0
                    ORDER BY Admit_ID DESC
                    LIMIT 1
                </cfquery>
                
                <!--- Skip pAdmit update if any pAdmit record exists for this patient (CONDITION 2) --->
                <!--- If CheckPAdmit.recordcount GT 0, a pAdmit record exists - skip update to prevent overwriting --->
                <!--- NOTE: pPtMeds and pProblem will still be populated as per CONDITION 3 (handled in sync files) --->
                <cfif CheckPAdmit.recordcount EQ 0>
                    <!--- No pAdmit record exists - still skip update as per requirement: DO NOT CREATE/UPDATE pAdmit --->
                    <!--- This ensures we don't create new pAdmit records either --->
                </cfif>
                <cfcatch type="any">
                    <!--- Extract agency ID from agency_db (format: agency_XXX) --->
                    <cfset var agencyIDFromDB = 0 />
                    <cfif find("agency_", agency_db) GT 0>
                        <cfset agencyIDFromDB = val(listLast(agency_db, "_")) />
                    </cfif>
                    <!--- Send exception email --->
                    <cfset sendModuleExceptionEmail(
                        moduleName = "processAdmissionData - Update pAdmit",
                        error = cfcatch,
                        agencyID = agencyIDFromDB,
                        empID = created_by,
                        patientID = val(patient_id),
                        agency_db = agency_db,
                        inputData = pAdmit
                    ) />
                    <cfset arrayAppend(result.errors, "Update pAdmit table failed: " & cfcatch.message) />
                </cfcatch>
            </cftry>
        </cfif>
        
        <cfreturn result />
    </cffunction>

    <!--- Helper function to process problems --->
    <cffunction name="processProblems" access="private" returntype="struct" hint="Process problem data insertion/update">
        <cfargument name="problems" required="yes" type="array" />
        <cfargument name="patientAIID" required="yes" type="numeric" />
        <cfargument name="assessmentID" required="yes" type="numeric" />
        <cfargument name="agency_db" required="yes" type="string" />
        <cfargument name="created_by" required="yes" type="numeric" />
        
        <cfset var result = {"problemCount" = 0, "problemIDs" = [], "errors" = []} />
        
        <cfset var problemIndex = 1 />
        <cfloop array="#problems#" index="problemDesc">
            <cftry>
                <cfquery name="CheckExistingProblem" datasource="#Application.DataSrc#">
                    SELECT Problem_ID FROM #agency_db#.problems_ai
                    WHERE Patient_AI_ID = <cfqueryparam value="#patientAIID#" cfsqltype="cf_sql_integer">
                    AND Assmt_ID = <cfqueryparam value="#assessmentID#" cfsqltype="cf_sql_integer">
                    AND Description = <cfqueryparam value="#problemDesc#" cfsqltype="cf_sql_longvarchar">
                    AND Status = 0 LIMIT 1
                </cfquery>
                
                <cfif CheckExistingProblem.recordcount eq 0>
                    <cfquery name="InsertProblem" datasource="#Application.DataSrc#" result="problemResult">
                        INSERT INTO #agency_db#.problems_ai (
                            Patient_AI_ID, Assmt_ID, Status, M0_No, Description, Answer,
                            Severity, dx_order, Oasis_Deficits, Date_Create, Created_by,
                            Date_Change, Change_by, record_timestamp
                        ) VALUES (
                            <cfqueryparam value="#patientAIID#" cfsqltype="cf_sql_integer">,
                            <cfqueryparam value="#assessmentID#" cfsqltype="cf_sql_integer">,
                            <cfqueryparam value="0" cfsqltype="cf_sql_tinyint">,
                            <cfqueryparam value="" cfsqltype="cf_sql_varchar" null="true">,
                            <cfqueryparam value="#problemDesc#" cfsqltype="cf_sql_longvarchar">,
                            <cfqueryparam value="" cfsqltype="cf_sql_longvarchar" null="true">,
                            <cfqueryparam value="" cfsqltype="cf_sql_varchar" null="true">,
                            <cfqueryparam value="#problemIndex#" cfsqltype="cf_sql_integer">,
                            <cfqueryparam value="" cfsqltype="cf_sql_longvarchar" null="true">,
                            <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                            <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">,
                            <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                            <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">,
                            <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">
                        )
                    </cfquery>
                    <cfset arrayAppend(result.problemIDs, problemResult.GENERATED_KEY) />
                    <cfset result.problemCount++ />
                <cfelse>
                    <cfset var existingProblemID = CheckExistingProblem.Problem_ID />
                    <cfquery name="UpdateProblem" datasource="#Application.DataSrc#">
                        UPDATE #agency_db#.problems_ai SET
                            dx_order = <cfqueryparam value="#problemIndex#" cfsqltype="cf_sql_integer">,
                            Date_Change = <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">,
                            Change_by = <cfqueryparam value="#created_by#" cfsqltype="cf_sql_integer">,
                            record_timestamp = <cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">
                        WHERE Problem_ID = <cfqueryparam value="#existingProblemID#" cfsqltype="cf_sql_integer"> AND Status = 0
                    </cfquery>
                    <cfset arrayAppend(result.problemIDs, existingProblemID) />
                </cfif>
                <cfset problemIndex++ />
                <cfcatch type="any">
                    <!--- Extract agency ID from agency_db (format: agency_XXX) --->
                    <cfset var agencyIDFromDB = 0 />
                    <cfif find("agency_", agency_db) GT 0>
                        <cfset agencyIDFromDB = val(listLast(agency_db, "_")) />
                    </cfif>
                    <!--- Send exception email --->
                    <cfset sendModuleExceptionEmail(
                        moduleName = "processProblems",
                        error = cfcatch,
                        agencyID = agencyIDFromDB,
                        empID = created_by,
                        patientID = 0,
                        agency_db = agency_db,
                        inputData = {"problem": problemDesc, "problemIndex": problemIndex}
                    ) />
                    <cfset arrayAppend(result.errors, "Problem insert failed: " & cfcatch.message) />
                </cfcatch>
            </cftry>
        </cfloop>
        
        <cfreturn result />
    </cffunction>
    
    <!--- Bulk Import Patient Data --->
    <cffunction name="importPatientData" access="remote" returnformat="JSON" hint="Import complete patient data into AI tables">
        <cfargument name="Agency_ID" required="yes" hint="Agency ID">
        <cfargument name="appkey" required="yes" hint="appkey">
        <cfargument name="Emp_ID" required="no" default="0" hint="Emp ID (optional, defaults to 0)">
        <cfargument name="Patient_ID" required="yes" hint="Patient ID">
        <cfargument name="Assessment_ID" required="yes" hint="Assessment ID">
        <cfargument name="Website_name" required="no" default="" hint="Website name">
        <cfargument name="extracted_data" required="yes" hint="JSON string or struct with extracted data">
        
        <cfset var response = {} />
        <cfset var insertedPatientID = 0 />
        <cfset var insertedContactID = 0 />
        <cfset var insertedPayerID = 0 />
        <cfset var insertedAdmitID = 0 />
        <cfset var insertedMedicationIDs = [] />
        <cfset var insertedProblemIDs = [] />
        <cfset var medicationCount = 0 />
        <cfset var problemCount = 0 />
        <cfset var contactInserted = false />
        <cfset var payerInserted = false />
        <cfset var admitInserted = false />
        <cfset var errors = [] />
        <cfset var decryptedAgencyID = "" />
        <cfset var decryptedEmpID = "" />
        <cfset var decryptedPatientID = "" />
        <cfset var decryptedAssessmentID = "" />
        <cfset var decryptedAppKey = "" />
        <cfset var extractedJSONString = "" />
        <!--- Store original encrypted values for email reporting --->
        <cfset var originalAgencyID = arguments.Agency_ID />
        <cfset var originalEmpID = arguments.Emp_ID />
        <cfset var originalPatientID = arguments.Patient_ID />
        <cfset var originalAssessmentID = arguments.Assessment_ID />
        <cfset var originalAppKey = arguments.appkey />
        
        <cftry>
            <!--- Attempt to decrypt incoming values (handles encrypted payloads) --->
            <cfset decryptedAgencyID = maybeDecrypt(arguments.Agency_ID, true) />
            <cfset decryptedEmpID = maybeDecrypt(arguments.Emp_ID, true) />
            <cfset decryptedPatientID = maybeDecrypt(arguments.Patient_ID, true) />
            <cfset decryptedAssessmentID = maybeDecrypt(arguments.Assessment_ID, true) />
            <cfset decryptedAppKey = maybeDecrypt(arguments.appkey) />
 
            <cfif decryptedAgencyID NEQ arguments.Agency_ID>
                <cfset arguments.Agency_ID = decryptedAgencyID />
            </cfif>
            <cfif decryptedEmpID NEQ arguments.Emp_ID>
                <cfset arguments.Emp_ID = decryptedEmpID />
            </cfif>
            <cfif decryptedPatientID NEQ arguments.Patient_ID>
                <cfset arguments.Patient_ID = decryptedPatientID />
            </cfif>
            <cfif decryptedAssessmentID NEQ arguments.Assessment_ID>
                <cfset arguments.Assessment_ID = decryptedAssessmentID />
            </cfif>
            <cfif len(decryptedAppKey)>
                <cfset arguments.appkey = decryptedAppKey />
            </cfif> 

            <!--- Normalize numeric arguments --->
            <cfset arguments.Agency_ID = val(arguments.Agency_ID) />
            <cfset arguments.Emp_ID = val(arguments.Emp_ID) />
            <cfset arguments.Patient_ID = val(arguments.Patient_ID) />
            <cfset arguments.Assessment_ID = val(arguments.Assessment_ID) />

            <!--- Validate Basic Authentication --->
            <cfset var authResult = validateBasicAuth(arguments.appkey, arguments.Agency_ID, arguments.Emp_ID, arguments.Patient_ID) />
            <cfif not authResult.valid>
                <cfset response = {
                    "success": false,
                    "message": authResult.message,
                    "data": {}
                } />
                <cfreturn serializeJSON(response) />
            </cfif>
            
            <cfset var agency_db = 'agency_' & arguments.Agency_ID   />
            <cfset var created_by = arguments.Emp_ID   />
            
            <!--- Parse extracted_data if it's JSON --->
            <cfif isJSON(arguments.extracted_data)>
                <cfset var data = deserializeJSON(arguments.extracted_data) />
                <cfset extractedJSONString = arguments.extracted_data />
            <cfelse>
                <cfset var data = arguments.extracted_data />
                <cftry>
                    <cfset extractedJSONString = serializeJSON(data) />
                    <cfcatch>
                        <cfset extractedJSONString = "" />
                    </cfcatch>
                </cftry>
            </cfif>
            
            <!--- Initialize query log --->
            <cfset request.bulk_import_queries = [] />
            
            <!--- Start transaction --->
            <cftransaction>
                <!--- 1. Insert or Update Patient Data --->
                <cftry>
                    <cfset var patientResult = processPatientData(
                        data = data,
                        agency_db = agency_db,
                        created_by = created_by,
                        patient_id = arguments.Patient_ID
                    ) />
                    <cfset insertedPatientID = patientResult.insertedPatientID />
                    <cfset var patientAction = patientResult.patientAction />
                    <cfloop array="#patientResult.errors#" index="err">
                        <cfset arrayAppend(errors, err) />
                    </cfloop>
                    <cfcatch type="any">
                        <!--- Send exception email --->
                        <cfset sendProcessPatientDataExceptionEmail(
                            error = cfcatch,
                            agencyID = arguments.Agency_ID,
                            empID = arguments.Emp_ID,
                            patientID = arguments.Patient_ID,
                            agency_db = agency_db,
                            data = data
                        ) />
                        <cfset arrayAppend(errors, "processPatientData exception: " & cfcatch.message) />
                        <cfrethrow />
                    </cfcatch>
                </cftry>
                
                <!--- 2. Insert Emergency Contact Data --->
                <cfif structKeyExists(data, "pPtContacts") and insertedPatientID gt 0>
                    <cfset var contactResult = processContactData(
                        pPtContacts = data.pPtContacts,
                        patientAIID = insertedPatientID,
                        agency_db = agency_db,
                        created_by = created_by
                    ) />
                    <cfset insertedContactID = contactResult.insertedContactID />
                    <cfset contactInserted = contactResult.contactInserted />
                    <cfloop array="#contactResult.errors#" index="err">
                        <cfset arrayAppend(errors, err) />
                    </cfloop>
                </cfif>
                
                <!--- 3. Insert Payer/Subscriber Data --->
                <cfif structKeyExists(data, "pPayer") and insertedPatientID gt 0>
                    <cfset var payerResult = processPayerData(
                        pPayer = data.pPayer,
                        patientAIID = insertedPatientID,
                        agency_db = agency_db,
                        created_by = created_by
                    ) />
                    <cfset insertedPayerID = payerResult.insertedPayerID />
                    <cfset payerInserted = payerResult.payerInserted />
                    <cfloop array="#payerResult.errors#" index="err">
                        <cfset arrayAppend(errors, err) />
                    </cfloop>
                </cfif>
                
                <!--- 4. Insert Admission/Physician Data --->
                <cfif structKeyExists(data, "pAdmit") and insertedPatientID gt 0>
                    <cfset var admitResult = processAdmissionData(
                        pAdmit = data.pAdmit,
                        patientAIID = insertedPatientID,
                        assessmentID = arguments.Assessment_ID,
                        agency_db = agency_db,
                        created_by = created_by,
                        patient_id = arguments.Patient_ID
                    ) />
                    <cfset insertedAdmitID = admitResult.insertedAdmitID />
                    <cfset admitInserted = admitResult.admitInserted />
                    <cfloop array="#admitResult.errors#" index="err">
                        <cfset arrayAppend(errors, err) />
                    </cfloop>
                </cfif>
                
                <!--- 5. Insert Medication Data --->
                <cfif structKeyExists(data, "Medications") and isArray(data.Medications) and arrayLen(data.Medications) gt 0>
                    <cfset var medResult = processMedications(
                        medications = data.Medications,
                        patientID = arguments.Patient_ID,
                        patientAIID = insertedPatientID,
                        agency_db = agency_db,
                        created_by = created_by
                    ) />
                    <cfset medicationCount = medResult.medicationCount />
                    <cfset insertedMedicationIDs = medResult.medicationIDs />
                    <cfloop array="#medResult.errors#" index="err">
                        <cfset arrayAppend(errors, err) />
                    </cfloop>
                </cfif>
                
                <!--- 6. Insert Problem Data --->
                <cfif structKeyExists(data, "pProblem") and structKeyExists(data.pProblem, "description") and isArray(data.pProblem.description)>
                    <cftry>
                        <cfset var problemResult = processProblems(
                            problems = data.pProblem.description,
                            patientAIID = insertedPatientID,
                            assessmentID = arguments.Assessment_ID,
                            agency_db = agency_db,
                            created_by = created_by
                        ) />
                        <cfset problemCount = problemResult.problemCount />
                        <cfset insertedProblemIDs = problemResult.problemIDs />
                        <cfloop array="#problemResult.errors#" index="err">
                            <cfset arrayAppend(errors, err) />
                        </cfloop>
                        
                        <!--- Send email notification about problems insertion --->
                        <cfif problemResult.problemCount GT 0>
                            <cftry>
                                <cfmail to="#this.notificationEmails#" 
                                        from="notification@myhomecarebiz.com" 
                                        subject="Bulk Import AI API - Problems Inserted: #problemResult.problemCount# problem(s)" 
                                        type="html">
                                    <h3 style="color: green;">Problems Successfully Inserted</h3>
                                    <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                                    <p><strong>Agency ID:</strong> #arguments.Agency_ID#</p>
                                    <p><strong>Employee ID:</strong> #arguments.Emp_ID#</p>
                                    <p><strong>Patient ID:</strong> #arguments.Patient_ID#</p>
                                    <p><strong>Assessment ID:</strong> #arguments.Assessment_ID#</p>
                                    <p><strong>Agency Database:</strong> #agency_db#</p>
                                    <p><strong>Patient AI ID:</strong> #insertedPatientID#</p>
                                    <hr>
                                    <h4>Insertion Summary:</h4>
                                    <p><strong>Problems Inserted:</strong> #problemResult.problemCount#</p>
                                    <p><strong>Problem IDs:</strong> #arrayToList(problemResult.problemIDs, ", ")#</p>
                                    <cfif arrayLen(problemResult.errors) GT 0>
                                        <hr>
                                        <h4 style="color: orange;">Errors:</h4>
                                        <ul>
                                            <cfloop array="#problemResult.errors#" index="err">
                                                <li>#htmlEditFormat(err)#</li>
                                            </cfloop>
                                        </ul>
                                    </cfif>
                                    <hr>
                                    <h4>Input Problems Data:</h4>
                                    <pre style="white-space: pre-wrap; font-family: monospace; background-color: ##f5f5f5; padding: 10px;">#htmlEditFormat(serializeJSON(data.pProblem.description))#</pre>
                                    <hr>
                                    <p style="color: ##666; font-size: 12px; margin-top: 20px;">
                                        <strong>Note:</strong> Problems have been inserted into <strong>#agency_db#.problems_ai</strong> table with status=0.<br>
                                        <strong>Next Step:</strong> Call <strong>sync_problems_action.cfm</strong> to sync these problems from <strong>problems_ai</strong> to <strong>pProblem</strong> table.
                                    </p>
                                    <hr>
                                    <p><em>This is an automated notification from the Bulk Import AI API</em></p>
                                </cfmail>
                                <cfcatch type="any">
                                    <!--- Silently fail if email notification fails --->
                                </cfcatch>
                            </cftry>
                        </cfif>
                        <cfcatch type="any">
                            <!--- Send exception email for processProblems call failure --->
                            <cfset sendModuleExceptionEmail(
                                moduleName = "importPatientData - processProblems Call",
                                error = cfcatch,
                                agencyID = arguments.Agency_ID,
                                empID = arguments.Emp_ID,
                                patientID = arguments.Patient_ID,
                                agency_db = agency_db,
                                inputData = structKeyExists(data, "pProblem") ? data.pProblem : {}
                            ) />
                            <cfset arrayAppend(errors, "processProblems call failed: " & cfcatch.message) />
                        </cfcatch>
                    </cftry>
                </cfif>
                
            </cftransaction>
            <!--- Transaction auto-commits here if successful --->
            
            <!--- Sync patient data from patients_ai to pPatients (all details except Pt_First and Pt_Last) --->
            <cfif arguments.Patient_ID GT 0>
                <cftry>
                    <!--- Set up request scope variables for sync --->
                    <cfset request.sync_patient_id = arguments.Patient_ID />
                    <cfset request.sync_assessment_id = arguments.Assessment_ID />
                    <cfset request.sync_employee_id = arguments.Emp_ID />
                    
                    <!--- Set Request.prefix_db_agency for sync file (used instead of session.AgencyID) --->
                    <cfset Request.prefix_db_agency = agency_db />
                    
                    <!--- Store Vertex API patient data in request scope if available --->
                    <cfif structKeyExists(data, "pPatient") AND isStruct(data.pPatient) AND NOT structIsEmpty(data.pPatient)>
                        <cfset request.vertex_api_patient_data = data.pPatient />
                    </cfif>
                    <cfif structKeyExists(data, "vertex_api_patient_data") AND isStruct(data.vertex_api_patient_data) AND NOT structIsEmpty(data.vertex_api_patient_data)>
                        <cfset request.vertex_api_patient_data = data.vertex_api_patient_data />
                    </cfif>
                    <cfif structKeyExists(data, "pAdmit") AND isStruct(data.pAdmit) AND NOT structIsEmpty(data.pAdmit)>
                        <cfset request.vertex_api_admit_data = data.pAdmit />
                    </cfif>
                    <cfif structKeyExists(data, "vertex_api_admit_data") AND isStruct(data.vertex_api_admit_data) AND NOT structIsEmpty(data.vertex_api_admit_data)>
                        <cfset request.vertex_api_admit_data = data.vertex_api_admit_data />
                    </cfif>
                   
                    
                    <!--- Include sync file to sync from patients_ai to pPatients --->
                    <cfinclude template="../../patientadmin_new/patient/sync_ai_patients_admit.cfm" />
                    
                    <!--- Check sync result --->
                    <cfif structKeyExists(request, "patient_admit_sync_result")>
                        <cfif request.patient_admit_sync_result.patient_synced>
                            <cfset arrayAppend(errors, "Patient data synced successfully from patients_ai to pPatients") />
                        <cfelse>
                            <cfif arrayLen(request.patient_admit_sync_result.errors) GT 0>
                                <cfloop array="#request.patient_admit_sync_result.errors#" index="syncError">
                                    <cfset arrayAppend(errors, "Sync error: " & syncError) />
                                </cfloop>
                            </cfif>
                        </cfif>
                    </cfif>
                    <cfcatch type="any">
                        <!--- Send email notification about sync failure --->
                        <cftry>
                            <cfmail to="#this.notificationEmails#"
                                    from="sync@myhomecarebiz.com"
                                    subject="Bulk Import AI - Sync Failed for Patient ID #arguments.Patient_ID#"
                                    type="html">
                                <h3 style="color: red;">Bulk Import AI - Sync Failed</h3>
                                <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                                <p><strong>Agency ID:</strong> #arguments.Agency_ID#</p>
                                <p><strong>Patient ID:</strong> #arguments.Patient_ID#</p>
                                <hr>
                                <h4>Error Details:</h4>
                                <p><strong>Error Type:</strong> #htmlEditFormat(cfcatch.type)#</p>
                                <p><strong>Error Message:</strong> #htmlEditFormat(cfcatch.message)#</p>
                                <p><strong>Error Detail:</strong> #htmlEditFormat(cfcatch.detail)#</p>
                                <cfif structKeyExists(cfcatch, "stackTrace")>
                                    <hr>
                                    <h4>Stack Trace:</h4>
                                    <pre style="background-color: ##f5f5f5; padding: 10px; border: 1px solid ##ddd; overflow-x: auto; font-size: 11px;">#htmlEditFormat(left(cfcatch.stackTrace, 2000))#</pre>
                                </cfif>
                            </cfmail>
                            <cfcatch>
                                <!--- Silently fail if email fails --->
                            </cfcatch>
                        </cftry>
                        <!--- Log sync error but don't fail the entire import --->
                        <cfset arrayAppend(errors, "Sync from patients_ai to pPatients failed: " & cfcatch.message) />
                    </cfcatch>
                </cftry>
            <cfelse>
                <!--- Send email notification when sync is NOT called due to invalid Patient_ID --->
                <cftry>
                    <cfmail to="#this.notificationEmails#"
                            from="sync@myhomecarebiz.com"
                            subject="Bulk Import AI - Sync NOT Called - Invalid Patient ID"
                            type="html">
                        <h3 style="color: orange;">Bulk Import AI - Sync NOT Called</h3>
                        <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                        <p><strong>Agency ID:</strong> #arguments.Agency_ID#</p>
                        <p><strong>Agency Database:</strong> #agency_db#</p>
                        <p><strong>Patient ID:</strong> #arguments.Patient_ID#</p>
                        <p><strong>Assessment ID:</strong> #arguments.Assessment_ID#</p>
                        <p><strong>Employee ID:</strong> #arguments.Emp_ID#</p>
                        <hr>
                        <h4>Reason:</h4>
                        <p style="color: red;"><strong>Patient_ID is 0 or negative - Sync will NOT be called</strong></p>
                        <p><strong>Condition:</strong> arguments.Patient_ID GT 0 = <strong>FALSE</strong></p>
                        <hr>
                        <p><em>sync_ai_patients_admit.cfm was NOT included because Patient_ID is invalid</em></p>
                    </cfmail>
                    <cfcatch>
                        <!--- Silently fail if email fails --->
                    </cfcatch>
                </cftry>
            </cfif>
            
            <!--- Send query dump email --->
            <cfset sendQueryDumpEmail(
                agencyID = arguments.Agency_ID,
                empID = arguments.Emp_ID,
                patientID = arguments.Patient_ID,
                agency_db = agency_db
            ) />
            
            <!--- Send success email notification --->
            <cfset sendSuccessEmail(
                insertedPatientID = insertedPatientID,
                patientAction = patientAction,
                insertedContactID = insertedContactID,
                contactInserted = contactInserted,
                insertedPayerID = insertedPayerID,
                payerInserted = payerInserted,
                insertedAdmitID = insertedAdmitID,
                admitInserted = admitInserted,
                medicationCount = medicationCount,
                problemCount = problemCount,
                errors = errors,
                agencyID = arguments.Agency_ID,
                empID = arguments.Emp_ID,
                patientID = arguments.Patient_ID,
                assessmentID = arguments.Assessment_ID,
                websiteName = arguments.Website_name,
                extractedJSONString = extractedJSONString,
                originalAgencyID = originalAgencyID,
                originalEmpID = originalEmpID,
                originalPatientID = originalPatientID,
                originalAssessmentID = originalAssessmentID,
                originalAppKey = originalAppKey,
                decryptedAgencyID = decryptedAgencyID,
                decryptedEmpID = decryptedEmpID,
                decryptedPatientID = decryptedPatientID,
                decryptedAssessmentID = decryptedAssessmentID,
                decryptedAppKey = decryptedAppKey,
                agency_db = agency_db
            ) />
            
            <!--- Build success response --->
            <cfset response = {
                "success": true,
                "message": "Patient data imported successfully (patient #patientAction#)",
                "data": {
                    "patient_ai_id": insertedPatientID,
                    "patient_action": patientAction,
                    "contact_inserted": contactInserted,
                    "contact_id": insertedContactID,
                    "payer_inserted": payerInserted,
                    "payer_id": insertedPayerID,
                    "admit_inserted": admitInserted,
                    "admit_id": insertedAdmitID,
                    "medications_inserted": medicationCount,
                    "medication_ids": insertedMedicationIDs,
                    "problems_inserted": problemCount,
                    "problem_ids": insertedProblemIDs,
                    "errors": errors,
                    "debug_info": {
                        "datasource": Application.DataSrc,
                        "agency_db": agency_db,
                        "transaction_completed": true
                    }
                }
            } />
            
            <cfcatch type="any">
                <!--- Send query dump email (even on error) --->
                <cfset sendQueryDumpEmail(
                    agencyID = arguments.Agency_ID,
                    empID = arguments.Emp_ID,
                    patientID = arguments.Patient_ID,
                    agency_db = agency_db
                ) />
                
                <!--- Send error email notification --->
                <cfset sendErrorEmail(
                    error = cfcatch,
                    agencyID = arguments.Agency_ID,
                    empID = arguments.Emp_ID,
                    patientID = arguments.Patient_ID,
                    assessmentID = arguments.Assessment_ID,
                    websiteName = arguments.Website_name,
                    extractedJSONString = extractedJSONString,
                    originalAgencyID = originalAgencyID,
                    originalEmpID = originalEmpID,
                    originalPatientID = originalPatientID,
                    originalAssessmentID = originalAssessmentID,
                    originalAppKey = originalAppKey,
                    decryptedAgencyID = decryptedAgencyID,
                    decryptedEmpID = decryptedEmpID,
                    decryptedPatientID = decryptedPatientID,
                    decryptedAssessmentID = decryptedAssessmentID,
                    decryptedAppKey = decryptedAppKey,
                    insertedPatientID = insertedPatientID,
                    medicationCount = medicationCount,
                    problemCount = problemCount,
                    errors = errors
                ) />
                
                <cfset response = {
                    "success": false,
                    "message": "Failed to import patient data",
                    "error": cfcatch.message,
                    "detail": cfcatch.detail,
                    "data": {
                        "patient_ai_id": insertedPatientID,
                        "medications_inserted": medicationCount,
                        "problems_inserted": problemCount,
                        "errors": errors
                    }
                } />
            </cfcatch>
        </cftry>
        
        <cfreturn serializeJSON(response) />
    </cffunction>
    
</cfcomponent>

