package monitor

import (
	"log"
	"time"

	"gitea.dooplex.hu/admin/felhom-hub/internal/store"
)

// budapest returns the Europe/Budapest timezone (cached).
var budapest *time.Location

func init() {
	var err error
	budapest, err = time.LoadLocation("Europe/Budapest")
	if err != nil {
		// Fallback: UTC+1 (CET base; DST handled by OS if available)
		budapest = time.FixedZone("CET", 3600)
	}
}

// CheckBackupDeadlines checks whether active customers had their expected
// daily backups and DB dumps. Runs once daily at 05:00 Budapest time.
//
// For each active customer, it checks for backup_completed and db_dump_completed
// events since Budapest midnight. If neither success nor failure events exist,
// it inserts expected_backup_missed / expected_dbdump_missed events.
//
// Customers whose nodes are "down" (no report in >1h) are skipped — they
// already have staleness events.
func CheckBackupDeadlines(s *store.Store, staleness *StalenessChecker, onEvent EventNotifyFunc, logger *log.Logger) {
	customerIDs, err := s.GetActiveCustomerIDs()
	if err != nil {
		logger.Printf("[WARN] Deadline check: failed to get active customers: %v", err)
		return
	}

	// Budapest midnight today
	now := time.Now().In(budapest)
	midnightBudapest := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, budapest)
	sinceUTC := midnightBudapest.UTC()

	var backupMissed, dbdumpMissed, skipped int

	for _, id := range customerIDs {
		// Skip nodes that are down — they already have staleness events
		if staleness != nil && staleness.GetState(id) == "down" {
			skipped++
			continue
		}

		// Check blocked
		if s.IsCustomerBlocked(id) {
			continue
		}

		// Check backup_completed / backup_failed since midnight
		backupOK, _ := s.GetEventsByType(id, "backup_completed", sinceUTC)
		backupFailed, _ := s.GetEventsByType(id, "backup_failed", sinceUTC)
		if len(backupOK) == 0 && len(backupFailed) == 0 {
			msg := "No backup completed or failed since midnight"
			if _, err := s.SaveEvent(id, "expected_backup_missed", "error", msg, "{}", "hub"); err != nil {
				logger.Printf("[WARN] Failed to save expected_backup_missed for %s: %v", id, err)
			} else if onEvent != nil {
				onEvent(id, "expected_backup_missed", "error", msg, "{}", "hub")
			}
			backupMissed++
		}

		// Check db_dump_completed / db_dump_failed since midnight
		dumpOK, _ := s.GetEventsByType(id, "db_dump_completed", sinceUTC)
		dumpFailed, _ := s.GetEventsByType(id, "db_dump_failed", sinceUTC)
		if len(dumpOK) == 0 && len(dumpFailed) == 0 {
			msg := "No DB dump completed or failed since midnight"
			if _, err := s.SaveEvent(id, "expected_dbdump_missed", "error", msg, "{}", "hub"); err != nil {
				logger.Printf("[WARN] Failed to save expected_dbdump_missed for %s: %v", id, err)
			} else if onEvent != nil {
				onEvent(id, "expected_dbdump_missed", "error", msg, "{}", "hub")
			}
			dbdumpMissed++
		}
	}

	logger.Printf("[INFO] Deadline check: %d customers, %d backup missed, %d dbdump missed, %d skipped (down)",
		len(customerIDs), backupMissed, dbdumpMissed, skipped)
}
