<!--- Vertex job processor (included from call_vertex_api.cfm synchronously) --->
<cfparam name="agencyId" default="" />
<cfparam name="employeeId" default="0" />
<cfparam name="employeeIdVal" default="0" />
<cfparam name="patientId" default="" />
<cfparam name="patientIdVal" default="0" />
<cfparam name="fileId" default="0" />
<cfparam name="dupFileName" default="" />
<cfparam name="s3Url" default="" />
<cfparam name="vtxJobRowId" default="0" />
<!--- agencyId was previously set from cfthread attributes; ensure it exists when included directly --->
<cfif NOT len(trim(agencyId & ""))>
    <cfif structKeyExists(session, "AgencyID") AND len(trim(session.AgencyID & ""))>
        <cfset agencyId = session.AgencyID />
    <cfelseif structKeyExists(session, "AgencyId") AND len(trim(session.AgencyId & ""))>
        <cfset agencyId = session.AgencyId />
    </cfif>
</cfif>
<cfset session.AgencyID = agencyId />
<cfset session.AgencyId = agencyId />
<cfset vertexEmployeeFallback = 0 />
<cfinclude template="vertex_api_resolve_employee.cfm" />
<cfif NOT structKeyExists(variables, "responseStruct") OR NOT isStruct(variables.responseStruct)>
    <cfset responseStruct = { "success": false, "message": "", "errorDetail": "", "data": {} } />
</cfif>

<cfif NOT isDefined("table_files") OR NOT len(table_files)>
    <cfif Request.prefix_db_agency EQ 'agency_455'>
        <cfset table_files = Request.prefix_db_lookup & '.files_old' />
    <cfelse>
        <cfset table_files = Request.prefix_db_agency & '.files' />
    </cfif>
