package oracle

import (
	"net/http"
	"testing"
	"time"

	"github.com/Armur-Ai/Pentest-Swarm-AI/internal/swarm/verify"
)

func names(oracles []verify.Oracle) []string {
	out := make([]string, len(oracles))
	for i, o := range oracles {
		out[i] = o.Name()
	}
	return out
}

func TestBuildLive_FullSet(t *testing.T) {
	got := names(BuildLive(&fakeSession{}, http.DefaultClient, Options{OOBWindow: time.Second}))
	want := []string{"oob-callback", "differential-response", "timing"}
	if len(got) != 3 {
		t.Fatalf("got %v, want 3 oracles", got)
	}
	for i := range want {
		if got[i] != want[i] {
			t.Errorf("oracle[%d] = %q, want %q", i, got[i], want[i])
		}
	}
}

func TestBuildLive_NoSessionSkipsOOB(t *testing.T) {
	got := names(BuildLive(nil, http.DefaultClient, Options{}))
	for _, n := range got {
		if n == "oob-callback" {
			t.Fatal("OOB oracle should be skipped without a session")
		}
	}
	if len(got) != 2 {
		t.Errorf("got %v, want differential+timing", got)
	}
}

func TestBuildLive_NoDoerSkipsHTTP(t *testing.T) {
	got := names(BuildLive(&fakeSession{}, nil, Options{}))
	if len(got) != 1 || got[0] != "oob-callback" {
		t.Errorf("got %v, want only oob-callback", got)
	}
}

func TestBuildLive_Empty(t *testing.T) {
	if got := BuildLive(nil, nil, Options{}); len(got) != 0 {
		t.Errorf("got %v, want no oracles", got)
	}
}

// Every oracle in a live set is spec-gated: none applies to a bare candidate.
func TestBuildLive_AllSpecGated(t *testing.T) {
	oracles := BuildLive(&fakeSession{}, http.DefaultClient, Options{})
	bare := verify.Candidate{Type: "CVE_MATCH", Detail: "blind sqli ssrf idor timing"} // keywords that WOULD trip defaults
	for _, o := range oracles {
		if o.Applies(bare) {
			t.Errorf("%s applied to a spec-less candidate — live oracles must require a recipe", o.Name())
		}
	}
}
