<cfcomponent displayname="OASIS AI API" hint="REST API for OASIS questions and answers" 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 datasource name (fallback if Application scope not available) --->
    <cfif not isDefined("Application.DataSrc")>
        <cfset Application.DataSrc = "hhapowerpath" />
    </cfif>

    <!--- Ensure lookup prefix is available --->
    <cfif not isDefined("Request.prefix_db_lookup") OR NOT len(trim(Request.prefix_db_lookup))>
        <cfset Request.prefix_db_lookup = "hhapowerpath" />
    </cfif>

    <!--- 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>

    <!--- Validate appkey using Agency_ID + Patient_ID pattern --->
    <cffunction name="validateBasicAuth" access="private" returntype="struct" hint="Validate appkey authentication">
        <cfargument name="appkey" required="yes" hint="appkey">
        <cfargument name="agency_id" required="no" default="0" hint="Agency ID">
        <cfargument name="emp_id" required="no" default="0" hint="Employee ID">
        <cfargument name="patient_id" required="no" default="0" hint="Patient ID">

        <cfset var result = {
            "valid": false,
            "message": "Authentication required"
        } />

        <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 arguments.appkey EQ expectedKey>
                <cfheader statuscode="200" statustext="success">
                <cfset result.valid = true />
                <cfset result.message = "Authentication successful" />
            <cfelse>
                <cfheader statuscode="401" statustext="Unauthorized">
                <cfset result.message = "Invalid username or password" />
            </cfif>

            <cfcatch type="any">
                <cfheader statuscode="500" statustext="Internal Server Error">
                <cfset result.valid = false />
                <cfset result.message = "Authentication error: " & cfcatch.message />
            </cfcatch>
        </cftry>

        <cfreturn result />
    </cffunction>

    <!--- Get all OASIS questions + answers by assessment_reason (no new_wizard) --->
    <cffunction name="getOasisQuestionsAnswers" access="remote" httpmethod="GET" returnformat="JSON" hint="Return all OASIS questions and answers by assessment_reason">
        <cfargument name="Agency_ID" required="yes" hint="Agency ID">
        <cfargument name="appkey" required="yes" hint="appkey">
        <cfargument name="Patient_ID" required="yes" hint="Patient ID">
        <cfargument name="Emp_ID" required="no" default="0" hint="Employee ID (optional)">
        <cfargument name="assessment_reason" required="yes" hint="Assessment Reason">
        <cfargument name="OASIS_type" required="no" default="" hint="OASIS Type">

        <cfset var response = {} />
        <cfset var questionList = [] />
        <cfset var questionMap = {} />
        <cfset var questionKey = "" />
        <cfset var answerItem = {} />
        <cfset var questionItem = {} />
        <cfset var decryptedAgencyID = maybeDecrypt(arguments.Agency_ID, true) />
        <cfset var decryptedEmpID = maybeDecrypt(arguments.Emp_ID, true) />
        <cfset var decryptedPatientID = maybeDecrypt(arguments.Patient_ID, true) />
        <cfset var decryptedAppKey = maybeDecrypt(arguments.appkey) />

        <cftry>
            <!--- Normalize decrypted values --->
            <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 len(trim(decryptedAppKey))>
                <cfset arguments.appkey = decryptedAppKey />
            </cfif>

            <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_reason = trim(arguments.assessment_reason) />

            <!--- Validate auth --->
            <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>

            <!--- Query follows assessments.cfc get_all_questions logic, without new_wizard filter --->
            <cfquery name="get_all_questions" datasource="#Application.DataSrc#">
                SELECT
                    ques.ques_id,
                    ques.title_2,
                    ques.questions_type,
                    ques.new_order_id,
                    ques.ques_identifier_2,
                    ques.answer_label,
                    ques.assessment_reason,
                    answ.ans_id,
                    answ.question_id,
                    CASE
                        WHEN LEFT(ques.assessment_reason,1) = '1' AND TRIM(IFNULL(ques.questions_2,'')) <> '' THEN ques.questions_2
                        ELSE ques.questions
                    END AS question_display,
                    CASE
                        WHEN LEFT(ques.assessment_reason,1) = '1' AND TRIM(IFNULL(ques.questions_2,'')) <> '' THEN 1
                        ELSE 0
                    END AS show_question_hover,
                    CASE
                        WHEN LEFT(ques.assessment_reason,1) = '1' 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
                <cfif LEFT(arguments.OASIS_type,1) EQ 1>
                    AND ((ques.answer_label = 'F26' AND LEFT(answ.answer,1) = '1') OR ques.answer_label != 'F26')
                </cfif>
                AND ques.new_wizard != 0
                ORDER BY ques.new_wizard, ques.new_order_id, answ.srt_id, ques.answer_label ASC
            </cfquery>

            <!--- Format JSON as questions with nested answers --->
            <cfloop query="get_all_questions">
                <cfset questionKey = toString(get_all_questions.ques_id) />

                <cfif NOT structKeyExists(questionMap, questionKey)>
                    <cfset questionItem = {
                        "ques_id": get_all_questions.ques_id,
                        "question_display": get_all_questions.question_display,
                        "title_2": get_all_questions.title_2,
                        "questions_type": get_all_questions.questions_type,
                        "new_order_id": get_all_questions.new_order_id,
                        "ques_identifier_2": get_all_questions.ques_identifier_2,
                        "answer_label": get_all_questions.answer_label,
                        "assessment_reason": get_all_questions.assessment_reason,
                        "answers": []
                    } />
                    <cfset arrayAppend(questionList, questionItem) />
                    <cfset questionMap[questionKey] = arrayLen(questionList) />
                </cfif>

                <cfset answerItem = {
                    "answer_display": get_all_questions.answer_display,
                    "ans_id": get_all_questions.ans_id,
                    "question_id": get_all_questions.question_id
                } />

                <cfset arrayAppend(questionList[questionMap[questionKey]].answers, answerItem) />
            </cfloop>

            <cfset response = {
                "success": true,
                "message": "Questions and answers fetched successfully",
                "assessment_reason": arguments.assessment_reason,
                "total_questions": arrayLen(questionList),
                "total_records": get_all_questions.recordcount,
                "data": questionList
            } />

            <cfcatch type="any">
                <cfset response = {
                    "success": false,
                    "message": "Failed to fetch questions and answers",
                    "error": cfcatch.message,
                    "detail": cfcatch.detail,
                    "data": []
                } />
            </cfcatch>
        </cftry>

        <cfreturn serializeJSON(response) />
    </cffunction>

</cfcomponent>
