package alert

import (
	"context"
	"fmt"
	"log/slog"
	"time"

	"gitea.dcglab.co.uk/steve/restic-manager/internal/notification"
)

// Alert-kind constants for P6 self-update flows.
const (
	// KindUpdateFailed is raised when an agent fails to come back with
	// the expected version after a command.update dispatch (timeout or
	// version-mismatch). Resolved by a subsequent matching hello.
	KindUpdateFailed = "update_failed"

	// KindFleetUpdateHalted is raised when the fleet-update worker
	// stops mid-run because a host failed to update or went offline.
	// Host-less alert (system-scoped). Manually resolved by an admin.
	KindFleetUpdateHalted = "fleet_update_halted"
)

// RaiseUpdateFailed records a per-host update failure. dedupKey is the
// hostID so a re-dispatch on the same host touches the existing alert
// rather than spawning a duplicate.
func (e *Engine) RaiseUpdateFailed(ctx context.Context, hostID, jobID, reason string, when time.Time) {
	msg := fmt.Sprintf("Agent update failed (job %s): %s", jobID, reason)
	e.raiseAndNotify(ctx, hostID, KindUpdateFailed, hostID, "warning", msg, when)
}

// ResolveUpdateFailed clears any open update_failed alert for hostID.
// Called from the WS hello path when the agent reconnects with the
// target version.
func (e *Engine) ResolveUpdateFailed(ctx context.Context, hostID string, when time.Time) {
	e.resolveAndNotify(ctx, hostID, KindUpdateFailed, hostID, when)
}

// RaiseFleetUpdateHalted is host-less — the fleet update is a
// system-level concept. We persist it via the dedicated host-less
// alert path so the alerts table's host_id column carries NULL.
func (e *Engine) RaiseFleetUpdateHalted(ctx context.Context, fleetUpdateID, reason string, when time.Time) {
	msg := fmt.Sprintf("Fleet update %s halted: %s", fleetUpdateID, reason)
	id, didRaise, err := e.store.RaiseOrTouchSystem(ctx, KindFleetUpdateHalted, fleetUpdateID, "warning", msg, when)
	if err != nil {
		slog.Warn("alert: raise fleet_update_halted", "fu_id", fleetUpdateID, "err", err)
		return
	}
	if !didRaise {
		return
	}
	go e.hub.Dispatch(ctx, notification.Payload{
		Event:    notification.EventRaised,
		AlertID:  id,
		Severity: "warning",
		Kind:     KindFleetUpdateHalted,
		HostID:   "",
		HostName: "",
		Message:  msg,
		RaisedAt: when,
	})
}
