package escrow

import (
	"bytes"
	"context"
	"os/exec"
	"runtime"
	"testing"
)

func ageAvailable() bool {
	if runtime.GOOS != "linux" {
		return false
	}
	if _, err := exec.LookPath("age"); err == nil {
		return true
	}
	return false
}

func ensureAge(t *testing.T) {
	t.Helper()
	if !ageAvailable() {
		t.Skip("skipping: the `age` CLI + linux required (runs on the demo/build host)")
	}
	if p, err := exec.LookPath("age"); err == nil {
		ageBinary = p
	}
}

func TestIdentity_InputValidation(t *testing.T) {
	ctx := context.Background()
	if _, err := WrapIdentity(ctx, nil, "R"); err == nil {
		t.Error("empty bundle must error")
	}
	if _, err := WrapIdentity(ctx, []byte("x"), ""); err == nil {
		t.Error("empty R must error")
	}
	if _, err := UnwrapIdentity(ctx, nil, "R"); err == nil {
		t.Error("empty blob must error")
	}
}

// Round-trip: a bundle wraps under R and recovers byte-identical (the identity analog of K-escrow).
func TestIdentity_RoundTrip(t *testing.T) {
	ensureAge(t)
	ctx := context.Background()
	const R = "throwaway-correct-horse-battery-staple-words"
	bundle := IdentityBundle{TunnelToken: "eyJhIjoidGVzdCIsInQiOiJ4In0", PBSToken: "felhom@pbs!n100:deadbeefcafe"}

	blob, err := WrapIdentityBundle(ctx, bundle, R)
	if err != nil {
		t.Fatalf("WrapIdentityBundle: %v", err)
	}
	// the blob is opaque ciphertext, not the bundle.
	if bytes.Contains(blob, []byte(bundle.TunnelToken)) || bytes.Contains(blob, []byte(bundle.PBSToken)) {
		t.Fatal("the blob leaks plaintext token bytes — not encrypted")
	}
	got, err := UnwrapIdentityBundle(ctx, blob, R)
	if err != nil {
		t.Fatalf("UnwrapIdentityBundle: %v", err)
	}
	if got != bundle {
		t.Errorf("recovered bundle = %+v, want %+v", got, bundle)
	}
}

// Wrong R fails CLOSED — no bundle emitted.
func TestIdentity_WrongRFailsClosed(t *testing.T) {
	ensureAge(t)
	ctx := context.Background()
	blob, err := WrapIdentity(ctx, []byte(`{"tunnel_token":"a","pbs_token":"b"}`), "the-correct-code")
	if err != nil {
		t.Fatalf("WrapIdentity: %v", err)
	}
	if _, err := UnwrapIdentity(ctx, blob, "DEFINITELY-the-wrong-code"); err == nil {
		t.Fatal("a wrong recovery code must fail closed (no bundle)")
	}
	// the blob is unchanged / retryable: the RIGHT code still works after a wrong attempt.
	if _, err := UnwrapIdentity(ctx, blob, "the-correct-code"); err != nil {
		t.Errorf("the blob was not retryable after a wrong-R attempt: %v", err)
	}
}
