package main

// Bootstrap test for issue 0006a/c: under enforce, membershipd must still reach
// JetStream on its OWN embedded server to create the nonce/KV buckets. It does so
// with an ephemeral internal identity the authenticator grants full permissions
// (NewNkeyAuthenticatorACLInternal). These tests prove that privileged
// self-connection works AND that no other identity can claim it.

import (
	"context"
	"encoding/hex"
	"net"
	"testing"
	"time"

	cs "fn-registry/functions/cybersecurity"

	"github.com/enmanuel/unibus/pkg/busauth"
	"github.com/enmanuel/unibus/pkg/embeddednats"
	"github.com/nats-io/nats.go"
	"github.com/nats-io/nats.go/jetstream"
)

func icFreePort(t *testing.T) int {
	t.Helper()
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("free port: %v", err)
	}
	defer l.Close()
	return l.Addr().(*net.TCPAddr).Port
}

// TestInternalConnPrivilegedUnderEnforce: with an enforce authenticator that
// authorizes NO bus user, the internal identity still connects in-process and has
// full permissions — it creates a KV bucket and round-trips a value. This is the
// resolution of the bootstrap cycle the audit flagged as the reason the KV store
// was never wired.
func TestInternalConnPrivilegedUnderEnforce(t *testing.T) {
	internalID, err := cs.GenerateIdentity()
	if err != nil {
		t.Fatalf("internal identity: %v", err)
	}
	internalPubHex := hex.EncodeToString(internalID.SignPub)

	// Authenticator: no bus user is authorized; only the internal identity passes.
	auth := busauth.NewNkeyAuthenticatorACLInternal(
		func(string) bool { return false },
		busauth.PermissionsFromSubjects(func(string) ([]string, error) { return []string{"_INBOX.>"}, nil }),
		internalPubHex,
	)
	ns, err := embeddednats.StartServer(embeddednats.ServerConfig{
		StoreDir: t.TempDir(), Host: "127.0.0.1", Port: icFreePort(t), Auth: auth,
	})
	if err != nil {
		t.Fatalf("nats: %v", err)
	}
	t.Cleanup(func() { ns.Shutdown(); ns.WaitForShutdown() })

	nc, js, err := connectInternalJS(ns, internalID, true /*useNkey*/)
	if err != nil {
		t.Fatalf("connectInternalJS: %v", err)
	}
	t.Cleanup(nc.Close)

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	kv, err := js.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: "KV_UNIBUS_test", Replicas: 1})
	if err != nil {
		t.Fatalf("internal conn could not create KV bucket (full perms expected): %v", err)
	}
	if _, err := kv.Put(ctx, "k", []byte("v")); err != nil {
		t.Fatalf("kv put: %v", err)
	}
	e, err := kv.Get(ctx, "k")
	if err != nil || string(e.Value()) != "v" {
		t.Fatalf("kv get: val=%q err=%v", e, err)
	}
}

// TestInternalConnOutsiderRejected: an identity that is neither the internal one
// nor an allowlisted bus user cannot connect — proving the internal bypass is
// scoped to the exact internal key, not a blanket hole.
func TestInternalConnOutsiderRejected(t *testing.T) {
	internalID, err := cs.GenerateIdentity()
	if err != nil {
		t.Fatalf("internal identity: %v", err)
	}
	auth := busauth.NewNkeyAuthenticatorACLInternal(
		func(string) bool { return false },
		busauth.PermissionsFromSubjects(func(string) ([]string, error) { return []string{"_INBOX.>"}, nil }),
		hex.EncodeToString(internalID.SignPub),
	)
	ns, err := embeddednats.StartServer(embeddednats.ServerConfig{
		StoreDir: t.TempDir(), Host: "127.0.0.1", Port: icFreePort(t), Auth: auth,
	})
	if err != nil {
		t.Fatalf("nats: %v", err)
	}
	t.Cleanup(func() { ns.Shutdown(); ns.WaitForShutdown() })

	outsider, err := cs.GenerateIdentity()
	if err != nil {
		t.Fatalf("outsider identity: %v", err)
	}
	pub, sign, err := busauth.ClientNkey(outsider.SignPriv)
	if err != nil {
		t.Fatalf("outsider nkey: %v", err)
	}
	conn, err := nats.Connect(ns.ClientURL(),
		nats.Nkey(pub, sign),
		nats.MaxReconnects(0),
		nats.Timeout(2*time.Second),
	)
	if err == nil {
		conn.Close()
		t.Fatalf("outsider (unauthorized, non-internal) must be rejected, but connected")
	}
}
