package main

import (
	"bytes"
	"os/exec"
	"syscall"
	"time"

	"github.com/rs/zerolog/log"
)

var currentConfig config

func main() {
	var err error
	currentConfig, err = ReadFromFile("config.yml")
	if err != nil {
		log.Fatal().Err(err).Msg("Cant read config file")
	}
	log.Debug().Interface("config", currentConfig).Msg("config")

	if len(currentConfig.Jobs) == 0 {
		log.Warn().Msg("config dont include any jobs")
	}
	cronTicker, configTicker := createTickers(realTimeProvider{})

	// Hauptloop mit select
	for {
		select {
		case t := <-cronTicker:
			execucteJobs(t, currentConfig.Jobs)
		case <-configTicker:
			log.Debug().Msg("Reload Config")
			currentConfig, err = ReadFromFile("config.yml")
			if err != nil {
				log.Error().Err(err).Msg("cant read config")
			}
		}
	}
}

func execucteJobs(t time.Time, jobs []jobconfig) {
	for _, job := range jobs {
		execute, err := job.MatchCurrentTime(t)
		log.Debug().Bool("execution", execute).Time("t", t).Msg("check cron execution")
		if err != nil {
			log.Error().Err(err).Msg("cant pars time for job")
		}
		if !execute {
			continue
		}

		go executeCommand(job)
	}
}

func executeCommand(job jobconfig) error {
	l := log.With().Str("name", job.Name).Str("command", job.Command).Logger()
	var output bytes.Buffer
	cmd := exec.Command("bash", "-c", job.Command)
	cmd.Stdout = &output
	cmd.Stderr = &output
	l.Debug().Msg("Start Execution")
	err := cmd.Run()

	outString := output.String()

	exitCode := 0
	if err != nil {
		if exitErr, ok := err.(*exec.ExitError); ok {
			if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
				exitCode = status.ExitStatus()
			}
		} else {
			l.Error().Err(err).Str("output", outString).Msg("Faild Execution")
			return err
		}
	}

	l.Debug().Err(err).Str("output", outString).Int("exitcode", exitCode).Msg("Success Execution")

	return nil
}
