/*
** Job Arranger for ZABBIX
** Copyright (C) 2025 Daiwa Institute of Research Ltd. All Rights Reserved.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
**/

package main

import (
	"fmt"
	"strconv"

	"jobarranger2/src/libs/golibs/common"
	"jobarranger2/src/libs/golibs/logger/logger"
	"jobarranger2/src/libs/golibs/utils"
)

func ProcessStartIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessStartIconResult"
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}

	logger.JaLog("JAICONRESULTSTART400001", *logData, funcName, innerJobID)

	return SetEnd(innerJobID, 1, processData, nextdata)
}

func ProcessEndIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessEndIconResult"
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}

	jobResult := processData.JobResult.Result
	message := processData.JobResult.Message

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	iconEndData, err := ExtractIconData[common.IconEndData](processData.RunJobData.Data)
	if err != nil {
		message, _ = logger.JaLog("JAICONRESULTEND200001", *logData, funcName, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	logger.JaLog("JAICONRESULTEND400001", *logData, funcName, iconEndData.JobnetStopCode, innerJobID)

	rawStopCode, err := CopyValue(innerJobID, iconEndData.JobnetStopCode, processData.RunJobVariableData.BeforeVariable, processData)
	if err != nil {
		message, _ = logger.JaLog("JAICONRESULTEND200002", *logData, funcName, iconEndData.JobnetStopCode, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	stopCodeValue, convErr := strconv.Atoi(rawStopCode)
	if convErr != nil {
		message, _ = logger.JaLog("JAICONRESULTEND200004", *logData, funcName, rawStopCode, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	if err = MergeAfterVariable(processData, "JOB_EXIT_CD", stopCodeValue); err != nil {
		message, _ = logger.JaLog("JAICONRESULTEND200003", *logData, funcName, "JOB_EXIT_CD", stopCodeValue, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	return SetEnd(innerJobID, 1, processData, nextdata)
}

func ProcessIfIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessIfIconResult"
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}
	logger.JaLog("JAICONRESULTIF400001", *logData, funcName, innerJobID)

	jobResult := processData.JobResult.Result
	message := processData.JobResult.Message

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	iconIfData, err := ExtractIconData[common.IconIfData](processData.RunJobData.Data)
	if err != nil {
		message, _ := logger.JaLog("JAICONRESULTIF200001", *logData, funcName, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	nextdata.NextProcess.Data = common.FlowProcessData{
		FlowType: iconIfData.FlowType,
	}

	return SetEnd(innerJobID, 1, processData, nextdata)
}

func ProcessValueIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessValueIconResult"

	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}

	message := processData.JobResult.Message
	jobResult := processData.JobResult.Result

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	variablesPtr, err := ExtractIconData[map[string]string](processData.RunJobData.Data["variables"])
	if err != nil || variablesPtr == nil || len(*variablesPtr) == 0 {
		message, _ := logger.JaLog("JAICONRESULTVALUE200001", *logData, funcName, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	variables := *variablesPtr
	logger.JaLog("JAICONRESULTVALUE400001", *logData, funcName, variables, innerJobID)

	for key, val := range variables {
		afterValue, err := CopyValue(innerJobID, val, processData.RunJobVariableData.BeforeVariable, processData)
		if err != nil {
			message, _ := logger.JaLog("JAICONRESULTVALUE200002", *logData, funcName, val, innerJobID)
			return handleIconError(innerJobID, 2, message, processData, nextdata)
		}

		if err := MergeAfterVariable(processData, key, afterValue); err != nil {
			message, _ := logger.JaLog("JAICONRESULTVALUE200003", *logData, funcName, key, val, innerJobID)
			return handleIconError(innerJobID, 2, message, processData, nextdata)
		}
	}

	return SetEnd(innerJobID, 1, processData, nextdata)
}

func ProcessAgentJobResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessAgentJobResult"
	var (
		msg        string
		iconStatus = 2
		runErr     = 1 // default is error
	)
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", *logData, funcName, err.Error())
		return err
	}

	result := processData.JobResult.Result
	returnCode := toInt(processData.JobResult.ReturnCode)
	message := processData.JobResult.Message
	signal := processData.JobResult.Signal
	status := processData.JobResult.JobStatus
	jobType := processData.RunJobData.IconType
	stopCode := processData.RunJobData.Data["stop_code"]
	stopCodeStr := fmt.Sprintf("%v", stopCode)
	hostname := processData.JobResult.Hostname

	logger.JaLog("JAICONRESULTAGENT400001", *logData, funcName, returnCode, stopCode, status, signal, innerJobID)

	iconTimeoutData, err := ExtractIconData[common.IconTimeoutData](processData.RunJobData.Data)
	if err != nil {
		message, _ := logger.JaLog("JAICONRESULTTIMEOUT200001", *logData, funcName, innerJobID, err.Error())
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	if jobType == common.JobTypeJob && iconTimeoutData.Timeout != 0 {
		updateQuery := fmt.Sprintf("UPDATE %s SET end_flag = TRUE WHERE  inner_job_id = ?", common.Ja2RunTimeOutTable)
		nextdata.AddPQ(updateQuery, innerJobID)
	}

	if jobType == common.JobTypeReboot {
		lockQuery := fmt.Sprintf("SELECT lock_host_name FROM %s WHERE lock_host_name = 'HOST_LOCK_RECORD' FOR UPDATE", common.Ja2HostLockTable)
		nextdata.AddPQ(lockQuery)
		updateQuery := fmt.Sprintf("DELETE FROM %s WHERE  lock_host_name = ?", common.Ja2HostLockTable)
		nextdata.AddPQ(updateQuery, hostname)

		if iconTimeoutData.Timeout != 0 {
			updateQuery := fmt.Sprintf("UPDATE %s SET end_flag = TRUE WHERE  inner_job_id = ?", common.Ja2RunTimeOutTable)
			nextdata.AddPQ(updateQuery, innerJobID)
		}
	}

	switch {
	case result != common.JA_RESPONSE_SUCCEED:
		msg = message
	case signal == 1 && status == common.AgentJobStatusAbort:
		msg = "Aborted the job"
		iconStatus = int(common.AgentJobStatusAbort)
	case status == common.AgentJobStatusAbort:
		msg = "Aborted the job"
		iconStatus = int(common.AgentJobStatusAbort)
		runErr = 0
	case signal == 1:
		msg = "The job caught a signal"
	default:
		switch jobType {
		case common.JobTypeJob:
			if JaNumberMatch(fmt.Sprintf("%v", processData.JobResult.ReturnCode), stopCodeStr, processData) == 0 {
				runErr = 0
			} else {
				iconStatus = 1
				msg = fmt.Sprintf("The job return code '%d' is range of the stop code '%s'", returnCode, stopCodeStr)
			}
		case common.JobTypeFwait:
			if returnCode == 0 || returnCode == 1 {
				runErr = 0
			} else {
				msg = "The job failed"
			}
		case common.JobTypeReboot:
			if returnCode == 0 {
				runErr = 0
			} else {
				msg = "The job failed"
			}
		default:
			return fmt.Errorf("unknown job type '%d'", jobType)
		}
	}

	if runErr == 0 {
		if err := MergeAfterVariable(processData, "ICON_STATUS", 0); err != nil {
			message, _ = logger.JaLog("JAICONRESULTAGENT200001", *logData, funcName, "ICON_STATUS", 0, innerJobID)
			return handleIconError(innerJobID, 2, message, processData, nextdata)
		}
		return SetEnd(innerJobID, 1, processData, nextdata)
	}

	return handleIconError(innerJobID, iconStatus, msg, processData, nextdata)
}

func ProcessJobnetIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessJobnetIconResult"
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}

	status := processData.RunJobData.Status

	logger.JaLog("JAICONRESULTJOBNET400001", *logData, funcName, status, innerJobID)

	switch status {
	case common.JAJobnetStatusEnd:
		exitCode := toInt(processData.JobResult.ReturnCode)
		if err := MergeAfterVariable(processData, "JOB_EXIT_CD", strconv.Itoa(exitCode)); err != nil {
			message, _ := logger.JaLog("JAICONRESULTJOBNET200002", *logData, funcName, "JOB_EXIT_CD", strconv.Itoa(exitCode), innerJobID)
			return handleIconError(innerJobID, 2, message, processData, nextdata)
		}
		return SetEnd(innerJobID, 1, processData, nextdata)

	case common.JAJobnetStatusRunErr:

		return SetRunError(innerJobID, 2, processData, nextdata)

	case common.JAJobnetStatusEndErr:

		return SetEndError(innerJobID, 0, processData, nextdata)

	default:
		message, _ := logger.JaLog("JAICONRESULTJOBNET200003", *logData, funcName, status, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}
}

func ProcessMIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessMIconResult"
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}
	logger.JaLog("JAICONRESULTM400001", *logData, funcName, innerJobID)

	message := processData.JobResult.Message
	jobResult := processData.JobResult.Result

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	return SetEnd(innerJobID, 1, processData, nextdata)
}

func ProcessWIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) (bool, error) {
	const funcName = "ProcessWIconResult"
	isSetValue := true
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return isSetValue, err
	}
	logger.JaLog("JAICONRESULTW400001", *logData, funcName, innerJobID)

	jobResult := processData.JobResult.Result
	message := processData.JobResult.Message

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return isSetValue, handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	iconWData, err := ExtractIconData[common.IconWData](processData.RunJobData.Data)
	if err != nil {
		message, _ = logger.JaLog("JAICONRESULTW200001", *logData, funcName, innerJobID)
		return isSetValue, handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	endCountPlusFlag := iconWData.EndCountPlusFlag

	if endCountPlusFlag && jobResult == common.JA_JOBRESULT_SUCCEED {
		lockQuery := fmt.Sprintf("SELECT end_count FROM %s WHERE inner_job_id = ? FOR UPDATE", common.Ja2RunJobTable)
		nextdata.AddPQ(lockQuery, innerJobID)
		updateQuery := fmt.Sprintf("UPDATE %s SET end_count = end_count + 1 WHERE inner_job_id = ?", common.Ja2RunJobTable)
		nextdata.AddPQ(updateQuery, innerJobID)
	}

	if !endCountPlusFlag && jobResult == common.JA_JOBRESULT_SUCCEED {
		return isSetValue, SetEnd(innerJobID, 1, processData, nextdata)
	}

	return !isSetValue, nil
}

func ProcessLIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessLIconResult"
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}
	logger.JaLog("JAICONRESULTL400001", *logData, funcName, innerJobID)

	jobResult := processData.JobResult.Result
	message := processData.JobResult.Message

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	return SetEnd(innerJobID, 1, processData, nextdata)
}

func ProcessExtIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessExtIconResult"
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}

	message := processData.JobResult.Message
	jobResult := processData.JobResult.Result

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	iconExtData, err := ExtractIconData[common.IconExtData](processData.RunJobData.Data)
	if err != nil {
		message, _ = logger.JaLog("JAICONRESULTEXT200001", *logData, funcName, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	commandId := iconExtData.CommandId
	logger.JaLog("JAICONRESULTEXT400001", *logData, funcName, commandId, innerJobID)

	if commandId == common.JA_CMD_WEEK {
		if err := MergeAfterVariable(processData, "JOB_EXIT_CD", processData.JobResult.ReturnCode); err != nil {
			message, _ = logger.JaLog("JAICONRESULTEXT200002", *logData, funcName, "JOB_EXIT_CD", processData.JobResult.ReturnCode, innerJobID)
			return handleIconError(innerJobID, 2, message, processData, nextdata)
		}
	}

	if commandId == common.ZABBIX_SENDER {

		if err := MergeAfterVariable(processData, "STD_OUT", processData.JobResult.StdOut); err != nil {
			message, _ = logger.JaLog("JAICONRESULTEXT200002", *logData, funcName, "STD_OUT", processData.JobResult.StdOut, innerJobID)
			return handleIconError(innerJobID, 2, message, processData, nextdata)
		}

		if err = MergeAfterVariable(processData, "STD_ERR", processData.JobResult.StdErr); err != nil {
			message, _ = logger.JaLog("JAICONRESULTEXT200002", *logData, funcName, "STD_ERR", processData.JobResult.StdErr, innerJobID)
			return handleIconError(innerJobID, 2, message, processData, nextdata)
		}

		if err = MergeAfterVariable(processData, "JOB_EXIT_CD", processData.JobResult.ReturnCode); err != nil {
			message, _ = logger.JaLog("JAICONRESULTEXT200002", *logData, funcName, "JOB_EXIT_CD", processData.JobResult.ReturnCode, innerJobID)
			return handleIconError(innerJobID, 2, message, processData, nextdata)
		}
	}

	return SetEnd(innerJobID, 1, processData, nextdata)
}

func ProcessCalcIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessCalcIconResult"
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}

	message := processData.JobResult.Message
	jobResult := processData.JobResult.Result

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	iconCalcData, err := ExtractIconData[common.IconCalcData](processData.RunJobData.Data)
	if err != nil {
		message, _ = logger.JaLog("JAICONRESULTCALC200001", *logData, funcName, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	logger.JaLog("JAICONRESULTCALC400001", *logData, funcName, iconCalcData.ValueName, iconCalcData.Value, innerJobID)

	if err = MergeAfterVariable(processData, iconCalcData.ValueName, iconCalcData.Value); err != nil {
		message, _ = logger.JaLog("JAICONRESULTCALC200002", *logData, funcName, iconCalcData.ValueName, iconCalcData.Value, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	return SetEnd(innerJobID, 1, processData, nextdata)
}

func ProcessTaskIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessTaskIconResult"
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}
	logger.JaLog("JAICONRESULTTASK400001", *logData, funcName, innerJobID)

	message := processData.JobResult.Message
	jobResult := processData.JobResult.Result

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	return SetEnd(innerJobID, 1, processData, nextdata)
}

func ProcessInfoIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessInfoIconResult"
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}

	message := processData.JobResult.Message
	jobResult := processData.JobResult.Result

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	iconInfoData, err := ExtractIconData[common.IconInfoData](processData.RunJobData.Data)
	if err != nil {
		message, _ = logger.JaLog("JAICONRESULTINFO200001", *logData, funcName, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	logger.JaLog("JAICONRESULTINFO400001", *logData, funcName, iconInfoData.Status, innerJobID)

	if iconInfoData.Status < 0 {
		message, _ = logger.JaLog("JAICONRESULTINFO200002", *logData, funcName, iconInfoData.Status, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	err = MergeAfterVariable(processData, "LAST_STATUS", iconInfoData.Status)
	if err != nil {
		message, _ := logger.JaLog("JAICONRESULTINFO200003", *logData, funcName, "LAST_STATUS", strconv.Itoa(iconInfoData.Status), innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	return SetEnd(innerJobID, 1, processData, nextdata)
}

func ProcessIfEndIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) (bool, error) {
	const funcName = "ProcessIfEndIconResult"
	isSetValue := true
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return isSetValue, err
	}
	logger.JaLog("JAICONRESULTIFEND400001", *logData, funcName, innerJobID)

	jobResult := processData.JobResult.Result
	message := processData.JobResult.Message

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return isSetValue, handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	iconIfEndData, err := ExtractIconData[common.IconIfEndData](processData.RunJobData.Data)
	if err != nil {
		message, _ = logger.JaLog("JAICONRESULTIFEND200001", *logData, funcName, innerJobID)
		return isSetValue, handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	endCountPlusFlag := iconIfEndData.EndCountPlusFlag

	if endCountPlusFlag && jobResult == common.JA_JOBRESULT_SUCCEED {
		lockQuery := fmt.Sprintf("SELECT end_count FROM %s WHERE inner_job_id = ? FOR UPDATE", common.Ja2RunJobTable)
		nextdata.AddPQ(lockQuery, innerJobID)
		updateQuery := fmt.Sprintf("UPDATE %s SET end_count = end_count + 1 WHERE inner_job_id = ?", common.Ja2RunJobTable)
		nextdata.AddPQ(updateQuery, innerJobID)
	}

	if !endCountPlusFlag && jobResult == common.JA_JOBRESULT_SUCCEED {
		return isSetValue, SetEnd(innerJobID, 1, processData, nextdata)
	}

	return !isSetValue, nil
}

func ProcessFcopyResult(innerJobID uint64, fileType common.AgentJobType, filePath string, processData *common.IconExecutionProcessData, nextdata *common.EventData) (bool, error) {
	const funcName = "ProcessFcopyResult"
	sendEvent := false
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return sendEvent, err
	}

	jobResult := processData.JobResult.Result
	message := processData.JobResult.Message

	logger.JaLog("JAICONRESULTFCOPY400001", *logData, funcName, innerJobID, fileType, filePath)

	if filePath == "" {
		message, _ = logger.JaLog("JAICONRESULTFCOPY200001", *logData, funcName, filePath, innerJobID)
		sendEvent = true
		return sendEvent, handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	switch fileType {
	/*	If the job result fails on the source side, simply move the event file to the end folder and ignore it,
		since the final fcopy icon status is determined based on the destination result.
	*/
	case common.AgentJobTypeGetFile:
		if jobResult == common.JA_RESPONSE_SUCCEED {
			if err := utils.MoveToSubFolder(filePath, "pending"); err != nil {
				message, _ = logger.JaLog("JAICONRESULTFCOPY200002", *logData, funcName, filePath, "in", "pending", err)
				sendEvent = true
				return sendEvent, handleIconError(innerJobID, 2, message, processData, nextdata)
			}
		} else {
			if err := utils.MoveToSubFolder(filePath, "end"); err != nil {
				message, _ = logger.JaLog("JAICONRESULTFCOPY200002", *logData, funcName, filePath, "in", "end", err)
				sendEvent = true
				return sendEvent, handleIconError(innerJobID, 2, message, processData, nextdata)
			}
		}

	case common.AgentJobTypePutFile:
		if jobResult == common.JA_RESPONSE_SUCCEED {
			if err := utils.MoveToSubFolder(filePath, "end"); err != nil {
				message, _ = logger.JaLog("JAICONRESULTFCOPY200002", *logData, funcName, filePath, "in", "end", err)
				sendEvent = true
				return sendEvent, handleIconError(innerJobID, 2, message, processData, nextdata)
			}
			sendEvent = true
			return sendEvent, SetEnd(innerJobID, 1, processData, nextdata)
		} else {
			if err := utils.MoveToSubFolder(filePath, "end"); err != nil {
				message, _ = logger.JaLog("JAICONRESULTFCOPY200002", *logData, funcName, filePath, "in", "end", err)
				sendEvent = true
				return sendEvent, handleIconError(innerJobID, 2, message, processData, nextdata)
			}
			sendEvent = true
			return sendEvent, handleIconError(innerJobID, 2, message, processData, nextdata)
		}

	default:
		message, _ = logger.JaLog("JAICONRESULTFCOPY200004", *logData, funcName, fileType, innerJobID)
		sendEvent = true
		return sendEvent, handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	return sendEvent, nil
}

func ProcessReleaseIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessReleaseIconResult"
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}
	logger.JaLog("JAICONRESULTREL400001", *logData, funcName, innerJobID)

	jobResult := processData.JobResult.Result
	message := processData.JobResult.Message

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	return SetEnd(innerJobID, 1, processData, nextdata)
}

func ProcessAgentLessIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessAgentLessIconResult"
	var (
		iconLessData            *common.IconLessData
		iconTimeoutData         *common.IconTimeoutData
		sessionID, stopCode     string
		sessionFlag, iconStatus int
		err                     error
	)
	logData := &logger.Logging{}
	logData, err = getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}

	innerJobnetMainID := processData.RunJobnetData.InnerJobnetMainID
	// returnCode := processData.JobResult.ReturnCode
	message := processData.JobResult.Message
	jobResult := processData.JobResult.Result
	// stdOut := common.TruncateTo64KB(processData.JobResult.StdOut)
	// stdErr := common.TruncateTo64KB(processData.JobResult.StdErr)
	// jobExitCode := processData.JobResult.ReturnCode

	iconLessData, err = ExtractIconData[common.IconLessData](processData.RunJobData.Data)
	if err != nil {
		message, _ = logger.JaLog("JAICONRESULTLINK200001", *logData, funcName, innerJobID)
		goto errhandling
	}

	iconTimeoutData, err = ExtractIconData[common.IconTimeoutData](processData.RunJobData.Data)
	if err != nil {
		message, _ = logger.JaLog("JAICONRESULTTIMEOUT200001", *logData, funcName, innerJobID, err.Error())
		goto errhandling
	}

	if iconTimeoutData.Timeout != 0 {
		updateQuery := fmt.Sprintf("UPDATE %s SET end_flag = TRUE WHERE  inner_job_id = ?", common.Ja2RunTimeOutTable)
		nextdata.AddPQ(updateQuery, innerJobID)
	}

	sessionID = iconLessData.SessionID
	sessionFlag = iconLessData.SessionFlag
	stopCode = iconLessData.StopCode

	logger.JaLog("JAICONRESULTLESS400001", *logData, funcName, sessionFlag, sessionID, innerJobnetMainID, stopCode, innerJobID)

	if sessionID == "" || innerJobnetMainID == 0 {
		message, _ = logger.JaLog("JAICONRESULTLESS200001", *logData, funcName, innerJobID)
		goto errhandling
	}

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		goto errhandling
	}

	if sessionFlag == common.JA_SES_OPERATION_FLAG_ONETIME || sessionFlag == common.JA_SES_OPERATION_FLAG_CONNECT || sessionFlag == common.JA_SES_OPERATION_FLAG_CONTINUE {
		if JaNumberMatch(fmt.Sprintf("%v", processData.JobResult.ReturnCode), stopCode, processData) != 0 {
			iconStatus = 1
			message, _ = logger.JaLog("JAICONRESULTLESS200002", *logData, funcName, fmt.Sprintf("%v", processData.JobResult.ReturnCode), stopCode, innerJobID)
			goto errhandling
		}
	}

	if err = UpdateSession(jobResult, sessionFlag, sessionID, innerJobnetMainID, processData, nextdata); err != nil {
		message, _ := logger.JaLog("JAICONRESULTLESS200003", *logData, funcName, sessionID, innerJobID)
		return handleIconError(innerJobID, iconStatus, message, processData, nextdata)
	}

	return SetEnd(innerJobID, 1, processData, nextdata)

errhandling:

	if err := UpdateSession(jobResult, sessionFlag, sessionID, innerJobnetMainID, processData, nextdata); err != nil {
		message, _ := logger.JaLog("JAICONRESULTLESS200003", *logData, funcName, sessionID, innerJobID)
		return handleIconError(innerJobID, iconStatus, message, processData, nextdata)
	}
	return handleIconError(innerJobID, 2, message, processData, nextdata)

}

