package monitor

import (
	"log"
	"sync"
	"time"

	"github.com/cynfo/rmm-backend/db"
	"github.com/cynfo/rmm-backend/models"
)

// Monitor prueft periodisch den Agent-Status und schreibt Events bei Statuswechsel
type Monitor struct {
	db           *db.Database
	lastStatus   map[string]string
	lastStatusMu sync.Mutex
	interval     time.Duration
}

// New erstellt einen neuen Monitor
func New(database *db.Database) *Monitor {
	return &Monitor{
		db:         database,
		lastStatus: make(map[string]string),
		interval:   60 * time.Second,
	}
}

// Run startet den Monitor als Goroutine — blockiert, also mit go aufrufen
func (m *Monitor) Run() {
	log.Println("Inaktivitaets-Monitor gestartet (Intervall: 60s)")

	// Initialen Status laden
	m.checkAgents()

	ticker := time.NewTicker(m.interval)
	defer ticker.Stop()

	for range ticker.C {
		m.checkAgents()
	}
}

func (m *Monitor) checkAgents() {
	agents, err := m.db.GetAgents()
	if err != nil {
		log.Printf("Monitor: Fehler beim Laden der Agents: %v", err)
		return
	}

	m.lastStatusMu.Lock()
	defer m.lastStatusMu.Unlock()

	for _, agent := range agents {
		newStatus := models.CalculateAgentStatus(agent.LastHeartbeat)
		oldStatus, known := m.lastStatus[agent.ID]

		if !known {
			// Erster Check — Status merken, kein Event
			m.lastStatus[agent.ID] = newStatus
			log.Printf("Monitor: Agent %s (%s) initialer Status: %s", agent.Name, agent.ID, newStatus)
			continue
		}

		if oldStatus == newStatus {
			continue
		}

		// Statuswechsel erkannt
		log.Printf("Monitor: Agent %s (%s) Status-Wechsel: %s -> %s", agent.Name, agent.ID, oldStatus, newStatus)
		m.lastStatus[agent.ID] = newStatus

		// Event schreiben
		message := "Status-Wechsel: " + oldStatus + " -> " + newStatus
		m.db.InsertAgentEvent(agent.ID, newStatus, message)
	}
}
