package localapi

import (
	"context"
	"io"
	"log/slog"
	"testing"

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

// TestStarttimeFromStat parses field 22 (starttime) from a /proc/<pid>/stat line whose comm contains
// spaces AND an inner ')' — the case naive whitespace-splitting (or split-on-FIRST-')') mis-parses.
//
// COMPANION GUARD: a pre-fix impl that splits the whole line on whitespace reads the wrong field (the
// multi-token comm shifts every index); one that splits on the FIRST ')' splits inside the comm. Both
// return != "9988776655" here.
func TestStarttimeFromStat(t *testing.T) {
	// pid=42, comm="(weird ) name)" (spaces + an inner ')'), state 'S', then fields; field 22 = 9988776655.
	stat := "42 (weird ) name) S 1 42 42 0 -1 4194560 100 0 0 0 5 6 0 0 20 0 1 0 9988776655 12345 67 1 1 1 0 0 0 0\n"
	if got := starttimeFromStat(stat); got != "9988776655" {
		t.Fatalf("starttimeFromStat = %q, want 9988776655 (comm with spaces+')' must not break the parse)", got)
	}
	if got := starttimeFromStat("garbage no parens"); got != "" {
		t.Fatalf("malformed stat should yield \"\", got %q", got)
	}
}

func TestStablePathForRaw_DriveName(t *testing.T) {
	cases := []struct {
		where, name, stable string
	}{
		{"/mnt/felhom-usb", "felhom-usb", "/mnt/felhom-drives/felhom-usb"},
		{"/mnt/felhom-flash", "felhom-flash", "/mnt/felhom-drives/felhom-flash"},
		{"/mnt/felhom-drives/x", "", ""}, // nested (slash in remainder) → not a /mnt/<name> raw mount
		{"/var/lib/vz", "", ""},          // not under /mnt
		{"/mnt/", "", ""},                // empty name
	}
	for _, c := range cases {
		if got := DriveNameFromRaw(c.where); got != c.name {
			t.Errorf("DriveNameFromRaw(%q) = %q, want %q", c.where, got, c.name)
		}
		if got := StablePathForRaw(c.where); got != c.stable {
			t.Errorf("StablePathForRaw(%q) = %q, want %q", c.where, got, c.stable)
		}
	}
}

// TestDisks_GuestPathAndBoundUnderParent asserts the intermediary reporting the controller relies on: a
// user-data drive gets a STABLE guest path (/mnt/felhom-drives/<name>) and BoundUnderParent reflects the
// host mount check; a SYSTEM mount gets neither (it never crosses into the guest).
//
// COMPANION GUARD: a pre-fix impl that left GuestPath empty (no repoint signal) or that reported
// BoundUnderParent ignoring the real mount state would fail the assertions below.
func TestDisks_GuestPathAndBoundUnderParent(t *testing.T) {
	d := &fakeDiskOps{probe: storage.DeviceProbe{Probed: true, HasFilesystem: true, FSType: "ext4"}}
	sv := fakeStorage{targets: []hub.StorageTarget{
		{Name: "usb", Type: hub.StorageTypeUSB, BackingDevice: "/dev/sdb1", MountPath: "/mnt/felhom-usb"},
		{Name: "flash", Type: hub.StorageTypeUSB, BackingDevice: "/dev/sdc1", MountPath: "/mnt/felhom-flash"},
		{Name: "system", Type: "local", MountPath: "/var/lib/vz"}, // system role → no guest path
	}}
	fg := &fakeGuestsCfg{}
	srv, err := NewServer(Options{
		ListenAddr: "127.0.0.1:0", Guests: fg, Backups: &fakeBackups{}, Store: &fakeStore{},
		Storage: sv, Tokens: staticTokens{"A": 8200},
		Disks: d, DiskGate: &fakeGate{}, HostReader: sysOnSDA(),
		Logger: slog.New(slog.NewTextHandler(io.Discard, nil)),
	})
	if err != nil {
		t.Fatal(err)
	}
	srv.baseCtx = context.Background()
	// felhom-usb is bound under the parent; felhom-flash is not.
	srv.boundCheck = func(p string) bool { return p == "/mnt/felhom-drives/felhom-usb" }

	disks := decodeDisks(t, do(t, srv.Handler(), "GET", "/disks", "A", "").Body.Bytes())
	byMount := map[string]DiskInfo{}
	for _, di := range disks {
		byMount[di.MountPath] = di
	}

	if gp := byMount["/mnt/felhom-usb"].GuestPath; gp != "/mnt/felhom-drives/felhom-usb" {
		t.Errorf("usb GuestPath = %q, want /mnt/felhom-drives/felhom-usb", gp)
	}
	if !byMount["/mnt/felhom-usb"].BoundUnderParent {
		t.Errorf("usb should report BoundUnderParent=true (bound under the parent)")
	}
	if byMount["/mnt/felhom-flash"].BoundUnderParent {
		t.Errorf("flash should report BoundUnderParent=false (not bound)")
	}
	if gp := byMount["/mnt/felhom-flash"].GuestPath; gp != "/mnt/felhom-drives/felhom-flash" {
		t.Errorf("flash GuestPath = %q, want /mnt/felhom-drives/felhom-flash", gp)
	}
	// A SYSTEM mount must never get a guest path (it does not cross into the guest).
	if gp := byMount["/var/lib/vz"].GuestPath; gp != "" {
		t.Errorf("system mount GuestPath = %q, want empty (never crosses into the guest)", gp)
	}
}
