/*
** 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 (
	"errors"
	"fmt"

	"jobarranger2/src/libs/golibs/builder"
	"jobarranger2/src/libs/golibs/common"
	"jobarranger2/src/libs/golibs/database"
	"jobarranger2/src/libs/golibs/event"
	"jobarranger2/src/libs/golibs/utils"
)

func processJobnetTimeout(jobnetPayload common.EventData, dbconn database.DBConnection) error {
	funcname := "processJobnetTimeout"
	JobnetRunLogger.JaLog("JAJOBNETRUN400001", funcname)

	if jobnetPayload.Event.Name == common.EventIconTimeoutWarning {
		err := processIconTimeout(jobnetPayload)
		if err != nil {
			JobnetRunLogger.JaLog("JAJOBNETRUN400003", funcname, err.Error())
			return err
		}
		return nil
	}
	jobnetRunData, ok := jobnetPayload.NextProcess.Data.(common.JobnetRunData)
	if !ok {
		return fmt.Errorf("type assertion to JobnetRunData failed")
	}

	if len(jobnetPayload.Transfer.Files) == 0 {
		return errors.New("no transfer files found")
	}

	queries := make([]common.ParameterizedQuery, 0)
	moveFilePath := END
	currentFilePath := jobnetPayload.Transfer.Files[0].Source
	var nextEventData common.EventData

	JobnetRunLogger.JaJobLog(common.JC_JOBNET_TIMEOUT)

	switch jobnetRunData.TimeoutRunType {
	case 0:
		//timeout warning
		queries = jaSetStatusJobnetTimeout(jobnetRunData.InnerJobnetId, jobnetRunData.TimeoutRunType, queries...)
		nextEventData = prepareNextEventData(
			common.EventJobnetStatusChange,
			common.DBSyncerManagerProcess,
			map[string]any{},
			queries,
		)
		JobnetRunLogger.JaLog("JAJOBNTRUN300001", funcname, jobnetRunData.InnerJobnetId)
	case 1:
		//timeout stop
		queries = jaSetStatusJobnetTimeout(jobnetRunData.InnerJobnetId, jobnetRunData.TimeoutRunType, queries...)
		nextEventData = prepareNextEventData(
			common.EventJobnetStatusChange,
			common.DBSyncerManagerProcess,
			map[string]any{},
			queries,
		)
	}

	sqlCond := builder.NewSQLCondition(
		fmt.Sprintf("select status from ja_2_run_jobnet_table where inner_jobnet_id = %d", jobnetRunData.InnerJobnetId),
	).
		AddCondition(
			builder.NewCondition("ignore").
				Field("status", common.OpEq, common.StatusEnd).
				Build(),
		).
		AddCondition(
			builder.NewCondition("ignore").
				Field("status", common.OpEq, common.StatusRunErr).
				Build(),
		).
		AddCondition(
			builder.NewCondition("ignore").
				Field("status", common.OpEq, common.StatusEndErr).
				Build(),
		).
		DefaultAction(common.ActionExec). // move to error folder
		Build()
	nextEventData.SQLConditions = []common.SQLCondition{sqlCond}

	JobnetRunLogger.JaLog("JAJOBNETRUN400009", nextEventData)
	err := event.CreateNextEvent(nextEventData, jobnetRunData.InnerJobnetId, jobnetRunData.JobnetID, jobnetRunData.InnerJobId)
	if err != nil {
		return fmt.Errorf("%v", err)
	}

	//if timeout is jobnet stop
	if jobnetRunData.TimeoutRunType == 1 {
		JobnetRunLogger.JaLog("JAJOBNETRUN000004")
		jobnetPayload.Event.Name = common.EventJobnetStop
		err := processEnd(jobnetPayload, dbconn)
		if err != nil {
			return fmt.Errorf("[ERROR] : %s", err.Error())
		}
	} else {
		// Move file to destination folder if needed
		JobnetRunLogger.JaLog("JAJOBNETRUN400005", currentFilePath, END)
		err := utils.MoveToSubFolder(currentFilePath, moveFilePath)
		if err != nil {
			return fmt.Errorf("moveFile from current %s to %s failed : %s", currentFilePath, moveFilePath, err.Error())
		}
	}

	JobnetRunLogger.JaLog("JAJOBNETRUN400002", funcname)
	return nil

}

func processIconTimeout(jobnetPayload common.EventData) error {
	funcname := "processIconTimeout"
	JobnetRunLogger.JaLog("JAJOBNETRUN400001", funcname)

	jobnetRunData, ok := jobnetPayload.NextProcess.Data.(common.JobnetRunData)
	if !ok {
		return fmt.Errorf("type assertion to JobnetRunData failed")
	}

	if len(jobnetPayload.Transfer.Files) == 0 {
		return errors.New("no transfer files found")
	}

	queries := make([]common.ParameterizedQuery, 0)

	currentFilePath := jobnetPayload.Transfer.Files[0].Destination
	JobnetRunLogger.JaLog("JAJOBNETRUN400006", currentFilePath)

	queries = jaSetStatusIconTimeoutWarning(jobnetRunData.InnerJobnetId, queries...)

	nextEventData := prepareNextEventData(
		common.EventJobnetStatusChange,
		common.DBSyncerManagerProcess,
		map[string]any{},
		queries,
	)

	JobnetRunLogger.JaLog("JAJOBNETRUN400009", nextEventData)
	err := event.CreateNextEvent(nextEventData, jobnetRunData.InnerJobnetId, jobnetRunData.JobnetID, jobnetRunData.InnerJobId)
	if err != nil {
		return fmt.Errorf("%v", err)
	}

	// Move file to destination folder if needed
	JobnetRunLogger.JaLog("JAJOBNETRUN400005", currentFilePath, END)
	err = utils.MoveToSubFolder(currentFilePath, END)
	if err != nil {
		return fmt.Errorf("moveFile from current %s to %s failed : %s", currentFilePath, END, err.Error())
	}

	JobnetRunLogger.JaLog("JAJOBNETRUN400002", funcname)
	return nil
}
