package localapi

import (
	"context"

	"gitea.dooplex.hu/admin/felhom-agent/internal/storage"
)

// networkReasserter is the optional concrete capability of the netStorage surface (satisfied by
// *storage.SudoHostOps). Type-asserted like main.go's ReassertEnrolledMounts so the lean
// NetworkStorageOps interface (and its test fakes) stay unchanged.
type networkReasserter interface {
	ReassertNetworkAutomounts(ctx context.Context) []storage.NetReassertResult
	RearmNetworkAutomount(ctx context.Context, where string) error
}

// ReassertNetworkMounts is the NAS counterpart of ReassertGuestBinds (RCA
// AUDIT-nas-cwa-rca-2026-07-11 fix 1): re-arm every idle network-share automount trigger host-side
// (a fresh trigger-mount event propagates live into running guests' slave binds), then best-effort
// verify each running guest actually sees each share's path. Runs at agent startup (after the
// guest-bind reconcile — covers guests that autostarted before the agent) and from the guest-hook
// post-start phase (its own process; this method is the daemon path). NEVER call this from a
// periodic health path — an idle trigger is healthy and must not be churned.
func (s *Server) ReassertNetworkMounts(ctx context.Context) {
	if s.netStorage == nil {
		return
	}
	r, ok := s.netStorage.(networkReasserter)
	if !ok {
		s.logger.Debug("netreassert: storage surface has no reassert capability — skipping")
		return
	}
	results := r.ReassertNetworkAutomounts(ctx)
	if len(results) == 0 {
		return
	}
	// Best-effort guest-visibility verify (the RCA's masking lesson: host-side health said nothing
	// about what the guests see). Only running guests; a failed verify is a WARN, never an error —
	// the next guest start re-runs the hook path anyway.
	if s.guestBinds == nil || s.guestAttach == nil {
		return
	}
	for vmid := range s.guestBinds.Guests() {
		if s.guestAttach.GuestBootID(ctx, vmid) == "" {
			s.logger.Debug("netreassert: guest not running — visibility verify skipped", "vmid", vmid)
			continue
		}
		for _, res := range results {
			if !res.Remediates() {
				continue // foreign/errored rows expect nothing in the guest
			}
			if s.guestAttach.GuestSeesMount(ctx, vmid, res.Where) {
				s.logger.Debug("netreassert: guest sees network share", "vmid", vmid, "name", res.Name, "where", res.Where)
				continue
			}
			// F11 matrix-correction (2026-07-12): a running guest that does NOT see a share must be
			// remediated — a fresh namespace inherits neither an idle trigger NOR an active mount; only a
			// FRESH trigger event propagates in. Re-arm this share and re-verify once (covers guests that
			// autostarted before the agent).
			r, ok := s.netStorage.(networkReasserter)
			if !ok {
				continue
			}
			s.logger.Warn("netreassert: guest does NOT see network share after reassert — re-arming",
				"vmid", vmid, "name", res.Name, "where", res.Where, "action", res.Action)
			if err := r.RearmNetworkAutomount(ctx, res.Where); err != nil {
				s.logger.Warn("netreassert: re-arm failed", "vmid", vmid, "name", res.Name, "err", err)
				continue
			}
			if s.guestAttach.GuestSeesMount(ctx, vmid, res.Where) {
				s.logger.Info("netreassert: guest sees network share after re-arm (healed)", "vmid", vmid, "name", res.Name, "where", res.Where)
			} else {
				s.logger.Warn("netreassert: guest STILL does not see network share after re-arm", "vmid", vmid, "name", res.Name, "where", res.Where)
			}
		}
	}
}
