package localapi

import (
	"bytes"
	"net/http"
	"strings"
	"testing"

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

// S7 sweep smoke (agent half): a full fake NAS add at emit level INFO must leave the
// EXPECTED LOG SEQUENCE in the debug ring — this is the test that encodes "an operator
// can reconstruct the NAS flow from the debug view". Companion red-proof: remove any
// one of the asserted phase lines (e.g. the /proc/mounts verdict Debug) → its marker
// is absent → FAIL naming the missing phase.
func TestNetAdd_LogSequenceReconstructsFlow(t *testing.T) {
	logger, ring := applog.NewWithWriter(&bytes.Buffer{}, "info", 200)
	n := &fakeNetOps{}
	srv := newVerifyServer(t, n, t.TempDir(), verifySeams{
		mounted: func(string) bool { return true }, // §8: in /proc/mounts ⇒ verified
	})
	srv.logger = logger // ring-backed capture layer under the whole flow

	body := `{"name":"vids","protocol":"smb","server":"nas","export":"vids","mapped_uid":1000,"mapped_gid":1000,"username":"u","password":"p"}`
	if w := do(t, srv.Handler(), "POST", "/netstorage/add", "A", body); w.Code != http.StatusOK {
		t.Fatalf("add: got %d (%s)", w.Code, w.Body.String())
	}
	final := pollVerify(t, srv.Handler())
	if final["phase"] != netVerifyPhaseDone {
		t.Fatalf("phase = %v, want done", final["phase"])
	}

	lines := ring.Lines(0)
	joined := strings.Join(lines, "\n")
	// The phase markers, in order (each must exist; each must come after the previous).
	sequence := []string{
		"NAS endpoint pre-probe passed",
		"SMB credentials staged",
		"network mount installed",
		"netverify: job started",
		"netverify: /proc/mounts verdict",
		"netverify: mount verified",
	}
	pos := -1
	for _, marker := range sequence {
		idx := indexOfLine(lines, marker, pos+1)
		if idx < 0 {
			t.Fatalf("phase line %q missing (or out of order) — flow not reconstructable.\nring:\n%s", marker, joined)
		}
		pos = idx
	}
	// The secret never appears in any line (creds are path-only).
	if strings.Contains(joined, "password") || strings.Contains(joined, `"p"`) {
		t.Errorf("a credential-looking token leaked into the log ring:\n%s", joined)
	}
}

// indexOfLine finds the first line at or after `from` containing marker; -1 if none.
func indexOfLine(lines []string, marker string, from int) int {
	for i := from; i < len(lines); i++ {
		if strings.Contains(lines[i], marker) {
			return i
		}
	}
	return -1
}