</cfif>

    <cfinclude template="vertex_api_config.cfm" />
    <!--- Obtain access token --->
    <cfinclude template="vertex_api_get_token.cfm" />
    <cfset accessToken = vertexAccessToken />
    <cfset accessTokenType = vertexAccessTokenType />
    <cfset tokenURL = vertexTokenURL />
    <cfset tokenStatusCode = vertexTokenStatusCode />
    <cfset tokenResponseBody = vertexTokenResponseBody />
    <cfset tokenRequestBody = vertexTokenRequestBody />

    <cfif NOT len(accessToken)>
        <cfset statusCode = 502>
        <cfset responseStruct.success = false>
        <cfset responseStruct.message = "Vertex authentication failed (token unavailable).">
        <cfset responseStruct.data = {
            "token_status": tokenStatusCode,
            "token_response": tokenResponseBody
        }>
        <cfmail to="velmurugan@myhomecarebiz.com"
                from="error@myhomecarebiz.com"
                subject="Vertex token request failed for Agency #session.AgencyID#"
                type="html">
            <h3 style="color:red;">Vertex token request failed</h3>
            <p><strong>Agency ID:</strong> #session.AgencyID#</p>
            <p><strong>Employee ID:</strong> #employeeId#</p>
            <p><strong>Patient ID:</strong> #patientId#</p>
            <p><strong>File ID:</strong> #fileId#</p>
            <p><strong>Dup File Name:</strong> #dupFileName#</p>
            <p><strong>S3 URL:</strong> #s3Url#</p>
            <p><strong>Token Status:</strong> #tokenStatusCode#</p>
            <p><strong>Token URL:</strong> #tokenURL#</p>
            <p><strong>Token Request Body:</strong></p>
            <pre>#encodeForHTML(tokenRequestBody)#</pre>
            <p><strong>Token Type:</strong> #accessTokenType#</p>
            <p><strong>Token Response:</strong></p>
            <pre>#encodeForHTML(tokenResponseBody)#</pre>
        </cfmail>
        <cfquery name="saveVertexJobFailedToken" datasource="#Application.DataSrc#">
            UPDATE #Request.prefix_db_agency#.vertex_jobs
            SET job_status = <cfqueryparam value="failed" cfsqltype="cf_sql_varchar">,
                error_message = <cfqueryparam value="#responseStruct.message#" cfsqltype="cf_sql_longvarchar">,
                result_json = <cfqueryparam value="#serializeJSON(responseStruct)#" cfsqltype="cf_sql_longvarchar">,
                raw_response = <cfqueryparam value="#tokenResponseBody#" cfsqltype="cf_sql_longvarchar">,
                Last_Checked = NOW()
            WHERE ID = <cfqueryparam value="#vtxJobRowId#" cfsqltype="cf_sql_bigint">
        </cfquery>
        <cfexit />
    </cfif>
    <cfif NOT len(accessTokenType)>
        <cfset accessTokenType = "Bearer" />
    </cfif>

    <!--- Call Vertex API --->
    <cfhttp url="#vertexApiBaseHost#/process_and_send_data/" method="post" timeout="1200" result="vertexResponse" throwonerror="false">
        <cfhttpparam type="header" name="Authorization" value="#accessTokenType# #accessToken#">
        <cfhttpparam type="header" name="accept" value="application/json">
        <cfset vertexRequiredPayloadKeys = "AGENCY_ID,PATIENT_ID,ASSESSMENT_ID,appKey,Website_name,Emp_ID,s3_url">
        <cfloop collection="#payload#" item="payloadKey">
            <cfif listFindNoCase(vertexRequiredPayloadKeys, payloadKey) OR len(payload[payloadKey])>
                <cfhttpparam type="formField" name="#payloadKey#" value="#payload[payloadKey]#">
            </cfif>
        </cfloop>
    </cfhttp>

    <cfset httpStatus = vertexResponse.StatusCode>
    <cfset responseBody = trim(vertexResponse.FileContent)>
    <cfset parsedRemoteResponse = {}>

    <cfif len(responseBody) AND isJSON(responseBody)>
        <cfset parsedRemoteResponse = deserializeJSON(responseBody)>
    </cfif>

    <cfset httpStatusCode = Left(trim(httpStatus), 3) />
    <cfset isHttp202Accepted = (httpStatusCode EQ "202") OR find("202", httpStatus) GT 0 />
    <!--- 200 = sync success; 202 Accepted = async queued (process_and_send_data) --->
    <cfset isSuccess = (httpStatusCode EQ "200") />
    <cfset isHttpAccepted = isSuccess OR isHttp202Accepted />
    <cfset responseStruct.success = isHttpAccepted />

    <!--- process_and_send_data async response: {"task_id","status","submitted_at","poll_url"} — persist full JSON and exit --->
    <cfset remoteTaskId = "" />
    <cfset remoteSubmitStatus = "" />
    <cfset remotePollUrl = "" />
    <cfset remoteSubmittedAt = "" />
    <cfif isStruct(parsedRemoteResponse)>
        <cfif structKeyExists(parsedRemoteResponse, "task_id") AND len(trim(parsedRemoteResponse.task_id & ""))>
            <cfset remoteTaskId = trim(parsedRemoteResponse.task_id & "") />
        </cfif>
        <cfif structKeyExists(parsedRemoteResponse, "status") AND len(trim(parsedRemoteResponse.status & ""))>
            <cfset remoteSubmitStatus = lCase(trim(parsedRemoteResponse.status & "")) />
        </cfif>
        <cfif structKeyExists(parsedRemoteResponse, "poll_url") AND len(trim(parsedRemoteResponse.poll_url & ""))>
            <cfset remotePollUrl = trim(parsedRemoteResponse.poll_url & "") />
        </cfif>
        <cfif structKeyExists(parsedRemoteResponse, "submitted_at") AND len(trim(parsedRemoteResponse.submitted_at & ""))>
            <cfset remoteSubmittedAt = trim(parsedRemoteResponse.submitted_at & "") />
        </cfif>
    </cfif>
    <cfset isProcessSendAsync = len(remoteTaskId) AND (isHttp202Accepted OR isSuccess) />

    <cfif isProcessSendAsync>
        <cfset asyncJobStatus = len(remoteSubmitStatus) ? remoteSubmitStatus : "queued" />
        <!--- Store exact process_and_send_data response body when present --->
        <cfset processSendResponseJson = len(responseBody) ? responseBody : serializeJSON({
            "task_id": remoteTaskId,
            "status": asyncJobStatus,
            "submitted_at": remoteSubmittedAt,
            "poll_url": remotePollUrl
        }) />
        <cftry>
            <cfquery name="saveVertexProcessSendResponse" datasource="#Application.DataSrc#">
                UPDATE #Request.prefix_db_agency#.vertex_jobs
                SET task_id = <cfqueryparam value="#remoteTaskId#" cfsqltype="cf_sql_varchar">,
                    job_status = <cfqueryparam value="#asyncJobStatus#" cfsqltype="cf_sql_varchar">,
                    poll_url = <cfqueryparam value="#remotePollUrl#" cfsqltype="cf_sql_varchar" null="#NOT len(remotePollUrl)#">,
                    submitted_at = <cfqueryparam value="#remoteSubmittedAt#" cfsqltype="cf_sql_varchar" null="#NOT len(remoteSubmittedAt)#">,
                    raw_response = <cfqueryparam value="#processSendResponseJson#" cfsqltype="cf_sql_longvarchar">,
                    status_response = <cfqueryparam value="#processSendResponseJson#" cfsqltype="cf_sql_longvarchar">,
                    result_json = <cfqueryparam value="#processSendResponseJson#" cfsqltype="cf_sql_longvarchar">,
                    error_message = <cfqueryparam cfsqltype="cf_sql_longvarchar" null="yes">,
                    Last_Checked = NOW()
                WHERE ID = <cfqueryparam value="#vtxJobRowId#" cfsqltype="cf_sql_bigint">
            </cfquery>
            <cfcatch type="any">
                <!--- poll_url / submitted_at columns may not exist on older schemas --->
                <cfquery name="saveVertexProcessSendResponseLegacy" datasource="#Application.DataSrc#">
                    UPDATE #Request.prefix_db_agency#.vertex_jobs
                    SET task_id = <cfqueryparam value="#remoteTaskId#" cfsqltype="cf_sql_varchar">,
                        job_status = <cfqueryparam value="#asyncJobStatus#" cfsqltype="cf_sql_varchar">,
                        raw_response = <cfqueryparam value="#processSendResponseJson#" cfsqltype="cf_sql_longvarchar">,
                        status_response = <cfqueryparam value="#processSendResponseJson#" cfsqltype="cf_sql_longvarchar">,
                        result_json = <cfqueryparam value="#processSendResponseJson#" cfsqltype="cf_sql_longvarchar">,
                        error_message = <cfqueryparam cfsqltype="cf_sql_longvarchar" null="yes">,
                        Last_Checked = NOW()
                    WHERE ID = <cfqueryparam value="#vtxJobRowId#" cfsqltype="cf_sql_bigint">
                </cfquery>
            </cfcatch>
        </cftry>
        <cfset responseStruct.success = true />
        <cfif isHttp202Accepted>
            <cfset responseStruct.message = "Vertex API call returned status 202 Accepted. Job queued — use Get Status to poll until complete." />
        <cfelse>
            <cfset responseStruct.message = "Vertex API job queued. Use task_id or Get Status to poll until complete." />
        </cfif>
        <cfset responseStruct.data = {
            "task_id": remoteTaskId,
            "status": asyncJobStatus,
            "submitted_at": remoteSubmittedAt,
            "poll_url": remotePollUrl,
            "vertex_job_row_id": vtxJobRowId,
            "job_status": asyncJobStatus,
            "job_in_progress": true,
            "statusCode": httpStatus,
            "s3_url": s3Url,
            "vertexResponse": parsedRemoteResponse,
            "rawResponse": processSendResponseJson,
            "async": true
        } />
        <cfexit />
    </cfif>

    <!--- Check for SSL certificate errors in the response --->
    <cfset sslErrorDetected = false>
    <cfset sslErrorMessage = "">
    <cfif NOT isSuccess AND structKeyExists(parsedRemoteResponse, "detail")>
        <cfset detailText = isSimpleValue(parsedRemoteResponse.detail) ? parsedRemoteResponse.detail : serializeJSON(parsedRemoteResponse.detail)>
        <cfif findNoCase("SSL", detailText) OR findNoCase("CERTIFICATE_VERIFY_FAILED", detailText) OR findNoCase("certificate verify failed", detailText)>
            <cfset sslErrorDetected = true>
            <cfset sslErrorMessage = "SSL Certificate Verification Error: The Vertex API service cannot verify the SSL certificate when calling back to the server. This is a server configuration issue that needs to be fixed by the infrastructure team. The SSL certificate chain may be incomplete or the certificate authority may not be trusted by the Vertex API service.">
        </cfif>
    </cfif>
    
    <cfif sslErrorDetected>
        <cfset responseStruct.message = sslErrorMessage>
    <cfelseif isHttp202Accepted AND len(remoteTaskId)>
        <!--- 202 + task body but async block missed — still treat as queued --->
        <cfset responseStruct.success = true />
        <cfset responseStruct.message = "Vertex API call returned status 202 Accepted. Job queued — use Get Status to poll until complete." />
    <cfelseif isHttp202Accepted>
        <cfset responseStruct.message = "Vertex API call returned status 202 Accepted.">
    <cfelse>
        <cfset responseStruct.message = isSuccess ? "Vertex API call completed successfully." : "Vertex API call returned status " & httpStatus & ".">
    </cfif>
    
    <cfset responseStruct.data = {
        "statusCode": httpStatus,
        "s3_url": s3Url,
        "vertexResponse": parsedRemoteResponse,
        "rawResponse": responseBody,
        "token_status": tokenStatusCode,
        "token_type": accessTokenType,
        "sslError": sslErrorDetected
    }>
    
    <!--- Declare helper function once before including other files --->
    <cfscript>
        function getPlaceholderValue(value) {
            if (isDefined("arguments.value") && len(trim(arguments.value)) > 0) {
                return trim(arguments.value);
            } else {
                return "PLACEHOLDER";
            }
        }
    </cfscript>
    
    <!--- Set flag to indicate function is already declared --->
    <cfset request.getPlaceholderValue_declared = true />
    
    <!--- If Vertex API call was successful, sync medications and problems from AI table --->
    <cfif isSuccess AND patientIdVal GT 0>
        <cftry>
            <!--- Set patient ID for medication sync --->
            <cfset request.med_sync_patient_id = patientIdVal />
            <cfset request.med_sync_employee_id = employeeIdVal />
            
            <!--- Include medication sync --->
            <cfinclude template="sync_ai_medications.cfm" />
            
            <!--- Add medication sync result to response --->
            <cfif structKeyExists(request, "med_sync_result")>
                <cfset responseStruct.data.medicationSync = request.med_sync_result />
                <cfif request.med_sync_result.success AND (request.med_sync_result.synced_count GT 0 OR request.med_sync_result.skipped_count GT 0)>
                    <cfset responseStruct.message = responseStruct.message & " " & request.med_sync_result.message />
                </cfif>
            </cfif>
            <cfcatch type="any">
                <!--- Send error email for medication sync failure --->
                <cftry>
                    <cfmail to="velmurugan@myhomecarebiz.com"
                            from="error@myhomecarebiz.com"
                            subject="Medication Sync Failed in call_vertex_api.cfm - Exception Error"
                            type="html">
                        <h3 style="color: red;">Medication Sync Failed in call_vertex_api.cfm</h3>
                        <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                        <p><strong>Agency ID:</strong> #session.AgencyID#</p>
                        <p><strong>Patient ID:</strong> #patientIdVal#</p>
                        <p><strong>Employee ID:</strong> #employeeIdVal#</p>
                        <p><strong>File ID:</strong> #fileId#</p>
                        <p><strong>Dup File Name:</strong> #dupFileName#</p>
                        <hr>
                        <h4>Exception 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(left(cfcatch.detail, 1000))#</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>
                        <cfif structKeyExists(cfcatch, "TagContext") AND arrayLen(cfcatch.TagContext) GT 0>
                            <hr>
                            <h4>Error Location:</h4>
                            <p><strong>File:</strong> #htmlEditFormat(cfcatch.TagContext[1].template)#</p>
                            <p><strong>Line:</strong> #cfcatch.TagContext[1].line#</p>
                        </cfif>
                        <hr>
                        <h4>Request Variables Set:</h4>
                        <p><strong>request.med_sync_patient_id:</strong> <cfif structKeyExists(request, "med_sync_patient_id")>#request.med_sync_patient_id#<cfelse><span style="color: red;">NOT SET</span></cfif></p>
                        <p><strong>request.med_sync_employee_id:</strong> <cfif structKeyExists(request, "med_sync_employee_id")>#request.med_sync_employee_id#<cfelse><span style="color: red;">NOT SET</span></cfif></p>
                        <hr>
                        <h4>Vertex API Response:</h4>
                        <p><strong>Vertex API Status:</strong> #httpStatus#</p>
                        <p><strong>S3 URL:</strong> #s3Url#</p>
                        <cfif len(responseBody)>
                            <p><strong>Vertex Response Body:</strong></p>
                            <pre style="background-color: ##f5f5f5; padding: 10px; border: 1px solid ##ddd; overflow-x: auto; font-size: 11px;">#htmlEditFormat(left(responseBody, 2000))#</pre>
                        </cfif>
                        <hr>
                        <p style="color: ##666; font-size: 12px; margin-top: 20px;">
                            <strong>Note:</strong> This error occurred when trying to include sync_ai_medications.cfm. The Vertex API call was successful but medication sync failed. The main request will continue without medication sync.
                        </p>
                    </cfmail>
                    <cfcatch type="any">
                        <!--- Silently fail if email fails --->
                    </cfcatch>
                </cftry>
                
                <!--- Medication sync failed, but don't fail the entire request --->
                <cfset responseStruct.data.medicationSync = {
                    success: false,
                    message: "Medication sync failed: #cfcatch.message#",
                    synced_count: 0,
                    skipped_count: 0,
                    duplicate_count: 0,
                    errors: [cfcatch.message]
                } />
            </cfcatch>
        </cftry>
        
        <!--- Sync problems if assessment ID is available --->
        <cfif len(resolvedAssessmentId) AND val(resolvedAssessmentId) GT 0>
            <cftry>
                <!--- Set patient ID and assessment ID for problems sync --->
                <cfset request.problems_sync_patient_id = patientIdVal />
                <cfset request.problems_sync_assmt_id = val(resolvedAssessmentId) />
                <cfset request.problems_sync_employee_id = employeeIdVal />
                
                <!--- Include problems sync --->
                <cfinclude template="sync_problems_action.cfm" />
                
                <!--- Add problems sync result to response --->
                <cfif structKeyExists(request, "problems_sync_result")>
                    <cfset responseStruct.data.problemsSync = request.problems_sync_result />
                    <!--- Show message if sync succeeded OR if it was aborted due to approved problems --->
                    <cfif (request.problems_sync_result.success AND request.problems_sync_result.synced_count GT 0) 
                          OR (NOT request.problems_sync_result.success AND structKeyExists(request.problems_sync_result, "skipped_reason") AND request.problems_sync_result.skipped_reason EQ "approved_problems_exist")>
                        <cfset responseStruct.message = responseStruct.message & " " & request.problems_sync_result.message />
                        <!--- If sync was aborted, also set main response success to false to indicate error --->
                        <cfif NOT request.problems_sync_result.success>
                            <cfset responseStruct.success = false />
                        </cfif>
                    </cfif>
                </cfif>
                <cfcatch type="any">
                    <!--- Send error email when problems sync fails --->
                    <cftry>
                        <cfmail to="velmurugan@myhomecarebiz.com"
                                from="error@myhomecarebiz.com"
                                subject="Problems Sync Failed - Exception Error"
                                type="html">
                            <h3 style="color: red;">Problems Sync Failed - Exception Error</h3>
                            <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                            <p><strong>Agency ID:</strong> #session.AgencyID#</p>
                            <p><strong>Patient ID:</strong> #patientIdVal#</p>
                            <p><strong>Assessment ID:</strong> #resolvedAssessmentId#</p>
                            <p><strong>Employee ID:</strong> #employeeIdVal#</p>
                            <hr>
                            <h4>Exception 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(left(cfcatch.detail, 1000))#</p>
                            <cfif structKeyExists(cfcatch, "stackTrace")>
                                <p><strong>Stack Trace:</strong></p>
                                <pre style="background-color: ##f5f5f5; padding: 10px; border: 1px solid ##ddd; overflow-x: auto; font-size: 11px;">#htmlEditFormat(left(cfcatch.stackTrace, 2000))#</pre>
                            </cfif>
                            <cfif structKeyExists(cfcatch, "TagContext") AND arrayLen(cfcatch.TagContext) GT 0>
                                <p><strong>File:</strong> #htmlEditFormat(cfcatch.TagContext[1].template)#</p>
                                <p><strong>Line:</strong> #cfcatch.TagContext[1].line#</p>
                            </cfif>
                            <hr>
                            <h4>Request Variables Set:</h4>
                            <p><strong>request.problems_sync_patient_id:</strong> <cfif structKeyExists(request, "problems_sync_patient_id")>#request.problems_sync_patient_id#<cfelse><span style="color: red;">NOT SET</span></cfif></p>
                            <p><strong>request.problems_sync_assmt_id:</strong> <cfif structKeyExists(request, "problems_sync_assmt_id")>#request.problems_sync_assmt_id#<cfelse><span style="color: red;">NOT SET</span></cfif></p>
                            <p><strong>request.problems_sync_employee_id:</strong> <cfif structKeyExists(request, "problems_sync_employee_id")>#request.problems_sync_employee_id#<cfelse><span style="color: red;">NOT SET</span></cfif></p>
                            <hr>
                            <p style="color: ##666; font-size: 12px; margin-top: 20px;">
                                <strong>Note:</strong> This error occurred when trying to include sync_problems_action.cfm. The sync process failed but the main request will continue.
                            </p>
                        </cfmail>
                        <cfcatch type="any">
                            <!--- Silently fail if email fails --->
                        </cfcatch>
                    </cftry>
                    
                    <!--- Problems sync failed, but don't fail the entire request --->
                    <cfset responseStruct.data.problemsSync = {
                        success: false,
                        message: "Problems sync failed: #cfcatch.message#",
                        synced_count: 0,
                        error_count: 0,
                        errors: [cfcatch.message]
                    } />
                </cfcatch>
            </cftry>
        <cfelse>
            <!--- Assessment ID not available - send diagnostic email --->
            <cftry>
                <cfmail to="velmurugan@myhomecarebiz.com"
                        from="error@myhomecarebiz.com"
                        subject="Problems Sync Blocked - Assessment ID Missing"
                        type="html">
                    <h3 style="color: orange;">Problems Sync Blocked - Assessment ID Missing</h3>
                    <p><strong>Timestamp:</strong> #DateFormat(Now(), 'mm/dd/yyyy')# #TimeFormat(Now(), 'HH:mm:ss')#</p>
                    <p><strong>Agency ID:</strong> #session.AgencyID#</p>
                    <p><strong>Patient ID:</strong> #patientIdVal#</p>
                    <p><strong>Employee ID:</strong> #employeeIdVal#</p>
                    <hr>
                    <h4>Assessment ID Resolution:</h4>
                    <p><strong>Original Assessment ID from file:</strong> #assessmentId#</p>
                    <p><strong>Resolved Assessment ID:</strong> #resolvedAssessmentId#</p>
                    <p><strong>Resolved Assessment ID (numeric):</strong> #val(resolvedAssessmentId)#</p>
                    <hr>
                    <h4>Why Sync Was Blocked:</h4>
                    <p>The sync_problems_action.cfm was NOT called because:</p>
                    <ul>
                        <li><strong>Condition 1:</strong> len(resolvedAssessmentId) = <strong>#len(resolvedAssessmentId)#</strong> <cfif len(resolvedAssessmentId) EQ 0><span style="color: red;">❌ FAILED</span><cfelse><span style="color: green;">✓ PASSED</span></cfif></li>
                        <li><strong>Condition 2:</strong> val(resolvedAssessmentId) GT 0 = <strong>#val(resolvedAssessmentId) GT 0#</strong> <cfif val(resolvedAssessmentId) GT 0><span style="color: green;">✓ PASSED</span><cfelse><span style="color: red;">❌ FAILED</span></cfif></li>
                    </ul>
                    <hr>
                    <h4>Other Conditions Check:</h4>
                    <p><strong>isSuccess:</strong> #isSuccess# <cfif isSuccess><span style="color: green;">✓ PASSED</span><cfelse><span style="color: red;">❌ FAILED</span></cfif></p>
                    <p><strong>patientIdVal GT 0:</strong> #patientIdVal GT 0# <cfif patientIdVal GT 0><span style="color: green;">✓ PASSED</span><cfelse><span style="color: red;">❌ FAILED</span></cfif></p>
                    <hr>
                    <p style="color: ##666; font-size: 12px; margin-top: 20px;">
                        <strong>Note:</strong> Problems sync requires a valid Assessment ID. Please ensure the file has an Assessment ID or that a valid assessment exists for this patient.
                    </p>
                </cfmail>
                <cfcatch type="any">
                    <!--- Silently fail if email fails --->
                </cfcatch>
            </cftry>
        </cfif>

        <!--- Mark file processed only after synchronous (200) Vertex completion and chart sync attempts --->
        <cfif fileId GT 0>
            <cftry>
                <cfquery name="getCurrentNotesSyncComplete" datasource="#Application.DataSrc#">
                    SELECT Notes FROM #table_files#
                    WHERE id = <cfqueryparam value="#fileId#" cfsqltype="cf_sql_integer">
                    AND AgencyId = <cfqueryparam value="#session.AgencyID#" cfsqltype="cf_sql_integer">
                    AND Status = 0 LIMIT 1
                </cfquery>
                <cfif getCurrentNotesSyncComplete.recordcount GT 0>
                    <cfset existingNotesSyncComplete = trim(getCurrentNotesSyncComplete.Notes)>
                    <cfif NOT findNoCase("Vertex API Processed", existingNotesSyncComplete)>
                        <cfset vertexProcessedNoteSync = "[Vertex API Processed - #dateTimeFormat(now(), 'mm/dd/yyyy hh:nn:ss tt')#]" />
                        <cfset updatedNotesSyncComplete = len(existingNotesSyncComplete) ? existingNotesSyncComplete & " | " & vertexProcessedNoteSync : vertexProcessedNoteSync />
                        <cfquery name="markFileProcessedSyncComplete" datasource="#Application.DataSrc#">
                            UPDATE #table_files# SET Notes = <cfqueryparam value="#updatedNotesSyncComplete#" cfsqltype="cf_sql_varchar">
                            WHERE id = <cfqueryparam value="#fileId#" cfsqltype="cf_sql_integer">
                            AND AgencyId = <cfqueryparam value="#session.AgencyID#" cfsqltype="cf_sql_integer">
                        </cfquery>
                    </cfif>
                </cfif>
                <cfcatch type="any"></cfcatch>
            </cftry>
        </cfif>
    </cfif>
    
  

    <cfif NOT isSuccess AND NOT isHttp202Accepted>
        <cfset statusCode = 502>
        <cfset emailSubject = "Vertex API call returned error status for Agency #session.AgencyID#">
        <cfif sslErrorDetected>
            <cfset emailSubject = "⚠️ SSL CERTIFICATE ERROR - Vertex API call failed for Agency #session.AgencyID#">
        </cfif>
        <cfmail to="velmurugan@myhomecarebiz.com"
                from="error@myhomecarebiz.com"
                subject="#emailSubject#"
                type="html">
            <h3 style="color:red;">Vertex API call returned status #httpStatus#</h3>
            <cfif sslErrorDetected>
                <div style="background-color: ##fff3cd; border: 2px solid ##ffc107; padding: 15px; margin: 15px 0; border-radius: 5px;">
                    <h4 style="color: ##856404; margin-top: 0;">🔒 SSL CERTIFICATE VERIFICATION ERROR DETECTED</h4>
                    <p style="color: ##856404; font-weight: bold;">The Vertex API service cannot verify the SSL certificate when calling back to #application.secure#</p>
                    <p><strong>Root Cause:</strong> The Vertex API (Python service) is trying to make an HTTPS request to:<br>
                    <code>https://#websiteName#/components/API/bulk_import_ai.cfc?method=importPatientData</code></p>
                    <p><strong>Error:</strong> <code>CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate</code></p>
                    <p><strong>Callback URL Used:</strong> <code>https://#websiteName#/components/API/bulk_import_ai.cfc?method=importPatientData</code></p>
                    <hr style="border-color: ##ffc107;">
                    <h5 style="color: ##856404;">Temporary Workaround (Application Configuration):</h5>
                    <p style="color: ##856404;">You can set <code>Application.vertexCallbackURL</code> in Application.cfm to use a different hostname with a valid SSL certificate. For example:</p>
                    <pre style="background-color: ##f5f5f5; padding: 10px; border: 1px solid ##ddd; color: ##856404;"><cfset Application.vertexCallbackURL = "secure.myhomecarebiz.com"></pre>
                    <p style="color: ##856404;"><strong>Note:</strong> This is a temporary workaround. The proper fix is to resolve the SSL certificate issue.</p>
                    <hr style="border-color: ##ffc107;">
                    <h5 style="color: ##856404;">Required Actions (Infrastructure Team - Permanent Fix):</h5>
                    <ol style="color: ##856404;">
                        <li>Ensure the full SSL certificate chain is installed on #application.secure#</li>
                        <li>Verify the certificate includes all intermediate certificates (not just the end-entity certificate)</li>
                        <li>Check that the certificate authority (CA) is trusted by the Vertex API service (Python service at int-extractaiapi.myhomecarebiz.com)</li>
                        <li>If using a self-signed or internal CA certificate, the Vertex API service may need to be configured to trust it</li>
                        <li>Alternatively, the Vertex API service configuration may need to be updated to include the CA certificate bundle</li>
                        <li>Test SSL certificate verification from the Vertex API server: <code>openssl s_client -connect stagesecure.myhomecarebiz.com:443 -showcerts</code></li>
                    </ol>
                </div>
            </cfif>
            <p><strong>Agency ID:</strong> #session.AgencyID#</p>
            <p><strong>Employee ID:</strong> #employeeId#</p>
            <p><strong>Patient ID:</strong> #patientId#</p>
            <p><strong>File ID:</strong> #fileId#</p>
            <p><strong>Dup File Name:</strong> #dupFileName#</p>
            <p><strong>S3 URL:</strong> #s3Url#</p>
            <p><strong>Token Status:</strong> #tokenStatusCode#</p>
            <p><strong>Token URL:</strong> #tokenURL#</p>
            <p><strong>Token Request Body:</strong></p>
            <pre>#encodeForHTML(tokenRequestBody)#</pre>
            <p><strong>Token Type:</strong> #accessTokenType#</p>
            <p><strong>Token Response:</strong></p>
            <pre>#encodeForHTML(tokenResponseBody)#</pre>
            <p><strong>Request Body:</strong></p>
            <pre>#encodeForHTML(serializeJSON(payload))#</pre>
            <p><strong>Response Body:</strong></p>
            <pre>#encodeForHTML(responseBody)#</pre>
        </cfmail>
    </cfif>

