<cfcomponent displayname="Patient Medications AI API" hint="REST API for ptmeds_ai table operations" 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==" />
    
    <!--- Validate Basic Authentication --->
    <cffunction name="validateBasicAuth" access="private" returntype="struct" hint="Validate HTTP Basic Authentication">
        <cfargument name="Agency_ID" required="yes" hint="Agency ID">
        
        <cfset var result = {
            "valid": false,
            "message": "Authentication required",
            "agency_db": "",
            "emp_id": 0
        } />
        
        <cftry>
            <!--- Get Authorization header --->
            <cfset var authHeader = getHttpRequestData().headers />
            
            <cfif not structKeyExists(authHeader, "Authorization") and not structKeyExists(authHeader, "authorization")>
                <cfheader statuscode="401" statustext="Unauthorized">
                <cfheader name="WWW-Authenticate" value="Basic realm=""API Access""">
                <cfset result.message = "Authorization header required" />
                <cfreturn result />
            </cfif>
            
            <!--- Get the authorization value (case insensitive) --->
            <cfset var authValue = "" />
            <cfif structKeyExists(authHeader, "Authorization")>
                <cfset authValue = authHeader.Authorization />
            <cfelse>
                <cfset authValue = authHeader.authorization />
            </cfif>
            
            <!--- Check if it's Basic auth --->
            <cfif not findNoCase("Basic ", authValue)>
                <cfheader statuscode="401" statustext="Unauthorized">
                <cfset result.message = "Basic Authentication required" />
                <cfreturn result />
            </cfif>
            
            <!--- Decode Base64 credentials --->
            <cfset var encodedCredentials = replaceNoCase(authValue, "Basic ", "") />
            <cfset var decodedCredentials = toString(toBinary(encodedCredentials)) />
            
            <!--- Split username and password --->
            <cfif not find(":", decodedCredentials)>
                <cfheader statuscode="401" statustext="Unauthorized">
                <cfset result.message = "Invalid credentials format" />
                <cfreturn result />
            </cfif>
            
            <cfset var username = listFirst(decodedCredentials, ":") />
            <cfset var password = listLast(decodedCredentials, ":") />
            
            <!--- Encrypt password for comparison --->
            <cfset var encryptedPassword = encrypt(password, this.passwordEncryptKey, "AES", "Base64") />
            
            <!--- Validate credentials against database --->
            <cfquery name="validateUser" datasource="#Application.DataSrc#">
                SELECT pEmployee.Emp_ID, pEmployee.Emp_First, pEmployee.Emp_Last, 
                       pEmployee.Loc_ID, Agency.Agency_Login
                FROM hhapowerpath.pEmployee
                JOIN hhapowerpath.Agency ON Agency.Agency_ID = pEmployee.Loc_ID
                WHERE pEmployee.Username = <cfqueryparam value="#username#" cfsqltype="cf_sql_varchar">
                AND pEmployee.Password = <cfqueryparam value="#encryptedPassword#" cfsqltype="cf_sql_varchar">
                AND pEmployee.Emp_Type = 'Employee'
                AND pEmployee.Status = 0
                AND pEmployee.Loc_ID = <cfqueryparam value="#arguments.Agency_ID#" cfsqltype="cf_sql_integer">
            </cfquery>
            
            <cfif validateUser.recordcount eq 0>
                <cfheader statuscode="401" statustext="Unauthorized">
                <cfset result.message = "Invalid username or password" />
                <cfreturn result />
            </cfif>
            
            <!--- Set agency database --->
            <cfset result.agency_db = 'agency_' & arguments.Agency_ID />
            
            <!--- Validate agency database exists --->
            <cfquery name="checkDBExistence" datasource="#Application.DataSrc#">
                SELECT SCHEMA_NAME FROM information_schema.schemata 
                WHERE SCHEMA_NAME = <cfqueryparam value="#result.agency_db#" cfsqltype="cf_sql_varchar">
            </cfquery>
            
            <cfif checkDBExistence.recordcount eq 0>
                <cfset result.message = "Invalid Agency ID - Database does not exist" />
                <cfreturn result />
            </cfif>
            
            <!--- Authentication successful --->
            <cfset result.valid = true />
            <cfset result.message = "Authentication successful" />
            <cfset result.emp_id = validateUser.Emp_ID />
            
            <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>
    
    <!--- Insert single medication record --->
    <cffunction name="insertMedication" access="remote" returnformat="JSON" hint="Insert a single ptmeds_ai record">
        <cfargument name="Agency_ID" required="yes" hint="Agency ID">
        <cfargument name="Patient_ID" required="yes" hint="Patient ID">
        <cfargument name="Drug_Name" required="yes" hint="Drug Name">
        <cfargument name="Drug_ID" required="no" default="0" hint="Drug ID">
        <cfargument name="Status" required="no" default="0" hint="Status">
        <cfargument name="DateOrdered" required="no" default="" hint="Date Ordered">
        <cfargument name="DateDCed" required="no" default="" hint="Date Discontinued">
        <cfargument name="Dose" required="no" default="" hint="Dose">
        <cfargument name="Dose_Units" required="no" default="" hint="Dose Units">
        <cfargument name="Route" required="no" default="" hint="Route">
        <cfargument name="Freq" required="no" default="" hint="Frequency">
        <cfargument name="Notes" required="no" default="" hint="Notes">
        
        <cfset var response = {} />
        
        <cftry>
            <!--- Validate Basic Authentication --->
            <cfset var authResult = validateBasicAuth(arguments.Agency_ID) />
            
            <cfif not authResult.valid>
                <cfset response = {
                    "success": false,
                    "message": authResult.message,
                    "data": {}
                } />
                <cfreturn serializeJSON(response) />
            </cfif>
            
            <cfset var agency_db = authResult.agency_db />
            <cfset var created_by = authResult.emp_id />
            
            <!--- Insert the medication record --->
            <cfquery name="InsertMedication" datasource="#Application.DataSrc#" result="insertResult">
                INSERT INTO #agency_db#.ptmeds_ai (
                    Patient_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="#arguments.Patient_ID#" cfsqltype="cf_sql_integer">,
                    <cfqueryparam value="#arguments.Drug_ID#" cfsqltype="cf_sql_integer" null="#arguments.Drug_ID eq 0#">,
                    <cfqueryparam value="#arguments.Status#" cfsqltype="cf_sql_tinyint">,
                    <cfqueryparam value="#arguments.DateOrdered#" cfsqltype="cf_sql_date" null="#len(trim(arguments.DateOrdered)) eq 0#">,
                    <cfqueryparam value="#arguments.DateDCed#" cfsqltype="cf_sql_date" null="#len(trim(arguments.DateDCed)) eq 0#">,
                    <cfqueryparam value="#arguments.Drug_Name#" cfsqltype="cf_sql_varchar">,
                    <cfqueryparam value="#arguments.Dose#" cfsqltype="cf_sql_varchar" null="#len(trim(arguments.Dose)) eq 0#">,
                    <cfqueryparam value="#arguments.Dose_Units#" cfsqltype="cf_sql_varchar" null="#len(trim(arguments.Dose_Units)) eq 0#">,
                    <cfqueryparam value="#arguments.Route#" cfsqltype="cf_sql_varchar" null="#len(trim(arguments.Route)) eq 0#">,
                    <cfqueryparam value="#arguments.Freq#" cfsqltype="cf_sql_varchar" null="#len(trim(arguments.Freq)) eq 0#">,
                    <cfqueryparam value="#arguments.Notes#" cfsqltype="cf_sql_longvarchar" null="#len(trim(arguments.Notes)) 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>
            
            <!--- Get the inserted record --->
            <cfset insertedID = insertResult.GENERATED_KEY />
            
            <cfquery name="GetInsertedRecord" datasource="#Application.DataSrc#">
                SELECT * FROM #agency_db#.ptmeds_ai
                WHERE PtMeds_ID = <cfqueryparam value="#insertedID#" cfsqltype="cf_sql_integer">
            </cfquery>
            
            <!--- Build success response --->
            <cfset response = {
                "success": true,
                "message": "Medication record inserted successfully",
                "data": {
                    "PtMeds_ID": GetInsertedRecord.PtMeds_ID,
                    "Patient_ID": GetInsertedRecord.Patient_ID,
                    "Drug_ID": GetInsertedRecord.Drug_ID,
                    "Status": GetInsertedRecord.Status,
                    "DateOrdered": isDate(GetInsertedRecord.DateOrdered) ? dateFormat(GetInsertedRecord.DateOrdered, "yyyy-mm-dd") : "",
                    "DateDCed": isDate(GetInsertedRecord.DateDCed) ? dateFormat(GetInsertedRecord.DateDCed, "yyyy-mm-dd") : "",
                    "Drug_Name": GetInsertedRecord.Drug_Name,
                    "Dose": GetInsertedRecord.Dose,
                    "Dose_Units": GetInsertedRecord.Dose_Units,
                    "Route": GetInsertedRecord.Route,
                    "Freq": GetInsertedRecord.Freq,
                    "Notes": GetInsertedRecord.Notes,
                    "Date_Create": dateFormat(GetInsertedRecord.Date_Create, "yyyy-mm-dd") & " " & timeFormat(GetInsertedRecord.Date_Create, "HH:mm:ss"),
                    "Created_by": GetInsertedRecord.Created_by
                }
            } />
            
            <cfcatch type="any">
                <cfset response = {
                    "success": false,
                    "message": "Failed to insert medication record",
                    "error": cfcatch.message,
                    "detail": cfcatch.detail,
                    "data": {}
                } />
            </cfcatch>
        </cftry>
        
        <cfreturn serializeJSON(response) />
    </cffunction>
    
    <!--- Batch insert multiple medication records --->
    <cffunction name="batchInsertMedications" access="remote" returnformat="JSON" hint="Insert multiple ptmeds_ai records">
        <cfargument name="Agency_ID" required="yes" hint="Agency ID">
        <cfargument name="medications_data" required="yes" hint="JSON array of medication records">
        
        <cfset var response = {} />
        <cfset var insertedCount = 0 />
        <cfset var failedCount = 0 />
        <cfset var insertedIDs = [] />
        <cfset var errors = [] />
        
        <cftry>
            <!--- Validate Basic Authentication --->
            <cfset var authResult = validateBasicAuth(arguments.Agency_ID) />
            
            <cfif not authResult.valid>
                <cfset response = {
                    "success": false,
                    "message": authResult.message,
                    "data": {
                        "inserted_count": 0,
                        "failed_count": 0,
                        "inserted_ids": [],
                        "errors": [authResult.message]
                    }
                } />
                <cfreturn serializeJSON(response) />
            </cfif>
            
            <cfset var agency_db = authResult.agency_db />
            <cfset var created_by = authResult.emp_id />
            
            <!--- Parse JSON data --->
            <cfif isJSON(arguments.medications_data)>
                <cfset dataArray = deserializeJSON(arguments.medications_data) />
            <cfelse>
                <cfset dataArray = arguments.medications_data />
            </cfif>
            
            <!--- Loop through each record --->
            <cfloop array="#dataArray#" index="idx" item="record">
                <cftry>
                    <!--- Validate required fields --->
                    <cfif not structKeyExists(record, "Patient_ID") or len(trim(record.Patient_ID)) eq 0>
                        <cfset arrayAppend(errors, "Record #idx#: Patient_ID is required") />
                        <cfset failedCount++ />
                        <cfcontinue />
                    </cfif>
                    
                    <cfif not structKeyExists(record, "Drug_Name") or len(trim(record.Drug_Name)) eq 0>
                        <cfset arrayAppend(errors, "Record #idx#: Drug_Name is required") />
                        <cfset failedCount++ />
                        <cfcontinue />
                    </cfif>
                    
                    <!--- Set defaults --->
                    <cfparam name="record.Drug_ID" default="0" />
                    <cfparam name="record.Status" default="0" />
                    <cfparam name="record.DateOrdered" default="" />
                    <cfparam name="record.DateDCed" default="" />
                    <cfparam name="record.Dose" default="" />
                    <cfparam name="record.Dose_Units" default="" />
                    <cfparam name="record.Route" default="" />
                    <cfparam name="record.Freq" default="" />
                    <cfparam name="record.Notes" default="" />
                    <cfif (NOT len(trim(record.Dose_Units))) AND structKeyExists(record, "dose_units") AND len(trim(record.dose_units))>
                        <cfset record.Dose_Units = trim(record.dose_units) />
                    </cfif>
                    
                    <!--- Insert the record --->
                    <cfquery name="InsertMedication" datasource="#Application.DataSrc#" result="insertResult">
                        INSERT INTO #agency_db#.ptmeds_ai (
                            Patient_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="#record.Patient_ID#" cfsqltype="cf_sql_integer">,
                            <cfqueryparam value="#record.Drug_ID#" cfsqltype="cf_sql_integer" null="#record.Drug_ID eq 0#">,
                            <cfqueryparam value="#record.Status#" cfsqltype="cf_sql_tinyint">,
                            <cfqueryparam value="#record.DateOrdered#" cfsqltype="cf_sql_date" null="#len(trim(record.DateOrdered)) eq 0#">,
                            <cfqueryparam value="#record.DateDCed#" cfsqltype="cf_sql_date" null="#len(trim(record.DateDCed)) eq 0#">,
                            <cfqueryparam value="#record.Drug_Name#" cfsqltype="cf_sql_varchar">,
                            <cfqueryparam value="#record.Dose#" cfsqltype="cf_sql_varchar" null="#len(trim(record.Dose)) eq 0#">,
                            <cfqueryparam value="#record.Dose_Units#" cfsqltype="cf_sql_varchar" null="#len(trim(record.Dose_Units)) eq 0#">,
                            <cfqueryparam value="#record.Route#" cfsqltype="cf_sql_varchar" null="#len(trim(record.Route)) eq 0#">,
                            <cfqueryparam value="#record.Freq#" cfsqltype="cf_sql_varchar" null="#len(trim(record.Freq)) eq 0#">,
                            <cfqueryparam value="#record.Notes#" cfsqltype="cf_sql_longvarchar" null="#len(trim(record.Notes)) 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(insertedIDs, insertResult.GENERATED_KEY) />
                    <cfset insertedCount++ />
                    
                    <cfcatch type="any">
                        <cfset arrayAppend(errors, "Record #idx#: " & cfcatch.message) />
                        <cfset failedCount++ />
                    </cfcatch>
                </cftry>
            </cfloop>
            
            <!--- Build response --->
            <cfset response = {
                "success": (insertedCount gt 0),
                "message": "Batch insert completed: #insertedCount# succeeded, #failedCount# failed",
                "data": {
                    "inserted_count": insertedCount,
                    "failed_count": failedCount,
                    "inserted_ids": insertedIDs,
                    "errors": errors
                }
            } />
            
            <cfcatch type="any">
                <cfset response = {
                    "success": false,
                    "message": "Batch insert failed",
                    "error": cfcatch.message,
                    "data": {
                        "inserted_count": 0,
                        "failed_count": 0,
                        "inserted_ids": [],
                        "errors": [cfcatch.message]
                    }
                } />
            </cfcatch>
        </cftry>
        
        <cfreturn serializeJSON(response) />
    </cffunction>
    
    <!--- Get medication records by Patient ID --->
    <cffunction name="getMedicationsByPatient" access="remote" returnformat="JSON" hint="Get all medications for a patient">
        <cfargument name="Agency_ID" required="yes" hint="Agency ID">
        <cfargument name="Patient_ID" required="yes" hint="Patient ID">
        
        <cfset var response = {} />
        <cfset var medicationsList = [] />
        
        <cftry>
            <!--- Validate Basic Authentication --->
            <cfset var authResult = validateBasicAuth(arguments.Agency_ID) />
            
            <cfif not authResult.valid>
                <cfset response = {
                    "success": false,
                    "message": authResult.message,
                    "data": []
                } />
                <cfreturn serializeJSON(response) />
            </cfif>
            
            <cfset var agency_db = authResult.agency_db />
            
            <!--- Get medications --->
            <cfquery name="GetMedications" datasource="#Application.DataSrc#">
                SELECT * FROM #agency_db#.ptmeds_ai
                WHERE Patient_ID = <cfqueryparam value="#arguments.Patient_ID#" cfsqltype="cf_sql_integer">
                ORDER BY Date_Create DESC
            </cfquery>
            
            <cfif GetMedications.recordcount gt 0>
                <cfloop query="GetMedications">
                    <cfset obj = {
                        "PtMeds_ID": GetMedications.PtMeds_ID,
                        "Patient_ID": GetMedications.Patient_ID,
                        "Drug_ID": GetMedications.Drug_ID,
                        "Status": GetMedications.Status,
                        "DateOrdered": isDate(GetMedications.DateOrdered) ? dateFormat(GetMedications.DateOrdered, "yyyy-mm-dd") : "",
                        "DateDCed": isDate(GetMedications.DateDCed) ? dateFormat(GetMedications.DateDCed, "yyyy-mm-dd") : "",
                        "Drug_Name": GetMedications.Drug_Name,
                        "Dose": GetMedications.Dose,
                        "Dose_Units": GetMedications.Dose_Units,
                        "Route": GetMedications.Route,
                        "Freq": GetMedications.Freq,
                        "Notes": GetMedications.Notes,
                        "Date_Create": dateFormat(GetMedications.Date_Create, "yyyy-mm-dd") & " " & timeFormat(GetMedications.Date_Create, "HH:mm:ss"),
                        "Created_by": GetMedications.Created_by
                    } />
                    <cfset arrayAppend(medicationsList, obj) />
                </cfloop>
            </cfif>
            
            <cfset response = {
                "success": true,
                "message": "Found #GetMedications.recordcount# medication record(s)",
                "data": medicationsList
            } />
            
            <cfcatch type="any">
                <cfset response = {
                    "success": false,
                    "message": "Failed to retrieve medication records",
                    "error": cfcatch.message,
                    "data": []
                } />
            </cfcatch>
        </cftry>
        
        <cfreturn serializeJSON(response) />
    </cffunction>
    
</cfcomponent>

