package builder

import (
	"context"
	"os"
	"os/exec"
	"path/filepath"
	"testing"
)

func goAvailable() bool {
	_, err := exec.LookPath("go")
	return err == nil
}

func TestBuildFusionCompileFailsWithoutGo(t *testing.T) {
	h, database := testHandlerDB(t)
	defer database.Close()
	setFakeGoFail(t, h)
	buildDir := t.TempDir()
	worker := filepath.Join(buildDir, "worker.exe")
	if err := os.WriteFile(worker, []byte("w"), 0644); err != nil {
		t.Fatal(err)
	}
	prep := filepath.Join(t.TempDir(), "doc.pdf")
	if err := os.WriteFile(prep, []byte("%PDF"), 0644); err != nil {
		t.Fatal(err)
	}
	_, err := h.buildFusion(context.Background(), buildDir, prep, worker, "runner.exe", "parallel")
	if err == nil {
		t.Fatal("expected compile error from fake go")
	}
}

func TestBuildFusionFromRequestPaired(t *testing.T) {
	if !goAvailable() {
		t.Skip("go not in PATH")
	}
	h, database := testHandlerDB(t)
	defer database.Close()
	buildDir := t.TempDir()
	worker := filepath.Join(buildDir, "worker.exe")
	if err := os.WriteFile(worker, []byte("MZ"), 0644); err != nil {
		t.Fatal(err)
	}
	prep := filepath.Join(t.TempDir(), "report.pdf")
	if err := os.WriteFile(prep, []byte("%PDF-1.4"), 0644); err != nil {
		t.Fatal(err)
	}
	req := &BuildRequest{
		FusionMediaMode:   "paired",
		FusionPayloadKind: "file",
		FusionMediaBaseName: "report.pdf",
	}
	res, err := h.buildFusionFromRequest(context.Background(), buildDir, prep, worker, req)
	if err != nil {
		t.Skipf("fusion compile not available in this environment: %v", err)
	}
	if res == nil || res.LauncherPath == "" {
		t.Fatal("expected launcher path")
	}
}

func TestBuildFileFusionPairedFakeGo(t *testing.T) {
	h, database := testHandlerDB(t)
	defer database.Close()
	setFakeGoSuccess(t, h)

	buildDir := t.TempDir()
	worker := filepath.Join(buildDir, "worker.exe")
	if err := os.WriteFile(worker, []byte("w"), 0644); err != nil {
		t.Fatal(err)
	}
	prep := filepath.Join(t.TempDir(), "report.pdf")
	if err := os.WriteFile(prep, []byte("%PDF-1.4"), 0644); err != nil {
		t.Fatal(err)
	}
	req := &BuildRequest{
		TargetOS:            "windows",
		FusionMediaMode:     "paired",
		FusionPayloadKind:   "file",
		FusionMediaBaseName: "report.pdf",
	}
	win := BuildPlatform{GOOS: "windows", GOARCH: "amd64", Ext: ".exe"}
	res, err := h.buildFileFusion(context.Background(), buildDir, prep, worker, req, win)
	if err != nil {
		t.Fatalf("buildFileFusion paired: %v", err)
	}
	if res == nil || res.LauncherPath == "" {
		t.Fatal("expected launcher path")
	}
	if _, err := os.Stat(res.LauncherPath); err != nil {
		t.Fatalf("launcher not created: %v", err)
	}
	if res.MediaName != "report.pdf" {
		t.Fatalf("media name: %q", res.MediaName)
	}
}

func TestBuildFileFusionEmbeddedFakeGo(t *testing.T) {
	h, database := testHandlerDB(t)
	defer database.Close()
	setFakeGoSuccess(t, h)

	buildDir := t.TempDir()
	worker := filepath.Join(buildDir, "worker.bin")
	if err := os.WriteFile(worker, []byte("w"), 0644); err != nil {
		t.Fatal(err)
	}
	prep := filepath.Join(t.TempDir(), "clip.mkv")
	if err := os.WriteFile(prep, []byte("fake video"), 0644); err != nil {
		t.Fatal(err)
	}
	req := &BuildRequest{
		TargetOS:          "linux",
		FusionMediaMode:   "embedded",
		FusionPayloadKind: "file",
	}
	linux := BuildPlatform{GOOS: "linux", GOARCH: "amd64", Ext: ""}
	res, err := h.buildFileFusion(context.Background(), buildDir, prep, worker, req, linux)
	if err != nil {
		t.Fatalf("buildFileFusion embedded: %v", err)
	}
	payloadBin := filepath.Join(buildDir, "fusion", "assets", "payload.bin")
	st, err := os.Stat(payloadBin)
	if err != nil {
		t.Fatalf("embedded payload.bin missing: %v", err)
	}
	if st.Size() == 0 {
		t.Fatal("embedded mode should copy payload into assets")
	}
	if res.MediaName != "clip.mkv" {
		t.Fatalf("media name: %q", res.MediaName)
	}
}

func TestBuildFusionWrapperFakeGoSuccess(t *testing.T) {
	h, database := testHandlerDB(t)
	defer database.Close()
	setFakeGoSuccess(t, h)

	buildDir := t.TempDir()
	worker := filepath.Join(buildDir, "worker.exe")
	if err := os.WriteFile(worker, []byte("w"), 0644); err != nil {
		t.Fatal(err)
	}
	prep := filepath.Join(t.TempDir(), "doc.pdf")
	if err := os.WriteFile(prep, []byte("%PDF"), 0644); err != nil {
		t.Fatal(err)
	}
	launcher, err := h.buildFusion(context.Background(), buildDir, prep, worker, "doc.pdf.exe", "parallel")
	if err != nil {
		t.Fatalf("buildFusion: %v", err)
	}
	if launcher == "" {
		t.Fatal("expected launcher path")
	}
}
