package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"metis/pkg/sentinel"
)

var fatalf = log.Fatalf

func main() {
	interval := time.Duration(getenvInt("METIS_SENTINEL_INTERVAL_SEC", 300)) * time.Second
	pushURL := os.Getenv("METIS_SENTINEL_PUSH_URL")
	runOnce := os.Getenv("METIS_SENTINEL_RUN_ONCE") == "1"

	for {
		snap := sentinel.Collect()
		enc := json.NewEncoder(os.Stdout)
		enc.SetIndent("", "  ")
		if err := enc.Encode(snap); err != nil {
			fatalf("encode: %v", err)
		}
		if out := os.Getenv("METIS_SENTINEL_OUT"); out != "" {
			writeHistory(out, snap)
		}
		if pushURL != "" {
			if err := pushSnapshot(pushURL, snap); err != nil {
				log.Printf("push snapshot failed: %v", err)
			}
		}
		if runOnce || pushURL == "" {
			break
		}
		time.Sleep(interval)
	}
}

func writeHistory(path string, snap *sentinel.Snapshot) {
	if path == "" {
		return
	}
	if err := os.MkdirAll(path, 0o755); err != nil {
		return
	}
	ts := time.Now().UTC().Format("20060102T150405Z")
	b, _ := json.MarshalIndent(snap, "", "  ")
	_ = os.WriteFile(filepath.Join(path, "snapshot-"+ts+".json"), b, 0o644)
}

func pushSnapshot(url string, snap *sentinel.Snapshot) error {
	payload := map[string]any{
		"node":         snap.Hostname,
		"collected_at": time.Now().UTC(),
		"snapshot":     snap,
	}
	body, err := json.Marshal(payload)
	if err != nil {
		return err
	}
	req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(body))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode >= 300 {
		return fmt.Errorf("push snapshot: %s", resp.Status)
	}
	return nil
}

func getenvInt(key string, fallback int) int {
	if raw := os.Getenv(key); raw != "" {
		if value, err := strconv.Atoi(raw); err == nil {
			return value
		}
	}
	return fallback
}
