package main

import (
	"encoding/json"
	"reflect"
	"sort"
	"testing"
)

// TestEscrowUploadContract pins the agent→hub escrow wire shape. It MUST match the hub's ingest
// struct (felhom-hub api.escrowUploadRequest). Cross-repo, no shared module — this is the agent
// half of the contract guard; the hub has the mirror in its own test.
func TestEscrowUploadContract(t *testing.T) {
	b, _ := json.Marshal(escrowUploadRequest{BlobB64: "x", KeyFingerprint: "y", Posture: "z", CreatedAt: "t", ResticPwSHA256: "h"})
	var m map[string]any
	if err := json.Unmarshal(b, &m); err != nil {
		t.Fatal(err)
	}
	got := make([]string, 0, len(m))
	for k := range m {
		got = append(got, k)
	}
	sort.Strings(got)
	want := []string{"blob_b64", "created_at", "key_fingerprint", "posture", "restic_pw_sha256"}
	if !reflect.DeepEqual(got, want) {
		t.Fatalf("escrow wire contract drift: got %v want %v (must match the hub ingest struct)", got, want)
	}
	// SLICE 3: no staged password folded in → the hash field is OMITTED on the wire (the hub stores NULL →
	// the controller never matches → stays pending; correct — the blob doesn't cover the key).
	b2, _ := json.Marshal(escrowUploadRequest{BlobB64: "x", KeyFingerprint: "y", Posture: "z", CreatedAt: "t"})
	var m2 map[string]any
	_ = json.Unmarshal(b2, &m2)
	if _, present := m2["restic_pw_sha256"]; present {
		t.Fatal("restic_pw_sha256 must be omitted when no staged password was sealed")
	}
}
