<!--- #10785: Find active patients with serious (orange) medication interactions.
     Same matching rules as patientadmin_new/patient/medlist.cfm (Med_Interactions pairs).
     Sets:
       Request.medInteractionPatients — array of structs:
         Patient_ID, Pt_Last, Pt_First, Fingerprint, Phys_Name, MedsHtml, DetailsHtml,
         Pairs (array of pair structs), Reported (boolean), Report_ID, Comm_ID
       Request.medInteractionPendingCount — patients not yet flagged as reported for current fingerprint
     Request.medInteractionShowReported: 0 = pending only, 1 = reported only
--->
<cfsetting requestTimeOut="300">

<cfparam name="Request.medInteractionShowReported" default="0">
<!--- Optional: limit scan to one patient (used by Report to Physician action) --->
<cfparam name="Request.medInteractionPatientId" default="0">

<cfset Request.medInteractionPatients = ArrayNew(1)>
<cfset Request.medInteractionPendingCount = 0>
<cfset _filterPatientId = Val(Request.medInteractionPatientId)>

<!--- Ensure report-flag table exists (safe if migration already ran) --->
<cfinclude template="medication_interaction_report_schema_inc.cfm">

<!--- #10846: heal Status=2 rows whose Communication was already faxed via View Communication
     (patientadmin sendfax.cfm) before that path promoted the report (Arkwood / Evergreen). --->
<cftry>
	<cfset _healEmp = 2>
	<cfif isDefined("session.employeeid") AND IsNumeric(session.employeeid) AND Val(session.employeeid) GT 0>
		<cfset _healEmp = Val(session.employeeid)>
	</cfif>
	<cfquery datasource="#Application.DataSrc#">
		UPDATE #Request.prefix_db_agency#.pMed_Interaction_Report r
		INNER JOIN #Request.prefix_db_agency#.Communication c
			ON c.Comm_ID = r.Comm_ID
			AND IFNULL(c.send_fax, 0) = 1
			AND IFNULL(c.Status, 0) = 0
		SET r.Status = 0,
			r.Reported_Date = IFNULL(DATE(c.fax_sent_date), CURDATE()),
			r.Reported_By = IF(IFNULL(r.Reported_By, 0) = 0, <cfqueryparam value="#_healEmp#" cfsqltype="cf_sql_integer">, r.Reported_By),
			r.Reporting_Method = IF(TRIM(IFNULL(r.Reporting_Method, '')) = '', 'Fax', r.Reporting_Method)
		WHERE r.Status = 2
		AND IFNULL(r.Comm_ID, 0) > 0
		<cfif _filterPatientId GT 0>
			AND r.Patient_ID = <cfqueryparam value="#_filterPatientId#" cfsqltype="cf_sql_integer">
		</cfif>
	</cfquery>
	<cfcatch type="any"></cfcatch>
</cftry>

<!--- Active patient meds with generics (one pass) --->
<cfquery name="GetAllPtMedGenerics" datasource="#Application.DataSrc#">
	SELECT pPatients.Patient_ID,
		pPatients.Pt_Last,
		pPatients.Pt_First,
		pPtmeds.PtMeds_ID,
		pPtmeds.Drug_Name,
		LCASE(TRIM(Meds_New.Generic_Name)) AS Generic,
		IFNULL(phys.Phys_Last, '') AS Phys_Last,
		IFNULL(phys.Phys_First, '') AS Phys_First
	FROM #Request.prefix_db_agency#.pPatients
	INNER JOIN #Request.prefix_db_agency#.pPtmeds
		ON pPtmeds.Patient_ID = pPatients.Patient_ID
		AND pPtmeds.Status = 0
	INNER JOIN #Request.prefix_db_lookup#.Meds_New
		ON pPtmeds.Drug_ID = Meds_New.Trade_Num
		AND TRIM(IFNULL(Meds_New.Generic_Name, '')) <> ''
	LEFT JOIN #Request.prefix_db_agency#.pAdmit
		ON pAdmit.Patient_ID = pPatients.Patient_ID
		AND pAdmit.Status = 0
		AND pAdmit.Admit_ID = (
			SELECT MAX(a2.Admit_ID)
			FROM #Request.prefix_db_agency#.pAdmit a2
			WHERE a2.Patient_ID = pPatients.Patient_ID
			AND a2.Status = 0
		)
	LEFT JOIN #Request.prefix_db_lookup#.pPhysicians phys
		ON phys.Phys_ID = pAdmit.Render_Phys_ID
		AND phys.Status = 0
	WHERE pPatients.Status = 0
	<cfif _filterPatientId GT 0>
		AND pPatients.Patient_ID = <cfqueryparam value="#_filterPatientId#" cfsqltype="cf_sql_integer">
	</cfif>
	ORDER BY pPatients.Pt_Last, pPatients.Pt_First, pPatients.Patient_ID, pPtmeds.PtMeds_ID
