package guesthook

import (
	"context"
	"testing"

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

type fakeReasserter struct {
	invoked  int
	rearmed  []string
	rearmErr error
	results  []storage.NetReassertResult
}

func (f *fakeReasserter) ReassertNetworkAutomounts(context.Context) []storage.NetReassertResult {
	f.invoked++
	return f.results
}

func (f *fakeReasserter) RearmNetworkAutomount(_ context.Context, where string) error {
	f.rearmed = append(f.rearmed, where)
	return f.rearmErr
}

// The post-start core must run the reassert pass and verify guest visibility for every share the
// pass acted on (or found actively mounted) — and never for foreign/errored rows.
func TestPostStartNetworkReassert_Core(t *testing.T) {
	ops := &fakeReasserter{results: []storage.NetReassertResult{
		{Name: "media", Where: "/mnt/felhom-drives/media", Action: storage.NetReassertRearmed},
		{Name: "active", Where: "/mnt/felhom-drives/active", Action: storage.NetReassertSkipActive},
		{Name: "foreign", Where: "/mnt/felhom-drives/foreign", Action: storage.NetReassertSkipForeign},
	}}
	var verified []string
	postStartNetworkReassert(context.Background(), "9201", ops, func(_ context.Context, vmid, path string) bool {
		if vmid != "9201" {
			t.Errorf("verify called with vmid %q, want 9201", vmid)
		}
		verified = append(verified, path)
		return true
	})
	if ops.invoked != 1 {
		t.Fatalf("reassert pass invoked %d times, want 1", ops.invoked)
	}
	if len(verified) != 2 || verified[0] != "/mnt/felhom-drives/media" || verified[1] != "/mnt/felhom-drives/active" {
		t.Fatalf("verify must cover rearmed + skip-active only, got %v", verified)
	}
}

// F11 matrix-correction: a guest that does NOT see a share (even a skip-active one) must trigger a
// re-arm of that specific share, then a re-verify. Encodes the live 2026-07-12 finding that a rebooted
// guest inherits neither an idle trigger nor an active mount.
func TestPostStartNetworkReassert_RearmsWhenGuestBlind(t *testing.T) {
	ops := &fakeReasserter{results: []storage.NetReassertResult{
		{Name: "media", Where: "/mnt/felhom-drives/media", Action: storage.NetReassertSkipActive},
	}}
	// sees: false the first time (blind), true the second (post-rearm) — the heal path.
	calls := 0
	postStartNetworkReassert(context.Background(), "9201", ops, func(context.Context, string, string) bool {
		calls++
		return calls >= 2
	})
	if len(ops.rearmed) != 1 || ops.rearmed[0] != "/mnt/felhom-drives/media" {
		t.Fatalf("a blind guest must trigger exactly one re-arm of the share, got %v", ops.rearmed)
	}
}

// A failed verify must be non-fatal even if the re-arm also fails: the core returns normally (hook
// exits 0 regardless).
func TestPostStartNetworkReassert_VerifyFailureNonFatal(t *testing.T) {
	ops := &fakeReasserter{
		rearmErr: context.DeadlineExceeded,
		results: []storage.NetReassertResult{
			{Name: "media", Where: "/mnt/felhom-drives/media", Action: storage.NetReassertRearmed},
		},
	}
	// Must not panic or abort; the WARNING goes to stderr (PVE task log). Guest never sees it, re-arm errors.
	postStartNetworkReassert(context.Background(), "9201", ops, func(context.Context, string, string) bool {
		return false
	})
	if ops.invoked != 1 {
		t.Fatalf("reassert pass invoked %d times, want 1", ops.invoked)
	}
	if len(ops.rearmed) != 1 {
		t.Fatalf("a blind guest must attempt one re-arm, got %d", len(ops.rearmed))
	}
}
