package exploit

import (
	"context"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

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

func TestPathTraversalSpec_Shape(t *testing.T) {
	spec, err := PathTraversalSpec("https://t/view?page=home", "page", "")
	if err != nil {
		t.Fatal(err)
	}
	if spec.Indicator != lfiIndicator {
		t.Errorf("indicator = %q, want %q", spec.Indicator, lfiIndicator)
	}
	if !strings.Contains(spec.BaseRequest, "page="+verify.DefaultMarker) {
		t.Errorf("param not marked: %q", spec.BaseRequest)
	}
	if strings.ContainsAny(spec.AttackPayload, " ") {
		t.Errorf("attack payload must be query-encoded: %q", spec.AttackPayload)
	}
}

func TestPathTraversalSpec_RejectsEmptyParam(t *testing.T) {
	if _, err := PathTraversalSpec("https://t/x", "", ""); err == nil {
		t.Error("empty param should be rejected")
	}
}

// End to end: an endpoint that returns the requested file's contents leaks
// /etc/passwd for the traversal payload but not for the benign control.
func TestPathTraversalSpec_ProvesViaDifferentialOracle(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		p := r.URL.Query().Get("page") // already percent-decoded
		w.WriteHeader(200)
		if strings.Contains(p, "etc/passwd") {
			_, _ = w.Write([]byte("root:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\n"))
			return
		}
		_, _ = w.Write([]byte("<html>welcome</html>"))
	}))
	defer srv.Close()

	spec, err := PathTraversalSpec(srv.URL+"/view?page=x", "page", "")
	if err != nil {
		t.Fatal(err)
	}
	v, _, proof, err := oracle.NewDifferential(oracle.LiveDiffProbe(srv.Client())).
		Probe(context.Background(), verify.Candidate{Target: srv.URL, Spec: spec})
	if err != nil || v != verify.Proven {
		t.Fatalf("verdict=%v err=%v proof=%q, want proven", v, err, proof)
	}
	if !strings.Contains(proof, lfiIndicator) {
		t.Errorf("proof should cite the %q indicator: %q", lfiIndicator, proof)
	}
}
