/*
** 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"
	"io"
	"os"
	"strconv"

	utils "jobarranger2/src/jobarg_monitor/pkg/utils"
	"jobarranger2/src/libs/golibs/forker"
	"jobarranger2/src/libs/golibs/uds"
)

const (
	SockFilePath = "/tmp/jamonitor.sock"
)

func main() {

	var args utils.MonitorArgs
	daemonflag := flag.Bool("d", false, "Run as daemon")
	flag.StringVar(&args.DBHost, "dbhost", "", "Database host")
	flag.IntVar(&args.DBPort, "dbport", 0, "Database port")
	flag.StringVar(&args.DBName, "dbname", "", "Database Name")
	flag.StringVar(&args.DBUser, "dbuser", "", "Database user")
	flag.StringVar(&args.DBPassword, "dbpassword", "", "Database password")
	flag.IntVar(&args.LoadShiftTime, "loadshift", 0, "Load shift time")
	flag.IntVar(&args.RunShiftTime, "runshift", 0, "Run shift time")
	flag.Parse()

	if err := utils.ValidateMonitorArgs(&args); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	dbcon, err := ConnectDB(&args)
	if err != nil {
		fmt.Printf("[ERROR] : %s\n", err.Error())
		os.Exit(1)
	}
	defer dbcon.Close()

	if *daemonflag {
		runDaemon(SockFilePath)
		return
	}

	udsClient := uds.CreateUdsClient(SockFilePath, 30)
	conn, err := udsClient.Connect()
	if err == nil {

		payload, _ := json.Marshal(args)
		_, err = conn.Write(payload)
		if err != nil {
			fmt.Printf("[ERROR] Failed to write: %s\n", err)
			return
		}
		buf := make([]byte, 1024)
		n, err := conn.Read(buf)
		if err != nil {
			if err == io.EOF {
				fmt.Println("")
			} else {
				fmt.Printf("[ERROR] : %s\n", err.Error())
			}
			return
		}
		if n == 0 {
			fmt.Println("[INFO] : Received empty data")
			return
		}
		msg := string(buf[:n])
		fmt.Printf("%s", msg)
		return
	}

	err = daemonize(&args)
	if err != nil {
		os.Exit(1)
	}
}

func daemonize(args *utils.MonitorArgs) error {
	execPath, err := os.Executable()
	if err != nil {
		os.Exit(1)
	}
	procForker := forker.New(forker.ProcessData{
		ExecPath: execPath,
		ExecParams: []string{
			"-d",
			"-dbhost", args.DBHost,
			"-dbport", strconv.Itoa(args.DBPort),
			"-dbname", args.DBName,
			"-dbuser", args.DBUser,
			"-dbpassword", args.DBPassword,
			"-loadshift", strconv.Itoa(args.LoadShiftTime),
			"-runshift", strconv.Itoa(args.RunShiftTime),
		},
		StdoutPath: "/dev/null",
		StderrPath: "/dev/null",
		Detached:   true,
	})
	_, err = procForker.StartNewProcess()
	if err != nil {
		fmt.Println("ERROR")
		return err
	}
	return nil
}
