/*
** 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 (
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"jobarranger2/src/jobarg_server/managers/icon_exec_manager/events"
	"jobarranger2/src/libs/golibs/common"
)

var transationFileId, udsFilepath, clientDataFilepath, inFolderPath, runFolderPath, udsDirpath, tmpDirPath, timeout string

func get_icon_data[T any](data map[string]interface{}) T{
	var iconData T

	dataByte, err := json.Marshal(data)
	if err != nil {
		panic(fmt.Errorf("could not Marshal data. data: %s, error:%s", data, err.Error()))
	}

	err = json.Unmarshal(dataByte, &iconData)
	if err != nil {
		panic(fmt.Errorf("could not get iconData. resultMap[.data]: %s, error:%s", string(dataByte), err.Error()))
	}

	return iconData
}

func main() {
	flag.StringVar(&transationFileId, "id", "", "icon transaction file's id")
	flag.StringVar(&udsFilepath, "uds", "", "unix domain socket filepath")
	flag.StringVar(&inFolderPath, "in", "", "exec manager's in folderpath")
	flag.StringVar(&runFolderPath, "run", "", "exec manager's run folderpath")
	flag.StringVar(&udsDirpath, "udsdir", "", "uds parent folderpath")
	flag.StringVar(&tmpDirPath, "tmpdir", "", "tmp folderpath")
	flag.StringVar(&timeout, "timeout", "0", "timeout")
	flag.StringVar(&clientDataFilepath, "clientdata", "", "clientdata filepath")
	flag.Parse()

	err := common.SetClientPid(os.Getpid())
	if err != nil {
		fmt.Fprintln(os.Stderr, "common.SetClientPidfailed, err:", err.Error())
		os.Exit(common.JA_JOBEXEC_FAIL)
	}

	if transationFileId != "" {
		// get processData from transaction file
		processData, err := events.GetIconExecutionProcessData(
			filepath.Join(inFolderPath, transationFileId + ".json"))
		if err != nil {
			panic(err)
		}

		fd := 3
		file := os.NewFile(uintptr(fd), "passed-fd")
		if file == nil {
			fmt.Println("Invalid file descriptor")
			// ignore err
		}
		defer file.Close()

		var byteData []byte
		switch processData.RunJobData.IconType {
		case common.IconTypeIf:
			iconData := get_icon_data[common.IconIfData](processData.RunJobData.Data)
			iconData.FlowType = 1

			byteData, err = json.Marshal(iconData)
		case common.IconTypeCalc:
			data := get_icon_data[common.IconCalcData](processData.RunJobData.Data)
			data.Value = "werwer"

			byteData, err = json.Marshal(data)
		case common.IconTypeLess:
			data := get_icon_data[common.IconLessData](processData.RunJobData.Data)

			cmd := exec.Command(common.LessIconClientExecPath)

			// Start the process but do not wait for it
			if err := cmd.Start(); err != nil {
				panic(err)
			}
			
			data.SshClientPid = cmd.Process.Pid
			data.JobExitCode = 0
			data.SshClientUdsPath = ""

			byteData, err = json.Marshal(data)
		case common.IconTypeExtJob:
			data := get_icon_data[common.IconExtData](processData.RunJobData.Data)
			data.WaitTime = 123456
			data.JobExitCode = 2

			byteData, err = json.Marshal(data)
		case common.IconTypeFCopy:
			data := get_icon_data[common.IconFCopyData](processData.RunJobData.Data)
			data.IsJaz1 = true

			byteData, err = json.Marshal(data)
		case common.IconTypeLink:
			data := get_icon_data[common.IconLinkData](processData.RunJobData.Data)

			byteData, err = json.Marshal(data)
		case common.IconTypeValue:
			data := get_icon_data[common.IconValueData](processData.RunJobData.Data)
			data.Variables["TEST"] = "IT IS TEST"
			
			byteData, err = json.Marshal(data)
		case common.IconTypeInfo:
			data := get_icon_data[common.IconInfoData](processData.RunJobData.Data)
			data.Status = 3

			byteData, err = json.Marshal(data)
		case common.IconTypeTask:
			data := get_icon_data[common.IconTaskData](processData.RunJobData.Data)
			data.SubmitInnerJobnetId = 123
			data.SubmitJobnetId = "1234"

			byteData, err = json.Marshal(data)
		case common.IconTypeW:
			data := get_icon_data[common.IconWData](processData.RunJobData.Data)
			data.EndCountPlusFlag = false

			byteData, err = json.Marshal(data)
		case common.IconTypeIfEnd:
			data := get_icon_data[common.IconIfEndData](processData.RunJobData.Data)
			data.EndCountPlusFlag = false

			byteData, err = json.Marshal(data)
		}

		if err != nil {
			panic(err)
		}

		if byteData != nil {
			file.Write(byteData)
		}
	}

	var timeToSleep time.Duration = 1
	fmt.Printf("client is runnig: %ds\n", timeToSleep)
	time.Sleep(timeToSleep * time.Second)
	fmt.Println("client is exiting", time.Now())
	os.Exit(1)
}