package utils

import (
	"bytes"
	"context"
	"crm-api/pkg/lfshook"
	"os/exec"
	"strings"
	"time"
)

// ExecCmdAsync 执行指定命令
func ExecCmdAsync(cmdName string, arg ...string) (stdOut, errOut string, err error) {
	lfshook.NewLogger().Infof("ExecCmdAsync cmd %s %s", cmdName, arg)
	cmd := exec.Command(cmdName, arg...)
	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err = cmd.Run()
	if err != nil {
		lfshook.NewLogger().Errorf("cmd.Run(%s) failed with %s\n", cmdName, err)
	}
	outStr, errStr := stdout.String(), stderr.String()
	if len(outStr) > 0 {
		lfshook.NewLogger().Debugf("cmd.Run(%s) %s", cmdName, outStr)
	}
	if len(errStr) > 0 {
		lfshook.NewLogger().Errorf("cmd.Run(%s)%s", cmdName, errStr)
	}
	return outStr, errStr, err
}

// ExecCmd 执行指定命令
func ExecCmd(cmdName string, arg ...string) (stdOut, errOut string, err error) {
	///etc/scripts/sysinfo.sh 会不断刷新
	if cmdName != "/etc/scripts/sysinfo.sh" {
		lfshook.NewLogger().Infof("ExecCmd cmd %s %s", cmdName, arg)
	}
	cmd := exec.Command(cmdName, arg...)
	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	err = cmd.Start()
	if err != nil {
		lfshook.NewLogger().Error(err)
		return "", "", err
	}

	go func() {
		err = cmd.Wait()
		if err != nil {
			lfshook.NewLogger().Errorf("cmd.Wait(%s) %s\n", cmdName, err)
		}
		cancel()
	}()

	<-ctx.Done()

	outStr, errStr := stdout.String(), stderr.String()
	if len(outStr) > 0 {
		lfshook.NewLogger().Debugf("cmd.Start(%s) %s", cmdName, outStr)
	}
	if len(errStr) > 0 {
		lfshook.NewLogger().Errorf("cmd.Start(%s)%s", cmdName, errStr)
	}
	return strings.TrimSpace(outStr), errStr, err
}

func Reboot(sleep time.Duration) {
	go func() {
		time.Sleep(sleep * time.Second)
		cmd := "/sbin/reboot"
		output, _ := exec.Command("bash", "-c", cmd).CombinedOutput()
		lfshook.NewLogger().Info(cmd)
		lfshook.NewLogger().Info(string(output))
	}()
}

func RunCmd(cmd string) (output []byte, err error) {
	lfshook.NewLogger().Debug(cmd)
	output, err = exec.Command("bash", "-c", cmd).CombinedOutput()
	lfshook.NewLogger().Debug("command res:", string(output), "\n")
	if err != nil {
		lfshook.NewLogger().Error(err)
	}
	return
}
