package api

import (
	"bytes"
	"log"
	"path/filepath"
	"strings"
	"testing"

	"gitea.dooplex.hu/admin/felhom-hub/internal/store"
	_ "modernc.org/sqlite"
)

func TestRecoveryCredential_VaultSelfScopedAndOperatorRetrieval(t *testing.T) {
	h, st, _ := newTestHandler(t)
	st.UpsertHost(&store.Host{HostID: "h1", CustomerID: "c1", APIKey: "HKEY"})
	st.UpsertHost(&store.Host{HostID: "h2", CustomerID: "c1", APIKey: "HKEY2"})

	body := `{"username":"root@pam","password":"Str0ng-Break-Glass"}`

	// self-scoped write: h1's key vaults h1 → 200
	if rr := do(h, "PUT", "/hosts/h1/recovery-credential", "HKEY", body); rr.Code != 200 {
		t.Fatalf("self vault = %d: %s", rr.Code, rr.Body.String())
	}
	// a host key CANNOT vault ANOTHER host → 403
	if rr := do(h, "PUT", "/hosts/h1/recovery-credential", "HKEY2", body); rr.Code != 403 {
		t.Fatalf("cross-host vault must be 403, got %d", rr.Code)
	}
	// unauthenticated → 401
	if rr := do(h, "PUT", "/hosts/h1/recovery-credential", "", body); rr.Code != 401 {
		t.Fatalf("unauth vault must be 401, got %d", rr.Code)
	}

	// operator retrieval requires the GLOBAL key; a host key is refused (401 — can't read its own back)
	if rr := do(h, "GET", "/admin/hosts/h1/recovery-credential", "HKEY", ""); rr.Code != 401 {
		t.Fatalf("host key reading recovery credential must be 401, got %d", rr.Code)
	}
	rr := do(h, "GET", "/admin/hosts/h1/recovery-credential", globalKey, "")
	if rr.Code != 200 {
		t.Fatalf("operator retrieval = %d: %s", rr.Code, rr.Body.String())
	}
	if !strings.Contains(rr.Body.String(), "Str0ng-Break-Glass") || !strings.Contains(rr.Body.String(), "root@pam") {
		t.Fatalf("retrieval must return the vaulted credential, got %s", rr.Body.String())
	}
	// a host with no credential → 404
	if rr := do(h, "GET", "/admin/hosts/h2/recovery-credential", globalKey, ""); rr.Code != 404 {
		t.Fatalf("no-credential host must be 404, got %d", rr.Code)
	}
}

// SECRET DISCIPLINE (red-proof for trap 3): the password must NEVER appear in the hub log — on the
// vault write NOR the operator retrieval. Companion: if a handler logged the password, this fails.
func TestRecoveryCredential_PasswordNeverLogged(t *testing.T) {
	var buf bytes.Buffer
	path := filepath.Join(t.TempDir(), "test.db")
	st, err := store.New(path, log.New(&buf, "", 0))
	if err != nil {
		t.Fatalf("store.New: %v", err)
	}
	defer st.Close()
	h := New(st, globalKey, "", "", nil, log.New(&buf, "", 0))
	st.UpsertHost(&store.Host{HostID: "h1", CustomerID: "c1", APIKey: "HKEY"})

	const secret = "SuperSecret-DoNotLog-42"
	if rr := do(h, "PUT", "/hosts/h1/recovery-credential", "HKEY", `{"username":"root@pam","password":"`+secret+`"}`); rr.Code != 200 {
		t.Fatalf("vault = %d", rr.Code)
	}
	if rr := do(h, "GET", "/admin/hosts/h1/recovery-credential", globalKey, ""); rr.Code != 200 {
		t.Fatalf("retrieve = %d", rr.Code)
	}
	if strings.Contains(buf.String(), secret) {
		t.Fatalf("the recovery password LEAKED into the hub log:\n%s", buf.String())
	}
}
