package internal

import (
	"errors"
	"path/filepath"
	"testing"
)

func TestSafeJoinWithinRoot(t *testing.T) {
	root := t.TempDir()
	got, err := SafeJoin(root, "folder/file.txt")
	if err != nil {
		t.Fatalf("SafeJoin failed: %v", err)
	}
	want := filepath.Join(root, "folder", "file.txt")
	if got != want {
		t.Fatalf("SafeJoin mismatch got=%q want=%q", got, want)
	}
}

func TestSafeJoinRejectsEscape(t *testing.T) {
	root := t.TempDir()
	if _, err := SafeJoin(root, "../etc/passwd"); err == nil {
		t.Fatalf("expected escape rejection")
	}
}

func TestSafeJoinAllowsRoot(t *testing.T) {
	root := t.TempDir()
	got, err := SafeJoin(root, "")
	if err != nil {
		t.Fatalf("SafeJoin root failed: %v", err)
	}
	if got != root {
		t.Fatalf("expected root path %q got %q", root, got)
	}
}

func TestSafeJoinAbsError(t *testing.T) {
	origAbs := absPath
	defer func() { absPath = origAbs }()

	absPath = func(string) (string, error) {
		return "", errors.New("boom")
	}

	if _, err := SafeJoin(t.TempDir(), "child"); err == nil {
		t.Fatalf("expected abs-path error")
	}
}

func TestSafeJoinRejectsSiblingPrefix(t *testing.T) {
	origAbs := absPath
	defer func() { absPath = origAbs }()

	absPath = func(p string) (string, error) {
		switch p {
		case "/root":
			return "/root", nil
		case "/root/child":
			return "/rootx/child", nil
		default:
			return p, nil
		}
	}

	if _, err := SafeJoin("/root", "child"); err == nil {
		t.Fatalf("expected sibling-prefix rejection")
	}
}

func TestSafeJoinRejectsRootAbsError(t *testing.T) {
	origAbs := absPath
	defer func() { absPath = origAbs }()

	absPath = func(p string) (string, error) {
		if p == "/root" {
			return "", errors.New("root failed")
		}
		return p, nil
	}

	if _, err := SafeJoin("/root", "child"); err == nil {
		t.Fatalf("expected root abs-path error")
	}
}
