<cfcomponent displayname="EVV Status Manager" hint="Manages EVV status tracking and change detection" output="false">
	
	<cffunction name="init" displayname="Initialize Component" access="public" returntype="EVVStatusManager" hint="I initialize and return the EVVStatusManager object.">
		<cfreturn this>
	</cffunction>
	
	<!--- Function to check if data has changed after EVV transmission --->
	<cffunction name="checkForDataChanges" access="public" returntype="struct" output="false">
		<cfargument name="API_Type" required="yes" hint="clients, employee, or visits">
		<cfargument name="Record_ID" required="yes" hint="Patient_ID, Emp_ID, or Schedule_ID">
		<cfargument name="Agency_ID" required="yes" hint="Agency ID">
		
		<cfset var result = structNew()>
		<cfset result.hasChanges = false>
		<cfset result.changeDetails = "">
		<cfset result.lastEVVDate = "">
		
		<!--- Get the last EVV transmission date for successfully transmitted records --->
		<cfquery name="getLastEVV" datasource="#Application.DataSrc#">
			SELECT Date_Create, San_status
			FROM #Request.prefix_db_lookup#.EVV
			WHERE API_Type = <cfqueryparam value="#arguments.API_Type#" cfsqltype="cf_sql_varchar">
			AND Agency_ID = <cfqueryparam value="#arguments.Agency_ID#" cfsqltype="cf_sql_integer">
			AND status = 0
			AND (
				UPPER(San_status) LIKE '%SUCCESS%'
				OR UPPER(San_status) LIKE '%TRANSMITTED%'
				OR UPPER(San_status) LIKE '%TRANSACTION RECEIVED%'
			)
			<cfif arguments.API_Type EQ 'clients'>
				AND Patient_ID = <cfqueryparam value="#arguments.Record_ID#" cfsqltype="cf_sql_integer">
			<cfelseif arguments.API_Type EQ 'employee'>
				AND Emp_ID = <cfqueryparam value="#arguments.Record_ID#" cfsqltype="cf_sql_integer">
			<cfelseif arguments.API_Type EQ 'visits'>
				AND Schedule_ID = <cfqueryparam value="#arguments.Record_ID#" cfsqltype="cf_sql_integer">
			</cfif>
			ORDER BY EVV_ID DESC
			LIMIT 1
		</cfquery>
		
		<cfif getLastEVV.recordcount GT 0>
			<cfset result.lastEVVDate = getLastEVV.Date_Create>
			
			<!--- Check for changes based on API type --->
			<cfif arguments.API_Type EQ 'clients'>
				<cfset result = checkClientChanges(arguments.Record_ID, getLastEVV.Date_Create, result)>
			<cfelseif arguments.API_Type EQ 'employee'>
				<cfset result = checkEmployeeChanges(arguments.Record_ID, getLastEVV.Date_Create, result)>
			<cfelseif arguments.API_Type EQ 'visits'>
				<cfset result = checkVisitChanges(arguments.Record_ID, getLastEVV.Date_Create, result)>
			</cfif>
		</cfif>
		
		<cfreturn result>
	</cffunction>
	
	<!--- Check for client data changes --->
	<cffunction name="checkClientChanges" access="private" returntype="struct" output="false">
		<cfargument name="Patient_ID" required="yes">
		<cfargument name="lastEVVDate" required="yes">
		<cfargument name="result" required="yes">
		
		<cftry>
			<!--- Add 2 minute grace period to avoid false positives from automatic updates --->
			<cfset graceDateTime = DateAdd("n", 2, arguments.lastEVVDate)>
			
			<cfquery name="checkClientUpdates" datasource="#Application.DataSrc#">
				SELECT COUNT(*) as change_count
				FROM #Request.prefix_db_agency#.pPatients
				WHERE Patient_ID = <cfqueryparam value="#arguments.Patient_ID#" cfsqltype="cf_sql_integer">
				AND Record_Mod_Date IS NOT NULL
				AND Record_Mod_Date > <cfqueryparam value="#graceDateTime#" cfsqltype="cf_sql_timestamp">
			</cfquery>
			
			<cfif checkClientUpdates.change_count GT 0>
				<cfset arguments.result.hasChanges = true>
				<cfset arguments.result.changeDetails = "Client information has been modified since last EVV transmission.">
			</cfif>
			
			<cfcatch type="any">
				<!--- If Record_Mod_Date column doesn't exist or other error, silently fail --->
				<cfset arguments.result.hasChanges = false>
			</cfcatch>
		</cftry>
		
		<cfreturn arguments.result>
	</cffunction>
	
	<!--- Check for employee data changes --->
	<cffunction name="checkEmployeeChanges" access="private" returntype="struct" output="false">
		<cfargument name="Emp_ID" required="yes">
		<cfargument name="lastEVVDate" required="yes">
		<cfargument name="result" required="yes">
		
		<cftry>
			<!--- Add 2 minute grace period to avoid false positives from automatic updates --->
			<cfset graceDateTime = DateAdd("n", 2, arguments.lastEVVDate)>
			
			<cfquery name="checkEmpUpdates" datasource="#Application.DataSrc#">
				SELECT COUNT(*) as change_count
				FROM #Request.prefix_db_lookup#.pEmployee
				WHERE Emp_ID = <cfqueryparam value="#arguments.Emp_ID#" cfsqltype="cf_sql_integer">
				AND Record_Mod_Date IS NOT NULL
				AND Record_Mod_Date > <cfqueryparam value="#graceDateTime#" cfsqltype="cf_sql_timestamp">
			</cfquery>
			
			<cfif checkEmpUpdates.change_count GT 0>
				<cfset arguments.result.hasChanges = true>
				<cfset arguments.result.changeDetails = "Employee information has been modified since last EVV transmission.">
			</cfif>
			
			<cfcatch type="any">
				<!--- If Record_Mod_Date column doesn't exist or other error, silently fail --->
				<cfset arguments.result.hasChanges = false>
			</cfcatch>
		</cftry>
		
		<cfreturn arguments.result>
	</cffunction>
	
	<!--- Check for visit data changes --->
	<cffunction name="checkVisitChanges" access="private" returntype="struct" output="false">
		<cfargument name="Schedule_ID" required="yes">
		<cfargument name="lastEVVDate" required="yes">
		<cfargument name="result" required="yes">
		
		<cftry>
			<!--- Add 2 minute grace period to avoid false positives from automatic updates --->
			<cfset graceDateTime = DateAdd("n", 2, arguments.lastEVVDate)>
			
			<cfquery name="checkVisitUpdates" datasource="#Application.DataSrc#">
				SELECT COUNT(*) as change_count
				FROM #Request.prefix_db_agency#.pSchedules
				WHERE Schedule_ID = <cfqueryparam value="#arguments.Schedule_ID#" cfsqltype="cf_sql_integer">
				AND Date_Change IS NOT NULL
				AND Date_Change > <cfqueryparam value="#graceDateTime#" cfsqltype="cf_sql_timestamp">
			</cfquery>
			
			<cfif checkVisitUpdates.change_count GT 0>
				<cfset arguments.result.hasChanges = true>
				<cfset arguments.result.changeDetails = "Visit information has been modified since last EVV transmission.">
			</cfif>
			
			<cfcatch type="any">
				<!--- If Date_Change column doesn't exist or other error, silently fail --->
				<cfset arguments.result.hasChanges = false>
			</cfcatch>
		</cftry>
		
		<cfreturn arguments.result>
	</cffunction>
	
	<!--- Function to update EVV status when data changes --->
	<cffunction name="updateEVVStatusForChanges" access="public" returntype="boolean" output="false">
		<cfargument name="API_Type" required="yes" hint="clients, employee, or visits">
		<cfargument name="Record_ID" required="yes" hint="Patient_ID, Emp_ID, or Schedule_ID">
		<cfargument name="Agency_ID" required="yes" hint="Agency ID">
		
		<cfset var changeResult = checkForDataChanges(arguments.API_Type, arguments.Record_ID, arguments.Agency_ID)>
		
		<cfif changeResult.hasChanges>
			<!--- First, get the latest EVV_ID that was successfully transmitted --->
			<cfquery name="getLatestEVV" datasource="#Application.DataSrc#">
				SELECT EVV_ID, San_status
				FROM #Request.prefix_db_lookup#.EVV 
				WHERE API_Type = <cfqueryparam value="#arguments.API_Type#" cfsqltype="cf_sql_varchar">
				AND Agency_ID = <cfqueryparam value="#arguments.Agency_ID#" cfsqltype="cf_sql_integer">
				AND status = 0
				AND (
					UPPER(San_status) LIKE '%SUCCESS%'
					OR UPPER(San_status) LIKE '%TRANSMITTED%'
					OR UPPER(San_status) LIKE '%TRANSACTION RECEIVED%'
				)
				<cfif arguments.API_Type EQ 'clients'>
					AND Patient_ID = <cfqueryparam value="#arguments.Record_ID#" cfsqltype="cf_sql_integer">
				<cfelseif arguments.API_Type EQ 'employee'>
					AND Emp_ID = <cfqueryparam value="#arguments.Record_ID#" cfsqltype="cf_sql_integer">
				<cfelseif arguments.API_Type EQ 'visits'>
					AND Schedule_ID = <cfqueryparam value="#arguments.Record_ID#" cfsqltype="cf_sql_integer">
				</cfif>
				ORDER BY EVV_ID DESC
				LIMIT 1
			</cfquery>
			
			<!--- Then update the status --->
			<cfif getLatestEVV.recordcount GT 0>
				<cfquery name="updateEVVStatus" datasource="#Application.DataSrc#">
					UPDATE #Request.prefix_db_lookup#.EVV 
					SET San_status = 'Data Changed - Retransmission Required',
						Date_Update = NOW()
					WHERE EVV_ID = <cfqueryparam value="#getLatestEVV.EVV_ID#" cfsqltype="cf_sql_integer">
					AND (
						UPPER(San_status) LIKE '%SUCCESS%'
						OR UPPER(San_status) LIKE '%TRANSMITTED%'
						OR UPPER(San_status) LIKE '%TRANSACTION RECEIVED%'
					)
					AND (
						UPPER(San_status) NOT LIKE '%FAILED%'
						AND UPPER(San_status) NOT LIKE '%ERROR%'
						AND UPPER(San_status) NOT LIKE '%REJECTED%'
						AND UPPER(San_status) NOT LIKE '%DATA CHANGED%'
					)
				</cfquery>
				
				<cfreturn true>
			</cfif>
		</cfif>
		
		<cfreturn false>
	</cffunction>
	
	<!--- Function to get current EVV status with change detection --->
	<cffunction name="getEVVStatusWithChangeDetection" access="public" returntype="struct" output="false">
		<cfargument name="API_Type" required="yes" hint="clients, employee, or visits">
		<cfargument name="Record_ID" required="yes" hint="Patient_ID, Emp_ID, or Schedule_ID">
		<cfargument name="Agency_ID" required="yes" hint="Agency ID">
		
		<cfset var result = structNew()>
		<cfset result.EVV_Status = "Not Transmitted">
		<cfset result.ButtonsDisabled = false>
		<cfset result.HasChanges = false>
		
		<!--- Get current EVV status --->
		<cfquery name="getEVVStatus" datasource="#Application.DataSrc#">
			SELECT San_status, Date_Create
			FROM #Request.prefix_db_lookup#.EVV
			WHERE API_Type = <cfqueryparam value="#arguments.API_Type#" cfsqltype="cf_sql_varchar">
			AND Agency_ID = <cfqueryparam value="#arguments.Agency_ID#" cfsqltype="cf_sql_integer">
			AND status = 0
			<cfif arguments.API_Type EQ 'clients'>
				AND Patient_ID = <cfqueryparam value="#arguments.Record_ID#" cfsqltype="cf_sql_integer">
			<cfelseif arguments.API_Type EQ 'employee'>
				AND Emp_ID = <cfqueryparam value="#arguments.Record_ID#" cfsqltype="cf_sql_integer">
			<cfelseif arguments.API_Type EQ 'visits'>
				AND Schedule_ID = <cfqueryparam value="#arguments.Record_ID#" cfsqltype="cf_sql_integer">
			</cfif>
			ORDER BY EVV_ID DESC
			LIMIT 1
		</cfquery>
		
		<cfif getEVVStatus.recordcount GT 0>
			<cfif FindNoCase('Transaction Received', getEVVStatus.San_status) GT 0>
				<cfset result.EVV_Status = "Transaction Received">
				<cfset result.ButtonsDisabled = true>  <!--- Disable both EVV and Status Check buttons --->
				
			<!--- Check for data changes after successful transmission
			<cfset var changeResult = checkForDataChanges(arguments.API_Type, arguments.Record_ID, arguments.Agency_ID)>
			<cfif changeResult.hasChanges>
				<!--- Data has been modified - reactivate buttons for retransmission --->
				<cfset result.EVV_Status = "Data Changed - Retransmission Required">
				<cfset result.ButtonsDisabled = false>
				<cfset result.HasChanges = true>
				
				<!--- Update the EVV status in database (fallback - triggers should handle this automatically) --->
				<!--- Note: If triggers are installed, this is redundant but provides safety --->
				<cfset updateEVVStatusForChanges(arguments.API_Type, arguments.Record_ID, arguments.Agency_ID)>
			</cfif> --->
			<cfelseif getEVVStatus.San_status EQ 'Transmitted - Initial submission'>
				<cfset result.EVV_Status = "Transmitted - Initial submission">
				<cfset result.ButtonsDisabled = false>  <!--- Enable buttons to check status --->
			<cfelseif getEVVStatus.San_status EQ 'Transmitted - awaiting status check'>
				<cfset result.EVV_Status = "Transmitted - awaiting status check">
				<cfset result.ButtonsDisabled = false>
			<cfelseif FindNoCase('awaiting status', getEVVStatus.San_status) GT 0>
				<cfset result.EVV_Status = getEVVStatus.San_status>
				<cfset result.ButtonsDisabled = false>
			<cfelseif FindNoCase('Pending', getEVVStatus.San_status) GT 0 OR FindNoCase('Processing', getEVVStatus.San_status) GT 0>
				<cfset result.EVV_Status = "Transmitted - awaiting status check">
				<cfset result.ButtonsDisabled = false>
			<cfelseif FindNoCase('Complete', getEVVStatus.San_status) GT 0 OR FindNoCase('Processed', getEVVStatus.San_status) GT 0 OR FindNoCase('Accepted', getEVVStatus.San_status) GT 0>
				<cfset result.EVV_Status = "Transaction Received">
				<cfset result.ButtonsDisabled = true>
			<cfelseif arguments.API_Type EQ 'visits' AND (getEVVStatus.San_status EQ 'Success' OR getEVVStatus.San_status EQ 'SUCCESS')>
				<cfset result.EVV_Status = "Transaction Received">
				<cfset result.ButtonsDisabled = true>
			<cfelseif getEVVStatus.San_status EQ 'Transmitted'>
				<cfset result.EVV_Status = "Transmitted">
				<cfset result.ButtonsDisabled = true>  <!--- Disable Send EVV button to prevent duplicate transmission --->
			<cfelseif FindNoCase('SUCCESS', getEVVStatus.San_status) GT 0>
				<cfset result.EVV_Status = "Transmitted">
				<cfset result.ButtonsDisabled = true>  <!--- Disable Send EVV button to prevent duplicate transmission --->
			<cfelseif FindNoCase('Data Changed', getEVVStatus.San_status) GT 0>
				<cfset result.EVV_Status = "Data Changed - Retransmission Required">
				<cfset result.HasChanges = true>
				<cfset result.ButtonsDisabled = false>  <!--- Enable buttons for re-transmission --->
			<cfelseif len(trim(getEVVStatus.San_status)) GT 0>
				<cfset result.EVV_Status = "Error">
				<cfset result.ButtonsDisabled = false>  <!--- Enable buttons for error retry --->
			</cfif>
		</cfif>
		
		<cfreturn result>
	</cffunction>

	<cffunction name="resolveVisitEVVStatusDisplay" access="public" returntype="string" output="false">
		<cfargument name="dbStatus" type="string" required="true">
		<cfargument name="activeJob" type="struct" required="true">

		<cfset var display = trim(arguments.dbStatus)>
		<cfset var jobStatus = "">

		<cfif findNoCase("Transaction Received", display) GT 0>
			<cfreturn "Transaction Received">
		</cfif>

		<cfif structKeyExists(arguments.activeJob, "evvStatus") AND len(trim(arguments.activeJob.evvStatus))>
			<cfset jobStatus = trim(arguments.activeJob.evvStatus)>
			<cfif findNoCase("Transaction Received", jobStatus) GT 0>
				<cfreturn "Transaction Received">
			</cfif>
			<cfset display = jobStatus>
		<cfelseif structKeyExists(arguments.activeJob, "hasActiveJob") AND arguments.activeJob.hasActiveJob
			AND structKeyExists(arguments.activeJob, "jobStatus") AND arguments.activeJob.jobStatus EQ "waiting_status"
			AND display EQ "Transmitted - Initial submission">
			<cfset display = "Transmitted - awaiting status check">
		</cfif>

		<cfreturn display>
	</cffunction>

	<cffunction name="getEVVAgenciesList" access="public" returntype="string" output="false">
		<cfif structKeyExists(session, "EVVagencies") AND len(trim(session.EVVagencies)) GT 0>
			<cfreturn trim(session.EVVagencies)>
		</cfif>
		<cfif structKeyExists(application, "EVVagencies") AND len(trim(application.EVVagencies)) GT 0>
			<cfreturn trim(application.EVVagencies)>
		</cfif>
		<cfreturn "">
	</cffunction>

	<cffunction name="agencyUsesEVVAutomation" access="public" returntype="boolean" output="false">
		<cfargument name="agencyID" type="numeric" required="true">
		<cfset var evvAgencies = getEVVAgenciesList()>
		<cfif NOT len(evvAgencies)>
			<cfreturn false>
		</cfif>
		<cfreturn listFind(evvAgencies, arguments.agencyID) GT 0>
	</cffunction>
	
</cfcomponent>
