/*
** 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"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"syscall"

	"jobarranger2/src/libs/golibs/common"
	"jobarranger2/src/libs/golibs/config_reader/server"
	"jobarranger2/src/libs/golibs/logger/logger"
)

// Move multiple files to the destination directory
func moveFiles(eventData common.EventData, logData logger.Logging, filename string) error {
	const fn = "moveFiles"

	fileEntries := eventData.Transfer.Files
	logger.JaLog("JADBSYNCER400004", logData, fn, filename, len(fileEntries))

	var allErr error
	for i, fileEntry := range fileEntries {
		// for the source file
		if i == 0 {
			// modify the data first
			// Remove existing extension
			content, err := json.MarshalIndent(eventData, "", "  ")
			if err != nil {
				logger.JaLog("JADBSYNCER200007", logData, fn, filename, fileEntry.Source, err.Error())
				return err
			}
			logger.JaLog("JADBSYNCER400006", logData, fn, filename, fileEntry.Source)

			// Overwrite the file with new content
			err = os.WriteFile(fileEntry.Source, content, common.FilePermission)
			if err != nil {
				logger.JaLog("JADBSYNCER200008", logData, fn, filename, fileEntry.Source, errMsgWithErrno(err))
				return err
			}
		}

		if fileEntry.Destination == "" {
			logger.JaLog("JADBSYNCER400010", logData, fn, filename, fileEntry.Source)

			endPath := filepath.Join(server.Options.TmpDir, common.DBSyncerManagerFolder, EndFolder, filepath.Base(fileEntry.Source))
			// Remove existing extension
			base := strings.TrimSuffix(endPath, filepath.Ext(endPath))
			endPath = base + ".json"

			// Move the file to end
			err := os.Rename(fileEntry.Source, endPath)
			if err != nil {
				logger.JaLog("JADBSYNCER200006", logData, fn, filename, fileEntry.Source, endPath, errMsgWithErrno(err))
				return err
			}
			logger.JaLog("JADBSYNCER400015", logData, fn, filename, fileEntry.Source, endPath)
			continue
		}

		logger.JaLog("JADBSYNCER400007", logData, fn, filename, fileEntry.Source, fileEntry.Destination)

		if err := os.Rename(fileEntry.Source, fileEntry.Destination); err != nil {
			logger.JaLog("JADBSYNCER200006", logData, fn, filename, fileEntry.Source, fileEntry.Destination, errMsgWithErrno(err))

			errorPath := filepath.Join(server.Options.TmpDir, common.DBSyncerManagerFolder, ErrorFolder, filepath.Base(fileEntry.Source))
			// Remove existing extension
			base := strings.TrimSuffix(errorPath, filepath.Ext(errorPath))
			errorPath = base + ".json"

			// Move the file to error
			renameErr := os.Rename(fileEntry.Source, errorPath)
			if renameErr != nil {
				logger.JaLog("JADBSYNCER200012", logData, fn, filename, fileEntry.Source, errMsgWithErrno(renameErr))
				continue
			}
			allErr = fmt.Errorf("failed to move file: %s", err.Error())
			continue
		}

		logger.JaLog("JADBSYNCER400013", logData, fn, filename, fileEntry.Source, fileEntry.Destination)
	}
	return allErr
}

// Move multiple files to the sub directory of db sycner manager
func moveFilesToDBSyncSubFolder(eventData common.EventData, logData logger.Logging, filename string, subFolder string) {
	const fn = "moveFilesToDBSyncSubFolder"

	fileEntries := eventData.Transfer.Files
	logger.JaLog("JADBSYNCER400004", logData, fn, filename, len(fileEntries))

	for _, fileEntry := range fileEntries {
		// Set the destination to target sub folder
		dest := filepath.Join(server.Options.TmpDir, common.DBSyncerManagerFolder, subFolder, filepath.Base(fileEntry.Source))

		logger.JaLog("JADBSYNCER400007", logData, fn, filename, fileEntry.Source, dest)

		if err := os.Rename(fileEntry.Source, dest); err != nil {
			logger.JaLog("JADBSYNCER200006", logData, fn, filename, fileEntry.Source, dest, errMsgWithErrno(err))

			renamePath := fileEntry.Source + ".error"
			// Rename the file as .error
			renameErr := os.Rename(fileEntry.Source, renamePath)
			if renameErr != nil {
				logger.JaLog("JADBSYNCER200018", logData, fn, filename, fileEntry.Source, errMsgWithErrno(renameErr))
				continue
			}

			logger.JaLog("JADBSYNCER400021", logData, fn, filename, fileEntry.Source, renamePath)
			continue
		}

		logger.JaLog("JADBSYNCER400013", logData, fn, filename, fileEntry.Source, dest)
	}
}

func errMsgWithErrno(err error) string {
	var errno syscall.Errno
	if errors.As(err, &errno) {
		return fmt.Sprintf("%v (errno=%d)", err, errno)
	}

	return fmt.Sprintf("%v (no errno)", err)
}
