<cfcomponent displayname="SOC Wizard Functions" hint="I return SOC wizard-specific questions and rules" output="false">

    <cffunction name="init" displayname="Initialize Component" access="public" returntype="any" hint="I initialize and return the SOC wizard object.">
        <cfreturn this>
    </cffunction>

    <!--- Visit_Type / short OASIS code → assessment_questions_lookup.assessment_reason (pass through if already full reason) --->
    <cffunction name="mapOasisTypeCodeToWizardAssessmentReason" access="public" returntype="string" output="false">
        <cfargument name="oasisTypeCode" type="string" required="true" />
        <cfset var c = Trim(arguments.oasisTypeCode) />
        <cfset var fullReasons = "1 - Start of care - further visits planned|1 - Start of care - further visits planned - Physical Therapy|1 - Start of care - further visits planned - Occupational Therapy|3 - Resumption of care (after inpatient stay)|PT Adult Evaluation|OT Adult Evaluation|ST Adult Evaluation|SN Adult Evaluation|MSW Evaluation|PT Followup|OT Followup|ST Followup|MSW Followup|SN Followup|Hospice Comprehensive|SN Hospice|Chaplain Comprehensive Evaluation|Hospice Discharge|Hospice admission|4 - Recertification (follow-up) reassessment|4 - Recertification (follow-up) reassessment - PT|4 - Recertification (follow-up) reassessment - OT|4 - Resumption/Recertification|5 - Other follow-up|6 - Transferred to an inpatient facility - patient not discharged from agency|7 - Transferred to an inpatient facility - patient discharged from agency|8 - Death at home|9 - Discharge from agency" />

        <cfif NOT Len(c) OR LCase(c) EQ "null">
            <cfreturn "1 - Start of care - further visits planned" />
        </cfif>
        <cfif ListFind(fullReasons, c, "|") GT 0>
            <cfreturn c />
        </cfif>
        <cfswitch expression="#c#">
            <cfcase value="1 - SOC - SN"><cfreturn "1 - Start of care - further visits planned" /></cfcase>
            <cfcase value="1 - SOC - PT"><cfreturn "1 - Start of care - further visits planned - Physical Therapy" /></cfcase>
            <cfcase value="1 - SOC - OT"><cfreturn "1 - Start of care - further visits planned - Occupational Therapy" /></cfcase>
            <cfcase value="3 - ROC - SN,3 - ROC - PT"><cfreturn "3 - Resumption of care (after inpatient stay)" /></cfcase>
            <cfcase value="PT Eval"><cfreturn "PT Adult Evaluation" /></cfcase>
            <cfcase value="OT Eval"><cfreturn "OT Adult Evaluation" /></cfcase>
            <cfcase value="ST Eval"><cfreturn "ST Adult Evaluation" /></cfcase>
            <cfcase value="SN Eval"><cfreturn "SN Adult Evaluation" /></cfcase>
            <cfcase value="MSW Eval"><cfreturn "MSW Evaluation" /></cfcase>
            <cfcase value="PT FU Eval"><cfreturn "PT Followup" /></cfcase>
            <cfcase value="OT FU Eval"><cfreturn "OT Followup" /></cfcase>
            <cfcase value="ST FU Eval"><cfreturn "ST Followup" /></cfcase>
            <cfcase value="MSW FU Eval"><cfreturn "MSW Followup" /></cfcase>
            <cfcase value="SN FU Eval"><cfreturn "SN Followup" /></cfcase>
            <cfcase value="Hospice Comprehensive"><cfreturn "Hospice Comprehensive" /></cfcase>
            <cfcase value="SN Hospice"><cfreturn "SN Hospice" /></cfcase>
            <cfcase value="Chaplain Comprehensive Evaluation"><cfreturn "Chaplain Comprehensive Evaluation" /></cfcase>
            <cfcase value="Hospice Discharge"><cfreturn "Hospice Discharge" /></cfcase>
            <cfcase value="Hospice admission"><cfreturn "Hospice admission" /></cfcase>
            <cfcase value="4 - Recertification"><cfreturn "4 - Recertification (follow-up) reassessment" /></cfcase>
            <cfcase value="4 - Recertification PT"><cfreturn "4 - Recertification (follow-up) reassessment - PT" /></cfcase>
            <cfcase value="4 - Recertification OT"><cfreturn "4 - Recertification (follow-up) reassessment - OT" /></cfcase>
            <cfcase value="4 - Resumption/Recertification"><cfreturn "4 - Resumption/Recertification" /></cfcase>
            <cfcase value="5 - Other follow-up"><cfreturn "5 - Other follow-up" /></cfcase>
            <cfcase value="6 - Transfer no discharge"><cfreturn "6 - Transferred to an inpatient facility - patient not discharged from agency" /></cfcase>
            <cfcase value="7 - Transfer discharged"><cfreturn "7 - Transferred to an inpatient facility - patient discharged from agency" /></cfcase>
            <cfcase value="8 - Death"><cfreturn "8 - Death at home" /></cfcase>
            <cfcase value="9 - Discharge from agency"><cfreturn "9 - Discharge from agency" /></cfcase>
            <cfdefaultcase><cfreturn c /></cfdefaultcase>
        </cfswitch>
    </cffunction>

    <cffunction name="get_all_answers_whisper"  access="remote" output="Yes" httpmethod="GET" returnformat="JSON">
			  <cfargument name="assessment_reason" required="yes" hint="assessment_reason"> 
			   <cfargument name="wizard"  default="0" hint="wizard"> 
			   	<cfset resumption = 'no'>  
			    <cfif assessment_reason EQ '3 - Resumption of care (after inpatient stay)'>
			   		<cfset assessment_reason= '1 - Start of care - further visits planned' />
					<cfset resumption = 'yes'>
			   </cfif>  
			  <cfset useNewWizardFilter = (Left(arguments.assessment_reason, 1) EQ "1" AND resumption EQ "no") OR Left(arguments.assessment_reason, 1) EQ "4" OR arguments.assessment_reason EQ "OT Adult Evaluation" OR arguments.assessment_reason EQ "OT Followup" OR arguments.assessment_reason EQ "PT Adult Evaluation" OR arguments.assessment_reason EQ "PT Followup" OR arguments.assessment_reason EQ "SN Adult Evaluation" OR arguments.assessment_reason EQ "MSW Evaluation" />
			  <cfquery name="get_label" datasource="#Application.DataSrc#">    
			          SELECT * FROM  #Request.prefix_db_lookup#.assessment_questions_lookup as ques
                      JOIN #Request.prefix_db_lookup#.assessment_answers_lookup as answ ON answ.question_id  = ques.ques_id 
					  WHERE ques.Deleted = 0  
					  AND  answ.Deleted = 0  
					  <cfif useNewWizardFilter AND arguments.wizard neq 0>
						  AND (ques.new_wizard  = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.wizard#">
						  OR ( ques.new_wizard = 0 AND ques.display IN ('yes','VertexAPI')))
					  <cfelseif arguments.wizard neq 0>
					  	AND  (ques.wizard =  <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.wizard#"> OR ques.wizard =  0)
					  </cfif> 
					  AND  ques.assessment_reason = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.assessment_reason#"> 
					  AND  ques.assessment_reason = answ.assessment_reason
					  ORDER BY ques.order_id ASC
			 </cfquery> 
			 <cfset label_name = '' >
			 <cfset responsekey=[] />
 			 <cfoutput query="get_label" group="answer_label">
				 <cfset impVal = get_label.important />
				 <cfif ListFindNoCase(get_label.columnList, "new_wizard") AND IsNumeric(get_label.new_wizard) AND get_label.new_wizard EQ 0><cfset impVal = 0 /></cfif>
				 <cfif IsDefined("get_label.display") AND get_label.display EQ 'VertexAPI'><cfset impVal = 0 /></cfif>
				 <cfset displayVal = (IsDefined("get_label.display")) ? get_label.display : "" />
				 <cfset obj={"label_name"=#answer_label# ,"answer_type" = #answer_type#,"important" = #impVal#,"questions" = #questions#, "questions_label" = #questions_label#, "other" = #other#,
				 "alert_message" = #alert_message#,"wizard" = #get_label.wizard#,"new_wizard" = #get_label.new_wizard#,"question_id" = #question_id#,"ans_id" = #ans_id#,"display" = displayVal }  />
                  <cfset arrayAppend(responsekey, obj) />
			 </cfoutput>
			 <cfset response={"answer_labels"= #responsekey#} />
			 <cfreturn response />
    	</cffunction>

    <!--- New SOC Process (#10058): get questions by new_wizard block (SN only) --->
    <cffunction name="get_all_ques_ans_new_wizard" access="public" output="true" returntype="query">
        <cfargument name="assessment_reason" required="yes" hint="assessment_reason">
        <cfargument name="new_wizard" required="yes" hint="new_wizard block number">
        <cfargument name="OASIS_type" default="" hint="OASIS Type">
        <cfargument name="view_mode" default="edit" hint="wizard or edit display mode">
        <cfargument name="legacy_wizard" default="0" hint="optional filter by assessment_questions_lookup.wizard (1-4 recert PT tabs)">
        <cfset var _useWizardDisplay = (CompareNoCase(Trim(arguments.view_mode), "wizard") EQ 0) />
        <cfquery name="get_all_questions" datasource="#Application.DataSrc#">
            SELECT
                ques.ques_id,
                answ.question_id AS question_id,
                ques.answer_label,
                ques.questions,
                ques.questions_2,
                ques.questions_label,
                answ.answer_type,
                ques.important,
                ques.other,
                ques.alert_message,
                ques.wizard,
                ques.new_wizard,
                ques.display,
                ques.title,
                ques.title_2,
                ques.quescolor,
                ques.ques_identifier,
                ques.ques_identifier_2,
                ques.text_labels,
                ques.assessment_reason,
                ques.order_id,
                ques.new_order_ID,
                answ.ans_id,
                answ.answer,
                answ.answer_2,
                answ.srt_id,
                answ.tooltip_title,
                CASE
                    WHEN <cfif _useWizardDisplay>1=1<cfelse>1=0</cfif> AND TRIM(IFNULL(ques.questions_2,'')) <> '' THEN ques.questions_2
                    ELSE ques.questions
                END AS question_display,
                CASE
                    WHEN <cfif _useWizardDisplay>1=1<cfelse>1=0</cfif> AND TRIM(IFNULL(ques.questions_2,'')) <> '' THEN 1
                    ELSE 0
                END AS show_question_hover,
                CASE
                    WHEN <cfif _useWizardDisplay>1=1<cfelse>1=0</cfif> THEN ques.title_2
                    ELSE ques.title
                END AS title_display,
                CASE
                    WHEN <cfif _useWizardDisplay>1=1<cfelse>1=0</cfif> AND TRIM(IFNULL(ques.ques_identifier_2,'')) <> '' THEN ques.ques_identifier_2
                    ELSE ques.ques_identifier
                END AS ques_identifier_display,
                CASE
                    WHEN <cfif _useWizardDisplay>1=1<cfelse>1=0</cfif> AND TRIM(IFNULL(answ.answer_2,'')) <> '' THEN answ.answer_2
                    ELSE answ.answer
                END AS answer_display
            FROM  #Request.prefix_db_lookup#.assessment_questions_lookup as ques
            JOIN #Request.prefix_db_lookup#.assessment_answers_lookup as answ ON answ.question_id  = ques.ques_id
            WHERE ques.Deleted = 0
            AND answ.Deleted = 0
            AND ques.assessment_reason = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.assessment_reason#">
            AND ques.assessment_reason = answ.assessment_reason
            AND (ques.new_wizard = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.new_wizard#">
            OR (ques.new_wizard = 0 AND ques.display = <cfqueryparam cfsqltype="cf_sql_varchar" value="yes">))
            <cfif Val(arguments.legacy_wizard) GT 0>
            AND (ques.wizard = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.legacy_wizard#">
            OR ques.wizard = 0)
            </cfif>
            <cfif isSimpleValue(arguments.OASIS_type) AND len(trim(arguments.OASIS_type)) AND LEFT(trim(arguments.OASIS_type),1) EQ "1">
                AND ((ques.answer_label = 'F26' AND LEFT(answ.answer,1) = '1') OR ques.answer_label != 'F26' )
            </cfif>
            ORDER BY
                CASE WHEN UPPER(TRIM(ques.answer_label)) = 'F175' THEN 1 ELSE 0 END,
                IFNULL(NULLIF(ques.new_order_ID, 0), ques.order_id),
                ques.new_wizard,
                answ.question_id,
                answ.srt_id,
                ques.answer_label ASC
        </cfquery>
        <cfreturn get_all_questions />
    </cffunction>

    <!--- Does assessment_tabs have a new_wizard column? (staging adds it; prefer over legacy wizard) --->
    <cffunction name="assessment_tabs_has_new_wizard" access="private" returntype="boolean" output="false">
        <cfset var colCheck = "" />
        <cfif StructKeyExists(variables, "_assessment_tabs_has_new_wizard")>
            <cfreturn variables._assessment_tabs_has_new_wizard />
        </cfif>
        <cftry>
            <cfquery name="colCheck" datasource="#Application.DataSrc#">
                SELECT 1 AS ok
                FROM information_schema.COLUMNS
                WHERE table_schema = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Request.prefix_db_lookup#">
                  AND table_name = <cfqueryparam cfsqltype="cf_sql_varchar" value="assessment_tabs">
                  AND COLUMN_NAME = <cfqueryparam cfsqltype="cf_sql_varchar" value="new_wizard">
                LIMIT 1
            </cfquery>
            <cfset variables._assessment_tabs_has_new_wizard = (colCheck.recordCount GT 0) />
            <cfcatch type="any">
                <cfset variables._assessment_tabs_has_new_wizard = false />
            </cfcatch>
        </cftry>
        <cfreturn variables._assessment_tabs_has_new_wizard />
    </cffunction>

    <!--- Assessment tabs for one assessment_reason: assessment_tabs.new_wizard ↔ questions.new_wizard --->
    <cffunction name="get_assessment_tabs" access="public" output="false" returntype="query">
        <cfargument name="assessment_reason" required="yes" hint="assessment_reason matching assessment_tabs.assessment_reason" />
        <cfset var tabsQ = "" />
        <cfset var useNewWizardCol = assessment_tabs_has_new_wizard() />
        <cftry>
            <cfquery name="tabsQ" datasource="#Application.DataSrc#">
                SELECT assessment_tabs_id,
                       tab_name,
                       status,
                       wizard,
                       <cfif useNewWizardCol>
                         COALESCE(NULLIF(new_wizard, 0), NULLIF(wizard, 0), 0) AS new_wizard
                       <cfelse>
                         wizard AS new_wizard
                       </cfif>
                FROM #Request.prefix_db_lookup#.assessment_tabs
                WHERE status = <cfqueryparam cfsqltype="cf_sql_integer" value="0">
                  AND assessment_reason = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(arguments.assessment_reason)#">
                ORDER BY
                  <cfif useNewWizardCol>
                    COALESCE(NULLIF(new_wizard, 0), NULLIF(wizard, 0), assessment_tabs_id),
                  <cfelse>
                    wizard,
                  </cfif>
                  assessment_tabs_id
            </cfquery>
            <cfcatch type="any">
                <cfset tabsQ = QueryNew("assessment_tabs_id,tab_name,status,wizard,new_wizard") />
            </cfcatch>
        </cftry>
        <cfreturn tabsQ />
    </cffunction>

    <!--- Dynamic wizard layout from assessment_tabs (preferred) or DISTINCT questions.new_wizard (fallback) --->
    <cffunction name="get_assessment_tab_layout" access="public" output="false" returntype="struct">
        <cfargument name="assessment_reason" required="yes" />
        <cfargument name="fallback_block_list" type="string" required="false" default="" hint="Comma list if neither tabs nor questions found" />
        <cfset var layout = {
            block_order = "",
            block_names = StructNew(),
            submit_block = 0,
            vitals_block = 0,
            source = "none",
            tabs_query = QueryNew("assessment_tabs_id,tab_name,status,wizard,new_wizard")
        } />
        <cfset var tabsQ = get_assessment_tabs(arguments.assessment_reason) />
        <cfset var blocksQ = "" />
        <cfset var blk = 0 />
        <cfset var lbl = "" />
        <cfset var seen = StructNew() />
        <cfset var orderArr = [] />
        <cfset var i = 0 />
        <cfset var fb = "" />
        <cfset var submitKey = "" />

        <cfif tabsQ.recordCount GT 0>
            <cfset layout.source = "assessment_tabs" />
            <cfset layout.tabs_query = tabsQ />
            <cfloop query="tabsQ">
                <cfset blk = Int(Val(tabsQ.new_wizard)) />
                <cfif blk LT 1>
                    <cfcontinue />
                </cfif>
                <cfset lbl = Trim(tabsQ.tab_name & "") />
                <cfif NOT StructKeyExists(seen, ToString(blk))>
                    <cfset ArrayAppend(orderArr, blk) />
                    <cfset seen[ToString(blk)] = true />
                </cfif>
                <cfif Len(lbl)>
                    <cfset layout.block_names[ToString(blk)] = lbl />
                </cfif>
                <cfif Len(lbl) AND (
                    FindNoCase("wound", lbl) GT 0 OR
                    FindNoCase("vital", lbl) GT 0 OR
                    FindNoCase("skin", lbl) GT 0
                )>
                    <cfset layout.vitals_block = blk />
                </cfif>
            </cfloop>
        <cfelse>
            <cfset blocksQ = get_new_wizard_blocks_from_questions(arguments.assessment_reason) />
            <cfif blocksQ.recordCount GT 0>
                <cfset layout.source = "questions_lookup" />
                <cfloop query="blocksQ">
                    <cfset blk = Int(Val(blocksQ.new_wizard)) />
                    <cfif blk LT 1 OR StructKeyExists(seen, ToString(blk))>
                        <cfcontinue />
                    </cfif>
                    <cfset ArrayAppend(orderArr, blk) />
                    <cfset seen[ToString(blk)] = true />
                    <cfset layout.block_names[ToString(blk)] = get_new_wizard_tab_label_for_block(arguments.assessment_reason, blk) />
                </cfloop>
            </cfif>
        </cfif>

        <cfif ArrayLen(orderArr) LT 1 AND Len(Trim(arguments.fallback_block_list))>
            <cfset layout.source = "fallback" />
            <cfloop list="#arguments.fallback_block_list#" index="fb">
                <cfset blk = Int(Val(Trim(fb))) />
                <cfif blk GT 0 AND NOT StructKeyExists(seen, ToString(blk))>
                    <cfset ArrayAppend(orderArr, blk) />
                    <cfset seen[ToString(blk)] = true />
                    <cfset layout.block_names[ToString(blk)] = "Tab " & blk />
                </cfif>
            </cfloop>
        </cfif>

        <!--- Stable numeric order when sourced from DISTINCT (tabs already ordered) --->
        <cfif layout.source EQ "questions_lookup" OR layout.source EQ "fallback">
            <cfset ArraySort(orderArr, "numeric", "asc") />
        </cfif>

        <cfset layout.block_order = ArrayToList(orderArr, ",") />
        <cfif ArrayLen(orderArr) GT 0>
            <cfset layout.submit_block = orderArr[ArrayLen(orderArr)] />
            <cfset submitKey = ToString(layout.submit_block) />
            <cfif layout.vitals_block LT 1 AND StructKeyExists(layout.block_names, submitKey) AND (
                FindNoCase("wound", layout.block_names[submitKey]) GT 0 OR
                FindNoCase("vital", layout.block_names[submitKey]) GT 0 OR
                FindNoCase("skin", layout.block_names[submitKey]) GT 0
            )>
                <cfset layout.vitals_block = layout.submit_block />
            </cfif>
        </cfif>
        <cfreturn layout />
    </cffunction>

    <!--- DISTINCT new_wizard blocks from assessment_questions_lookup (fallback when assessment_tabs empty) --->
    <cffunction name="get_new_wizard_blocks_from_questions" access="public" output="false" returntype="query">
        <cfargument name="assessment_reason" required="yes" hint="assessment_reason (e.g. 1 - Start of care - further visits planned for SN)">
        <cfquery name="get_blocks" datasource="#Application.DataSrc#">
            SELECT DISTINCT new_wizard
            FROM #Request.prefix_db_lookup#.assessment_questions_lookup
            WHERE assessment_reason = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.assessment_reason#">
            AND Deleted = 0
            AND new_wizard IS NOT NULL
            AND new_wizard <> 0
            ORDER BY new_wizard
        </cfquery>
        <cfreturn get_blocks />
    </cffunction>

    <!--- Blocks for wizard: prefer assessment_tabs.new_wizard, else questions_lookup.new_wizard --->
    <cffunction name="get_new_wizard_blocks" access="public" output="false" returntype="query">
        <cfargument name="assessment_reason" required="yes" hint="assessment_reason (e.g. 1 - Start of care - further visits planned for SN)">
        <cfset var tabsQ = get_assessment_tabs(arguments.assessment_reason) />
        <cfset var outQ = QueryNew("new_wizard,tab_name") />
        <cfset var blk = 0 />
        <cfset var seen = StructNew() />
        <cfset var blocksQ = "" />
        <cfif tabsQ.recordCount GT 0>
            <cfloop query="tabsQ">
                <cfset blk = Int(Val(tabsQ.new_wizard)) />
                <cfif blk LT 1 OR StructKeyExists(seen, ToString(blk))>
                    <cfcontinue />
                </cfif>
                <cfset seen[ToString(blk)] = true />
                <cfset QueryAddRow(outQ) />
                <cfset QuerySetCell(outQ, "new_wizard", blk) />
                <cfset QuerySetCell(outQ, "tab_name", Trim(tabsQ.tab_name & "")) />
            </cfloop>
            <cfreturn outQ />
        </cfif>
        <cfset blocksQ = get_new_wizard_blocks_from_questions(arguments.assessment_reason) />
        <cfloop query="blocksQ">
            <cfset blk = Int(Val(blocksQ.new_wizard)) />
            <cfif blk LT 1>
                <cfcontinue />
            </cfif>
            <cfset QueryAddRow(outQ) />
            <cfset QuerySetCell(outQ, "new_wizard", blk) />
            <cfset QuerySetCell(outQ, "tab_name", "") />
        </cfloop>
        <cfreturn outQ />
    </cffunction>

    <!--- Tab label: assessment_tabs.tab_name first, else first section title in lookup, else Tab N --->
    <cffunction name="get_new_wizard_tab_label_for_block" access="public" returntype="string" output="false">
        <cfargument name="assessment_reason" type="string" required="true" />
        <cfargument name="new_wizard" type="numeric" required="true" />
        <cfset var q = "" />
        <cfset var lbl = "Tab " & arguments.new_wizard />
        <cfset var rawTitle = "" />
        <cfset var tabsQ = "" />
        <cfif arguments.new_wizard LT 1 OR NOT Len(Trim(arguments.assessment_reason))>
            <cfreturn lbl />
        </cfif>
        <cfset tabsQ = get_assessment_tabs(arguments.assessment_reason) />
        <cfif tabsQ.recordCount GT 0>
            <cfloop query="tabsQ">
                <cfif Int(Val(tabsQ.new_wizard)) EQ Int(Val(arguments.new_wizard)) AND Len(Trim(tabsQ.tab_name & ""))>
                    <cfreturn Trim(tabsQ.tab_name) />
                </cfif>
            </cfloop>
        </cfif>
        <cfset q = get_all_ques_ans_new_wizard(assessment_reason = arguments.assessment_reason, new_wizard = arguments.new_wizard, view_mode = "wizard") />
        <cfif q.recordcount GT 0>
            <cfloop query="q">
                <cfset rawTitle = "" />
                <cfif ListFindNoCase(q.columnList, "title_display") GT 0>
                    <cfset rawTitle = Trim(q.title_display) />
                <cfelseif ListFindNoCase(q.columnList, "title_2") GT 0>
                    <cfset rawTitle = Trim(q.title_2) />
                <cfelseif ListFindNoCase(q.columnList, "title") GT 0>
                    <cfset rawTitle = Trim(q.title) />
                </cfif>
                <cfif Len(rawTitle) GT 0>
                    <cfset lbl = reReplace(rawTitle, "<[^>]*>", "", "all") />
                    <cfset lbl = reReplace(lbl, "&nbsp;", " ", "all") />
                    <cfset lbl = Trim(lbl) />
                    <cfbreak />
                </cfif>
            </cfloop>
        </cfif>
        <cfreturn lbl />
    </cffunction>

    <!--- new_wizard id (string key) -> tab label; safe when titles contain commas --->
    <cffunction name="get_new_wizard_block_names" access="public" returntype="struct" output="false">
        <cfargument name="assessment_reason" type="string" required="true" />
        <cfargument name="block_order_list" type="string" required="true" hint="Comma-separated new_wizard ids in tab order" />
        <cfset var names = StructNew() />
        <cfset var blk = "" />
        <cfset var layout = get_assessment_tab_layout(arguments.assessment_reason) />
        <cfloop list="#arguments.block_order_list#" index="blk">
            <cfset blk = Trim(blk) />
            <cfif NOT Len(blk) OR NOT IsNumeric(blk)><cfcontinue /></cfif>
            <cfif StructKeyExists(layout.block_names, blk) AND Len(Trim(layout.block_names[blk]))>
                <cfset names[blk] = layout.block_names[blk] />
            <cfelse>
                <cfset names[blk] = get_new_wizard_tab_label_for_block(arguments.assessment_reason, Int(Val(blk))) />
            </cfif>
        </cfloop>
        <cfreturn names />
    </cffunction>

    <!--- Question importance rules: when trigger question matches value, set target question(s) important (0/1). Query is based on Assessment_Reason only; not wizard-based. --->
    <cffunction name="get_question_importance_rules" access="public" output="false" returntype="query">
        <cfargument name="assessment_reason" type="string" required="yes" hint="Assessment reason (e.g. 1 - Start of care - further visits planned); rules are filtered by this">
        <cfset var hasValidationCols = false />
        <cftry>
            <cfquery name="colCheck" datasource="#Application.DataSrc#">
                SELECT 1 FROM information_schema.COLUMNS
                WHERE table_schema = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Request.prefix_db_lookup#">
                AND table_name = 'QuestionImportanceRules' AND COLUMN_NAME = 'Rule_Type'
            </cfquery>
            <cfif colCheck.recordCount GT 0><cfset hasValidationCols = true /></cfif>
            <cfcatch type="any"><cfset hasValidationCols = false /></cfcatch>
        </cftry>
        <cfif hasValidationCols>
            <cfquery name="get_rules" datasource="#Application.DataSrc#">
                SELECT Rule_ID, Trigger_Question, Trigger_Quest_ID, Value_Match_Type, Value_Pattern, Target_Questions, Target_Quest_Ids, Action_Value,
                    Rule_Type, Validation_Message, Validation_Condition
                FROM #Request.prefix_db_lookup#.QuestionImportanceRules
                WHERE Status = 0
                AND Assessment_Reason = <cfqueryparam cfsqltype="cf_sql_varchar" value="#trim(arguments.assessment_reason)#">
                ORDER BY Rule_ID
            </cfquery>
        <cfelse>
            <cfquery name="get_rules" datasource="#Application.DataSrc#">
                SELECT Rule_ID, Trigger_Question, Trigger_Quest_ID, Value_Match_Type, Value_Pattern, Target_Questions, Target_Quest_Ids, Action_Value
                FROM #Request.prefix_db_lookup#.QuestionImportanceRules
                WHERE Status = 0
                AND Assessment_Reason = <cfqueryparam cfsqltype="cf_sql_varchar" value="#trim(arguments.assessment_reason)#">
                ORDER BY Rule_ID
            </cfquery>
        </cfif>
        <cfreturn get_rules />
    </cffunction>

</cfcomponent>