func ProcessZabbixLinkIconResult(innerJobID uint64, processData *common.IconExecutionProcessData, nextdata *common.EventData) error {
	const funcName = "ProcessZabbixLinkIconResult"
	logData := &logger.Logging{}
	logData, err := getLogData(processData)
	if err != nil {
		logger.JaLog("JAICONRESULTNORMAL200013", logger.Logging{}, funcName, err.Error())
		return err
	}

	jobResult := processData.JobResult.Result
	message := processData.JobResult.Message

	if jobResult == common.JA_JOBRESULT_FAIL || jobResult == common.JA_JOBRESULT_PRE_EXEC_FAIL {
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	iconLinkData, err := ExtractIconData[common.IconLinkData](processData.RunJobData.Data)
	if err != nil {
		message, _ := logger.JaLog("JAICONRESULTLINK200001", *logData, funcName, innerJobID)
		return handleIconError(innerJobID, 2, message, processData, nextdata)
	}

	linkTarget := iconLinkData.LinkTarget
	linkOperation := iconLinkData.LinkOperation
	zbxLastStatus := iconLinkData.ZBXLastStatus
	zbxLatestData := iconLinkData.ZBXLatestData
	zbxDataType := iconLinkData.ZBXDataType

	logger.JaLog("JAICONRESULTLINK400001", *logData, funcName, linkTarget, linkOperation, innerJobID)

	if linkTarget == 1 || linkTarget == 2 || linkTarget == 3 {
		if linkOperation == 2 {
			if err := MergeAfterVariable(processData, common.ZBXLINK_ZBX_LAST_STATUS, zbxLastStatus); err != nil {
				message, _ = logger.JaLog("JAICONRESULTLINK200002", *logData, funcName, "ZBX_LAST_STATUS", zbxLastStatus, innerJobID)
				return handleIconError(innerJobID, 2, message, processData, nextdata)
			}
		}
	}

	if linkTarget == 2 {
		if linkOperation == 3 {
			if err := MergeAfterVariable(processData, common.ZBXLINK_ZBX_LATEST_DATA, zbxLatestData); err != nil {
				message, _ = logger.JaLog("JAICONRESULTLINK200002", *logData, funcName, "ZBX_LASTEST_DATA", zbxLatestData, innerJobID)
				return handleIconError(innerJobID, 2, message, processData, nextdata)
			}

			if err = MergeAfterVariable(processData, common.ZBXLINK_ZBX_DATA_TYPE, zbxDataType); err != nil {
				message, _ = logger.JaLog("JAICONRESULTLINK200002", *logData, funcName, "ZBX_DATA_TYPE", zbxDataType, innerJobID)
				return handleIconError(innerJobID, 2, message, processData, nextdata)
			}
		}
	}

	return SetEnd(innerJobID, 1, processData, nextdata)
}
