package daemon

import (
	"testing"

	"banger/internal/model"
	"banger/internal/paths"
)

// TestWireServicesInstantiatesStatsService pins that wireServices
// leaves d.stats non-nil after construction. A wiring-order bug that
// left stats unset would silently break background stats polling and
// the vm.stats / vm.health / vm.ping / vm.ports RPC methods — none
// of those would nil-deref at cold boot because the daemon might
// not get a call for minutes, but the pollStats ticker would
// immediately panic on its first fire.
func TestWireServicesInstantiatesStatsService(t *testing.T) {
	d := &Daemon{
		runner: &permissiveRunner{},
		config: model.DaemonConfig{BridgeIP: model.DefaultBridgeIP},
		layout: paths.Layout{
			StateDir:   t.TempDir(),
			ConfigDir:  t.TempDir(),
			RuntimeDir: t.TempDir(),
			VMsDir:     t.TempDir(),
		},
	}
	wireServices(d)

	if d.stats == nil {
		t.Fatal("d.stats is nil after wireServices")
	}
	// Spot-check the three closures that back every stats method —
	// a nil closure would be a less-obvious wiring regression than
	// a nil service.
	if d.stats.vmAlive == nil {
		t.Fatal("d.stats.vmAlive closure is nil")
	}
	if d.stats.vmHandles == nil {
		t.Fatal("d.stats.vmHandles closure is nil")
	}
	if d.stats.cleanupRuntime == nil {
		t.Fatal("d.stats.cleanupRuntime closure is nil")
	}
	if d.stats.withVMLockByRef == nil {
		t.Fatal("d.stats.withVMLockByRef closure is nil")
	}
	if d.stats.withVMLockByIDErr == nil {
		t.Fatal("d.stats.withVMLockByIDErr closure is nil")
	}
}