</cfquery>

<!--- Status 0 = reported; Status 2 = communication created, awaiting fax / Mark as reported (#10846) --->
<cfquery name="GetReportedFlags" datasource="#Application.DataSrc#">
	SELECT Report_ID, Patient_ID, Fingerprint, Comm_ID, Status,
		IFNULL(Reported_Date, NULL) AS Reported_Date,
		IFNULL(Reported_By, 0) AS Reported_By,
		IFNULL(Reporting_Method, '') AS Reporting_Method
	FROM #Request.prefix_db_agency#.pMed_Interaction_Report
	WHERE Status IN (0, 2)
	<cfif _filterPatientId GT 0>
		AND Patient_ID = <cfqueryparam value="#_filterPatientId#" cfsqltype="cf_sql_integer">
	</cfif>
</cfquery>
<cfset reportedByPatient = StructNew()>
<cfset pendingByPatient = StructNew()>
<cfloop query="GetReportedFlags">
	<cfset _pk = ToString(GetReportedFlags.Patient_ID)>
	<cfset _flagInfo = {
		Report_ID = GetReportedFlags.Report_ID,
		Comm_ID = GetReportedFlags.Comm_ID,
		Reported_Date = GetReportedFlags.Reported_Date,
		Reported_By = GetReportedFlags.Reported_By,
		Reporting_Method = GetReportedFlags.Reporting_Method
	}>
	<cfif Val(GetReportedFlags.Status) EQ 0>
		<cfif NOT StructKeyExists(reportedByPatient, _pk)>
			<cfset reportedByPatient[_pk] = StructNew()>
		</cfif>
		<cfset reportedByPatient[_pk][GetReportedFlags.Fingerprint] = _flagInfo>
	<cfelse>
		<cfif NOT StructKeyExists(pendingByPatient, _pk)>
			<cfset pendingByPatient[_pk] = StructNew()>
		</cfif>
		<cfset pendingByPatient[_pk][GetReportedFlags.Fingerprint] = _flagInfo>
	</cfif>
</cfloop>

<!--- Index Med_Interactions drug_generics (cached 1 hour, same as medlist) --->
<cfquery name="GetInteractionDrugGenerics" datasource="#Application.DataSrc#" cachedwithin="#CreateTimeSpan(0,1,0,0)#">
	SELECT DISTINCT LCASE(TRIM(drug_generic)) AS Drug_Generic
	FROM hhapowerpath.Med_Interactions
	WHERE TRIM(IFNULL(drug_generic, '')) <> ''
</cfquery>

<!--- Group meds by patient --->
<cfset medsByPatient = StructNew()>
<cfset patientMeta = StructNew()>
<cfloop query="GetAllPtMedGenerics">
	<cfset _pid = ToString(GetAllPtMedGenerics.Patient_ID)>
	<cfif NOT StructKeyExists(medsByPatient, _pid)>
		<cfset medsByPatient[_pid] = ArrayNew(1)>
		<cfset patientMeta[_pid] = {
			Patient_ID = GetAllPtMedGenerics.Patient_ID,
			Pt_Last = GetAllPtMedGenerics.Pt_Last,
			Pt_First = GetAllPtMedGenerics.Pt_First,
			Phys_Name = Trim(GetAllPtMedGenerics.Phys_Last & ", " & GetAllPtMedGenerics.Phys_First)
		}>
		<cfif patientMeta[_pid].Phys_Name EQ ",">
			<cfset patientMeta[_pid].Phys_Name = "">
		</cfif>
	</cfif>
	<cfset ArrayAppend(medsByPatient[_pid], {
		PtMeds_ID = GetAllPtMedGenerics.PtMeds_ID,
		Drug_Name = GetAllPtMedGenerics.Drug_Name,
		Generic = GetAllPtMedGenerics.Generic
	})>
</cfloop>

<!--- Candidate interaction rows for drug_generics present in this agency's meds --->
<cfset agencyDrugGenerics = StructNew()>
<cfloop collection="#medsByPatient#" item="_pid">
	<cfloop array="#medsByPatient[_pid]#" index="_med">
		<cfloop query="GetInteractionDrugGenerics">
			<cfset _dg = GetInteractionDrugGenerics.Drug_Generic>
			<cfif Find(_dg, _med.Generic)>
				<cfset agencyDrugGenerics[_dg] = true>
			</cfif>
		</cfloop>
	</cfloop>
</cfloop>

<cfif NOT StructIsEmpty(agencyDrugGenerics)>
	<cfquery name="GetCandidateInteractions" datasource="#Application.DataSrc#">
		SELECT DISTINCT LCASE(TRIM(drug_generic)) AS Drug_Generic,
			LCASE(TRIM(interaction_generic)) AS Interaction_Key,
			interaction_generic AS Interaction_Generic,
			IFNULL(level, '') AS Interaction_Level,
			IFNULL(notes, '') AS Med_Interaction_Notes
		FROM hhapowerpath.Med_Interactions
		WHERE LCASE(TRIM(drug_generic)) IN (
			<cfqueryparam cfsqltype="cf_sql_varchar" value="#StructKeyList(agencyDrugGenerics)#" list="yes">
		)
		AND TRIM(IFNULL(interaction_generic, '')) <> ''
	</cfquery>

	<cfloop collection="#medsByPatient#" item="_pid">
		<cfset _meds = medsByPatient[_pid]>
		<cfif ArrayLen(_meds) LT 2>
			<cfcontinue>
		</cfif>

		<!--- Map drug_generic → PtMeds_IDs for this patient --->
		<cfset medsByDrugGeneric = StructNew()>
		<cfset medLookup = StructNew()>
		<cfloop array="#_meds#" index="_med">
			<cfset medLookup[ToString(_med.PtMeds_ID)] = _med>
			<cfloop collection="#agencyDrugGenerics#" item="_dg">
				<cfif Find(_dg, _med.Generic)>
					<cfif NOT StructKeyExists(medsByDrugGeneric, _dg)>
						<cfset medsByDrugGeneric[_dg] = "">
					</cfif>
					<cfset medsByDrugGeneric[_dg] = ListAppend(medsByDrugGeneric[_dg], _med.PtMeds_ID)>
				</cfif>
			</cfloop>
		</cfloop>

		<cfif StructIsEmpty(medsByDrugGeneric)>
			<cfcontinue>
		</cfif>

		<cfset pairs = ArrayNew(1)>
		<cfset involvedMedIds = "">
		<cfset seenPairKeys = StructNew()>
		<cfset medsByInteractionGeneric = StructNew()>

		<cfloop query="GetCandidateInteractions">
			<cfif NOT StructKeyExists(medsByDrugGeneric, GetCandidateInteractions.Drug_Generic)>
				<cfcontinue>
			</cfif>
			<cfset _ig = GetCandidateInteractions.Interaction_Key>
			<cfif NOT StructKeyExists(medsByInteractionGeneric, _ig)>
				<cfset medsByInteractionGeneric[_ig] = "">
				<cfloop array="#_meds#" index="_med">
					<cfif Find(_ig, _med.Generic)>
						<cfset medsByInteractionGeneric[_ig] = ListAppend(medsByInteractionGeneric[_ig], _med.PtMeds_ID)>
					</cfif>
				</cfloop>
			</cfif>
			<cfif NOT Len(medsByInteractionGeneric[_ig])>
				<cfcontinue>
			</cfif>
			<cfloop list="#medsByDrugGeneric[GetCandidateInteractions.Drug_Generic]#" index="_primaryId">
				<cfloop list="#medsByInteractionGeneric[_ig]#" index="_compareId">
					<cfif _primaryId EQ _compareId>
						<cfcontinue>
					</cfif>
					<!--- Normalize pair order so A|B and B|A collapse --->
					<cfset _lo = Min(Val(_primaryId), Val(_compareId))>
					<cfset _hi = Max(Val(_primaryId), Val(_compareId))>
					<cfset _pairKey = _lo & "|" & _hi & "|" & GetCandidateInteractions.Interaction_Level & "|" & GetCandidateInteractions.Interaction_Generic>
					<cfif StructKeyExists(seenPairKeys, _pairKey)>
						<cfcontinue>
					</cfif>
					<cfset seenPairKeys[_pairKey] = true>
					<cfset _medA = medLookup[ToString(_lo)]>
					<cfset _medB = medLookup[ToString(_hi)]>
					<cfset ArrayAppend(pairs, {
						Med1_ID = _lo,
						Med1_Name = _medA.Drug_Name,
						Med1_Generic = _medA.Generic,
						Med2_ID = _hi,
						Med2_Name = _medB.Drug_Name,
						Med2_Generic = _medB.Generic,
						Interaction_Level = GetCandidateInteractions.Interaction_Level,
						Interaction_Generic = GetCandidateInteractions.Interaction_Generic,
						Notes = GetCandidateInteractions.Med_Interaction_Notes
					})>
					<cfif NOT ListFind(involvedMedIds, _lo)>
						<cfset involvedMedIds = ListAppend(involvedMedIds, _lo)>
					</cfif>
					<cfif NOT ListFind(involvedMedIds, _hi)>
						<cfset involvedMedIds = ListAppend(involvedMedIds, _hi)>
					</cfif>
				</cfloop>
			</cfloop>
		</cfloop>

		<cfif ArrayLen(pairs) EQ 0>
			<cfcontinue>
		</cfif>

		<!--- Fingerprint = sorted involved PtMeds_IDs (changes when interacting med set changes) --->
		<cfset idArr = ListToArray(involvedMedIds)>
		<cfset ArraySort(idArr, "numeric", "asc")>
		<cfset fingerprint = ArrayToList(idArr, ",")>

		<cfset isReported = false>
		<cfset isPendingReport = false>
		<cfset reportId = 0>
		<cfset commId = 0>
		<cfif StructKeyExists(reportedByPatient, _pid) AND StructKeyExists(reportedByPatient[_pid], fingerprint)>
			<cfset isReported = true>
			<cfset reportId = Val(reportedByPatient[_pid][fingerprint].Report_ID)>
			<cfset commId = Val(reportedByPatient[_pid][fingerprint].Comm_ID)>
		<cfelseif StructKeyExists(pendingByPatient, _pid) AND StructKeyExists(pendingByPatient[_pid], fingerprint)>
			<cfset isPendingReport = true>
			<cfset reportId = Val(pendingByPatient[_pid][fingerprint].Report_ID)>
			<cfset commId = Val(pendingByPatient[_pid][fingerprint].Comm_ID)>
		</cfif>

		<!--- Pending count always reflects unreported rows (even when viewing reported-only). --->
		<cfif NOT isReported>
			<cfset Request.medInteractionPendingCount = Request.medInteractionPendingCount + 1>
		</cfif>

		<!--- show_reported=0: pending/needs report only; show_reported=1: reported only --->
		<cfif Val(Request.medInteractionShowReported) EQ 1>
			<cfif NOT isReported>
				<cfcontinue>
			</cfif>
		<cfelse>
			<cfif isReported>
				<cfcontinue>
			</cfif>
		</cfif>

		<!--- Build display HTML / memo text --->
		<cfset medNameArr = ArrayNew(1)>
		<cfset detailsHtml = "">
		<cfset memoLines = "">
		<cfset seenMedName = StructNew()>
		<cfloop array="#pairs#" index="_p">
			<cfif NOT StructKeyExists(seenMedName, _p.Med1_Name)>
				<cfset seenMedName[_p.Med1_Name] = true>
				<cfset ArrayAppend(medNameArr, _p.Med1_Name)>
			</cfif>
			<cfif NOT StructKeyExists(seenMedName, _p.Med2_Name)>
				<cfset seenMedName[_p.Med2_Name] = true>
				<cfset ArrayAppend(medNameArr, _p.Med2_Name)>
			</cfif>
			<cfset _noteBit = "">
			<cfif Len(Trim(_p.Notes))>
				<cfset _noteBit = " — " & _p.Notes>
			</cfif>
			<cfset _lvlBit = "">
			<cfif Len(Trim(_p.Interaction_Level))>
				<cfset _lvlBit = " [" & _p.Interaction_Level & "]">
			</cfif>
			<cfset detailsHtml = detailsHtml & "<div style='margin-bottom:4px;'><strong>" & HTMLEditFormat(_p.Med1_Name) & "</strong> ↔ <strong>" & HTMLEditFormat(_p.Med2_Name) & "</strong>" & HTMLEditFormat(_lvlBit) & HTMLEditFormat(_noteBit) & "</div>">
			<cfset memoLines = memoLines & "- " & _p.Med1_Name & " (" & _p.Med1_Generic & ") interacts with " & _p.Med2_Name & " (" & _p.Med2_Generic & ")" & _lvlBit & _noteBit & Chr(10)>
		</cfloop>
		<cfset medNames = ArrayToList(medNameArr, "; ")>

		<cfset row = Duplicate(patientMeta[_pid])>
		<cfset row.Fingerprint = fingerprint>
		<cfset row.Pairs = pairs>
		<cfset row.MedsHtml = HTMLEditFormat(medNames)>
		<cfset row.DetailsHtml = detailsHtml>
		<cfset row.MemoText = memoLines>
		<cfset row.Reported = isReported>
		<cfset row.PendingReport = isPendingReport>
		<cfset row.Report_ID = reportId>
		<cfset row.Comm_ID = commId>
		<cfset ArrayAppend(Request.medInteractionPatients, row)>
	</cfloop>
</cfif>
