package rosa

import (
	"path/filepath"
	"slices"
	"strings"

	"hakurei.app/internal/pkg"
)

func (t Toolchain) newCMake() (pkg.Artifact, string) {
	const (
		version  = "4.3.2"
		checksum = "6QylwRVKletndTSkZTV2YBRwgd_9rUVgav_QW23HpjUgV21AVYZOUOal8tdBDmO7"
	)
	return t.NewPackage("cmake", version, newFromGitHubRelease(
		"Kitware/CMake",
		"v"+version,
		"cmake-"+version+".tar.gz",
		checksum,
		pkg.TarGzip,
	), &PackageAttr{
		// test suite expects writable source tree
		Writable: true,

		// expected to be writable in the copy made during bootstrap
		Chmod: true,

		Patches: []KV{
			{"bootstrap-test-no-openssl", `diff --git a/Tests/BootstrapTest.cmake b/Tests/BootstrapTest.cmake
index 137de78bc1..b4da52e664 100644
--- a/Tests/BootstrapTest.cmake
+++ b/Tests/BootstrapTest.cmake
@@ -9,7 +9,7 @@ if(NOT nproc EQUAL 0)
 endif()
 message(STATUS "running bootstrap: ${bootstrap} ${ninja_arg} ${parallel_arg}")
 execute_process(
-  COMMAND ${bootstrap} ${ninja_arg} ${parallel_arg}
+  COMMAND ${bootstrap} ${ninja_arg} ${parallel_arg} -- -DCMAKE_USE_OPENSSL=OFF
   WORKING_DIRECTORY "${bin_dir}"
   RESULT_VARIABLE result
   )
`},

			{"disable-broken-tests-musl", `diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 2ead810437..f85cbb8b1c 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -384,7 +384,6 @@ if(BUILD_TESTING)
     add_subdirectory(CMakeLib)
   endif()
   add_subdirectory(CMakeOnly)
-  add_subdirectory(RunCMake)
 
   add_subdirectory(FindPackageModeMakefileTest)
 
@@ -528,9 +527,6 @@ if(BUILD_TESTING)
                                  -DCMake_TEST_CUDA:BOOL=${CMake_TEST_CUDA}
                                  -DCMake_INSTALL_NAME_TOOL_BUG:BOOL=${CMake_INSTALL_NAME_TOOL_BUG}
                                  )
-  ADD_TEST_MACRO(ExportImport ExportImport)
-  set_property(TEST ExportImport APPEND
-    PROPERTY LABELS "CUDA")
   ADD_TEST_MACRO(Unset Unset)
   ADD_TEST_MACRO(PolicyScope PolicyScope)
   ADD_TEST_MACRO(EmptyLibrary EmptyLibrary)
@@ -624,7 +620,6 @@ if(BUILD_TESTING)
   # run test for BundleUtilities on supported platforms/compilers
   if((MSVC OR
       MINGW OR
-      CMAKE_SYSTEM_NAME MATCHES "Linux" OR
       CMAKE_SYSTEM_NAME MATCHES "Darwin")
     AND NOT CMAKE_GENERATOR STREQUAL "Watcom WMake")
 
@@ -3095,10 +3090,6 @@ if(BUILD_TESTING)
     "${CMake_SOURCE_DIR}/Tests/CTestTestFdSetSize/test.cmake.in"
     "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/test.cmake"
     @ONLY ESCAPE_QUOTES)
-  add_test(CTestTestFdSetSize ${CMAKE_CTEST_COMMAND}
-    -S "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/test.cmake" -j20 -V --timeout 120
-    --output-log "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/testOutput.log"
-    )
 
   if(CMAKE_TESTS_CDASH_SERVER)
     set(regex "^([^:]+)://([^/]+)(.*)$")
`},
		},
	}, &MakeHelper{
		OmitDefaults: true,

		ConfigureName: "/usr/src/cmake/bootstrap",
		Configure: []KV{
			{"prefix", "/system"},
			{"parallel", jobsE},
			{"--"},
			{"-DCMAKE_USE_OPENSSL", "OFF"},
			{"-DCMake_TEST_NO_NETWORK", "ON"},
		},
		Check: []string{
			"CTEST_OUTPUT_ON_FAILURE=1",
			"CTEST_PARALLEL_LEVEL=128",
			"test",
		},
	},
		KernelHeaders,
	), version
}
func init() {
	artifactsM[CMake] = Metadata{
		f: Toolchain.newCMake,

		Name:        "cmake",
		Description: "cross-platform, open-source build system",
		Website:     "https://cmake.org/",

		ID: 306,
	}
}

// CMakeHelper is the [CMake] build system helper.
type CMakeHelper struct {
	// Path elements joined with source.
	Append []string

	// Value of CMAKE_BUILD_TYPE. The zero value is equivalent to "Release".
	BuildType string
	// CMake CACHE entries.
	Cache []KV
	// Runs after install.
	Script string

	// Replaces the default test command.
	Test string
	// Whether to skip running tests.
	SkipTest bool

	// Whether to generate Makefile instead.
	Make bool
}

var _ Helper = new(CMakeHelper)

// extra returns a hardcoded slice of [CMake] and [Ninja].
func (attr *CMakeHelper) extra(int) P {
	if attr != nil && attr.Make {
		return P{CMake, Make}
	}
	return P{CMake, Ninja}
}

// wantsChmod returns false.
func (*CMakeHelper) wantsChmod() bool { return false }

// wantsWrite returns false.
func (*CMakeHelper) wantsWrite() bool { return false }

// scriptEarly returns the zero value.
func (*CMakeHelper) scriptEarly() string { return "" }

// createDir returns true.
func (*CMakeHelper) createDir() bool { return true }

// wantsDir returns a hardcoded, deterministic pathname.
func (*CMakeHelper) wantsDir() string { return "/cure/" }

// script generates the cure script.
func (attr *CMakeHelper) script(name string) string {
	if attr == nil {
		attr = new(CMakeHelper)
	}

	generate := "Ninja"
	test := "ninja " + jobsFlagE + " test"
	if attr.Make {
		generate = "'Unix Makefiles'"
		test = "make " + jobsFlagE + " test"
	}
	if attr.Test != "" {
		test = attr.Test
	}

	script := attr.Script
	if !attr.SkipTest && presetOpts&OptSkipCheck == 0 {
		script += "\n" + test
	}

	cache := make([]KV, 1, 1+len(attr.Cache))
	cache[0] = KV{"CMAKE_BUILD_TYPE", "Release"}
	if attr.BuildType != "" {
		cache[0][1] = attr.BuildType
	}
	cache = append(cache, attr.Cache...)

	return `
cmake -G ` + generate + ` \
	-DCMAKE_C_COMPILER_TARGET="${ROSA_TRIPLE}" \
	-DCMAKE_CXX_COMPILER_TARGET="${ROSA_TRIPLE}" \
	-DCMAKE_ASM_COMPILER_TARGET="${ROSA_TRIPLE}" \
	-DCMAKE_INSTALL_LIBDIR=lib \
	` + strings.Join(slices.Collect(func(yield func(string) bool) {
		for _, v := range cache {
			if !yield("-D" + v[0] + "=" + v[1]) {
				return
			}
		}
	}), " \\\n\t") + ` \
	-DCMAKE_INSTALL_PREFIX=/system \
	'/usr/src/` + name + `/` + filepath.Join(attr.Append...) + `'
cmake --build . --parallel=` + jobsE + `
cmake --install . --prefix=/work/system
` + script
}