<cfset vertexFinalJobStatus = isSuccess ? "completed" : (isHttp202Accepted AND len(remoteTaskId) ? "queued" : "failed") />
<cfif isHttp202Accepted AND len(remoteTaskId) AND NOT isProcessSendAsync>
    <!--- Late save when 202 + task_id was not handled in async block --->
    <cfset processSendResponseJsonLate = len(responseBody) ? responseBody : serializeJSON(parsedRemoteResponse) />
    <cftry>
        <cfquery name="saveVertex202Late" datasource="#Application.DataSrc#">
            UPDATE #Request.prefix_db_agency#.vertex_jobs
            SET task_id = <cfqueryparam value="#remoteTaskId#" cfsqltype="cf_sql_varchar">,
                job_status = <cfqueryparam value="#(len(remoteSubmitStatus) ? remoteSubmitStatus : 'queued')#" cfsqltype="cf_sql_varchar">,
                raw_response = <cfqueryparam value="#processSendResponseJsonLate#" cfsqltype="cf_sql_longvarchar">,
                status_response = <cfqueryparam value="#processSendResponseJsonLate#" cfsqltype="cf_sql_longvarchar">,
                result_json = <cfqueryparam value="#processSendResponseJsonLate#" cfsqltype="cf_sql_longvarchar">,
                error_message = <cfqueryparam cfsqltype="cf_sql_longvarchar" null="yes">,
                Last_Checked = NOW()
            WHERE ID = <cfqueryparam value="#vtxJobRowId#" cfsqltype="cf_sql_bigint">
        </cfquery>
        <cfcatch type="any"></cfcatch>
    </cftry>
</cfif>
<!--- Async 202 + task_id already saved in saveVertexProcessSendResponse; do not overwrite with failed/completed --->
<cfif NOT (isHttp202Accepted AND len(remoteTaskId))>
<cfquery name="saveVertexJobResult" datasource="#Application.DataSrc#">
    UPDATE #Request.prefix_db_agency#.vertex_jobs
    SET job_status = <cfqueryparam value="#vertexFinalJobStatus#" cfsqltype="cf_sql_varchar">,
        error_message = <cfqueryparam value="#(NOT isSuccess AND NOT isHttp202Accepted ? responseStruct.message : '')#" cfsqltype="cf_sql_longvarchar" null="#(isSuccess OR isHttp202Accepted)#">,
        result_json = <cfqueryparam value="#serializeJSON(responseStruct)#" cfsqltype="cf_sql_longvarchar">,
        raw_response = <cfqueryparam value="#responseBody#" cfsqltype="cf_sql_longvarchar">,
        status_response = <cfqueryparam value="#responseBody#" cfsqltype="cf_sql_longvarchar">,
        Last_Checked = NOW()
    WHERE ID = <cfqueryparam value="#vtxJobRowId#" cfsqltype="cf_sql_bigint">
</cfquery>
</cfif>
