package rosa

import (
	"slices"
	"strings"

	"hakurei.app/internal/pkg"
)

func (t Toolchain) newPython() (pkg.Artifact, string) {
	const (
		version  = "3.14.5"
		checksum = "zYIpDlk2ftZ-UVGCQS1rthle2OHoyXV653ztWiopKV1NhmIJf1K2hHbkwM4DozQ9"
	)
	return t.NewPackage("python", version, newTar(
		"https://www.python.org/ftp/python/"+version+
			"/Python-"+version+".tgz",
		checksum,
		pkg.TarGzip,
	), &PackageAttr{
		// test_synopsis_sourceless assumes this is writable and checks __pycache__
		Writable: true,
		Chmod:    true,

		Patches: []KV{
			{"zipfile-no-default-strict_timestamps", `diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py
index 19aea290b58..51603ba9510 100644
--- a/Lib/zipfile/__init__.py
+++ b/Lib/zipfile/__init__.py
@@ -617,7 +617,7 @@ def _decodeExtra(self, filename_crc):
             extra = extra[ln+4:]
 
     @classmethod
-    def from_file(cls, filename, arcname=None, *, strict_timestamps=True):
+    def from_file(cls, filename, arcname=None, *, strict_timestamps=False):
         """Construct an appropriate ZipInfo for a file on the filesystem.
 
         filename should be the path to a file or directory on the filesystem.
@@ -1412,7 +1412,7 @@ class ZipFile:
     _windows_illegal_name_trans_table = None
 
     def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=True,
-                 compresslevel=None, *, strict_timestamps=True, metadata_encoding=None):
+                 compresslevel=None, *, strict_timestamps=False, metadata_encoding=None):
         """Open the ZIP file with mode read 'r', write 'w', exclusive create 'x',
         or append 'a'."""
         if mode not in ('r', 'w', 'x', 'a'):
`},
		},

		Env: []string{
			"EXTRATESTOPTS=-j0 -x " + strings.Join([]string{
				// requires internet access (http://www.pythontest.net/)
				"test_asyncio",
				"test_socket",
				"test_urllib2",
				"test_urllibnet",
				"test_urllib2net",

				// makes assumptions about uid_map/gid_map
				"test_os",
				"test_subprocess",

				// patched out insane strict_timestamps default
				"test_zipfile",

				// requires gcc
				"test_ctypes",

				// breaks on llvm
				"test_dbm_gnu",
			}, " -x "),

			// _ctypes appears to infer something from the linker name
			"LDFLAGS=-Wl,--dynamic-linker=/system/lib/" +
				"ld-musl-" + linuxArch() + ".so.1",
		},
	}, &MakeHelper{
		Check: []string{"test"},
	},
		Zlib,
		Bzip2,
		Libffi,
		OpenSSL,

		PkgConfig,
		XZ,
	), version
}
func init() {
	artifactsM[Python] = Metadata{
		f: Toolchain.newPython,

		Name:        "python",
		Description: "the Python programming language interpreter",
		Website:     "https://www.python.org/",

		Dependencies: P{
			Zlib,
			Bzip2,
			Libffi,
			OpenSSL,
		},

		ID: 13254,
	}
}

// PipHelper is the [Python] pip packaging helper.
type PipHelper struct {
	// Path elements joined with source.
	Append []string
	// Whether to omit --no-build-isolation.
	BuildIsolation bool
	// Whether to enter source after install.
	EnterSource bool
	// Whether to install to build environment after install.
	Install bool
	// Whether to skip running tests.
	SkipCheck bool
	// Replaces pytest if non-empty.
	Check string
	// Runs after install.
	Script string
}

var _ Helper = new(PipHelper)

// extra returns python, or pytest if defaults are assumed.
func (attr *PipHelper) extra(int) P {
	if attr == nil || (!attr.SkipCheck && attr.Check == "") {
		return P{PythonPyTest}
	}
	return P{Python}
}

// wantsChmod returns true.
func (*PipHelper) wantsChmod() bool { return true }

// wantsWrite is equivalent to wantsChmod.
func (attr *PipHelper) wantsWrite() bool { return attr.wantsChmod() }

// scriptEarly is a noop.
func (*PipHelper) scriptEarly() string { return "" }

// createDir returns false.
func (*PipHelper) createDir() bool { return false }

// wantsDir requests a new directory in TMPDIR.
func (*PipHelper) wantsDir() string { return `"$(mktemp -d)"` }

// script generates the pip3 install command.
func (attr *PipHelper) script(name string) string {
	if attr == nil {
		attr = new(PipHelper)
	}
	sourcePath := AbsUsrSrc.Append(name).Append(attr.Append...)

	var extra string
	if !attr.BuildIsolation {
		extra += `
	--no-build-isolation \`
	}

	var script string
	if attr.Install {
		script += `pip3 install \
	--no-index \
	--prefix=/system \
	--no-build-isolation \
	'` + sourcePath.String() + `'
`
	}
	if attr.EnterSource {
		script += "cd '/usr/src/" + name + "'\n"
	}
	if !attr.SkipCheck {
		if attr.Check == "" {
			// some test suites fall apart when ran out-of-tree
			script += "(cd '" + sourcePath.String() + "' && pytest)\n"
		} else {
			script += attr.Check
		}
	}
	script += attr.Script

	return `
pip3 install \
	--no-index \
	--prefix=/system \
	--root=/work \` + extra + `
	'` + sourcePath.String() + `'
` + script
}

// newPythonPackage creates [Metadata] for a [Python] package.
func newPythonPackage(
	name string, id int, description, website, version string,
	source pkg.Artifact, attrP *PackageAttr, attr *PipHelper,
	build P, extra ...PArtifact,
) Metadata {
	name = "python-" + name
	return Metadata{
		f: func(t Toolchain) (pkg.Artifact, string) {
			return t.NewPackage(name, version, source, attrP, attr, slices.Concat(
				P{Python},
				extra,
				build,
			)...), version
		},

		Name:        name,
		Description: description,
		Website:     website,

		Dependencies: slices.Concat(P{Python}, extra),

		ID: id,
	}
}

func init() {
	const (
		version  = "0.47.0"
		checksum = "HZ-MvkUP8mbbx2YmsRNswj_bbOCIiXckuHqL5Qbvb5NxN5DYfWnqwkGNyS7OrId0"
	)
	artifactsM[PythonWheel] = newPythonPackage(
		"wheel", 11428,
		"the official binary distribution format for Python",
		"https://peps.python.org/pep-0427/",
		version, newFromGitHub(
			"pypa/wheel",
			version, checksum,
		), nil, &PipHelper{
			Install: true,
		}, P{PythonFlitCore, PythonSetuptools},
	)
}

func init() {
	const (
		version  = "82.0.1"
		checksum = "nznP46Tj539yqswtOrIM4nQgwLA1h-ApKX7z7ghazROCpyF5swtQGwsZoI93wkhc"
	)
	artifactsM[PythonSetuptools] = newPythonPackage(
		"setuptools", 4021,
		"the autotools of the Python ecosystem",
		"https://pypi.org/project/setuptools/",
		version, newFromGitHub(
			"pypa/setuptools",
			"v"+version, checksum,
		), nil, &PipHelper{
			// error: invalid command 'dist_info'
			BuildIsolation: true,
			// pytest circular dependency
			SkipCheck: true,
		}, nil)
}

func init() {
	const (
		version  = "1.1.1"
		checksum = "rXZixTsZcRcIoUC1LvWrjySsiXSv5uhW6ng2P-yXZrbdj7FrSrDeJLCfC2b-ladV"
	)
	artifactsM[PythonVCSVersioning] = newPythonPackage(
		"vcs-versioning", 389421,
		"core VCS versioning functionality extracted as a standalone library",
		"https://setuptools-scm.readthedocs.io/en/latest/",
		version, newFromGitHub(
			"pypa/setuptools-scm",
			"vcs-versioning-v"+version, checksum,
		), &PackageAttr{
			Env: []string{
				"SETUPTOOLS_SCM_PRETEND_VERSION=" + version,
			},
		}, &PipHelper{
			// upstream is monorepo of two packages (setuptools-scm)
			Append: []string{"vcs-versioning"},
			// pytest circular dependency
			SkipCheck: true,
		}, nil,
		PythonSetuptools,
		PythonPackaging,
	)
}

func init() {
	const (
		version  = "10.0.5"
		checksum = "vTN_TPd-b4Wbsw5WmAcsWjrs-FNXXznOeVTDnb54NtXve9Oy-eb2HPy-RG3FzNqp"
	)
	artifactsM[PythonSetuptoolsSCM] = newPythonPackage(
		"setuptools-scm", 7874,
		"extracts Python package versions from Git or Mercurial metadata",
		"https://setuptools-scm.readthedocs.io/en/latest/",
		version, newFromGitHub(
			"pypa/setuptools-scm",
			"setuptools-scm-v"+version, checksum,
		), &PackageAttr{
			Env: []string{
				"SETUPTOOLS_SCM_PRETEND_VERSION=" + version,
			},
		}, &PipHelper{
			// upstream is monorepo of two packages
			Append: []string{"setuptools-scm"},
			// pytest circular dependency
			SkipCheck: true,
		}, nil,
		PythonSetuptools,
		PythonVCSVersioning,
	)
}

func init() {
	const (
		version  = "3.12.0"
		checksum = "VcTsiGiDU1aPLbjSPe38f9OjJDCLcxFz9loObJqUI1ZxDHXAaQMxBpNyLz_G1Rff"
	)
	artifactsM[PythonFlitCore] = newPythonPackage(
		"flit-core", 44841,
		"a PEP 517 build backend for packages using Flit",
		"https://flit.pypa.io/",
		version, newFromGitHub(
			"pypa/flit",
			version, checksum,
		), nil, &PipHelper{
			// upstream has other unused packages with many dependencies
			Append: []string{"flit_core"},
			// pytest circular dependency
			SkipCheck: true,
		}, nil,
	)
}

func init() {
	const (
		version  = "26.2"
		checksum = "rdpGa2EkPFbj1mFtLKLnSwIX9gPfELcuneiICjRVDNw6By49szTFVoW8gtMMZ6ZS"
	)
	artifactsM[PythonPackaging] = newPythonPackage(
		"packaging", 60461,
		"reusable core utilities for various Python Packaging interoperability specifications",
		"https://packaging.pypa.io/",
		version, newFromGitHub(
			"pypa/packaging",
			version, checksum,
		), nil, &PipHelper{
			// pytest circular dependency
			SkipCheck: true,
		}, P{PythonFlitCore},
	)
}

func init() {
	artifactsM[LIT] = Metadata{
		f: func(t Toolchain) (pkg.Artifact, string) {
			version := t.Version(LLVM)
			return t.NewPackage("lit", version, t.Load(llvmSource), nil, &PipHelper{
				Append: []string{"llvm", "utils", "lit"},
				// already checked during llvm
				SkipCheck: true,
			},
				PythonSetuptools,
			), version
		},

		Name:        "lit",
		Description: "a portable tool for executing LLVM and Clang style test suites",
		Website:     "https://llvm.org/docs/CommandGuide/lit.html",

		Dependencies: P{
			Python,
		},
	}
}

func init() {
	const (
		version  = "1.1.1"
		checksum = "1fVwoal6FoKXczoG3qRUi87TxSWESSGcgvnbEZDYuaOgsO25o36iF3SbAhwkr4Va"
	)
	artifactsM[PythonPathspec] = newPythonPackage(
		"pathspec", 23424,
		"utility library for gitignore style pattern matching of file paths",
		"https://github.com/cpburnz/python-pathspec",
		version, newFromGitHub(
			"cpburnz/python-pathspec",
			"v"+version, checksum,
		), nil, &PipHelper{
			// pytest circular dependency
			SkipCheck: true,
		}, P{PythonFlitCore},
	)
}

func init() {
	const (
		version  = "2026.5.7.17"
		checksum = "1Fcps0gK9P4ofwGL8MISN9k1Q40-quxX7NDpIna50TmziBNrZy-0Vz0I9yIeHCoP"
	)
	artifactsM[PythonTroveClassifiers] = newPythonPackage(
		"trove-classifiers", 88298,
		"canonical source for classifiers on PyPI",
		"https://pypi.org/p/trove-classifiers/",
		version, newFromGitHub(
			"pypa/trove-classifiers",
			version, checksum,
		), nil, &PipHelper{
			// pytest circular dependency
			SkipCheck: true,
		}, P{PythonSetuptools},
	)
}

func init() {
	const (
		version  = "1.6.0"
		checksum = "GiUgDkKjF8Xn1cmq6iMhTGXzcPIYeaJrvQpHBSAJapNVx4UyuiTXqd5eVlxSClJu"
	)
	artifactsM[PythonPluggy] = newPythonPackage(
		"pluggy", 7500,
		"the core framework used by the pytest, tox, and devpi projects",
		"https://pluggy.readthedocs.io/en/latest/",
		version, newFromGitHub(
			"pytest-dev/pluggy",
			version, checksum,
		), &PackageAttr{
			Env: []string{
				"SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PLUGGY=" + version,
			},
		}, &PipHelper{
			// pytest circular dependency
			SkipCheck: true,
		}, P{PythonSetuptoolsSCM},
	)
}

func init() {
	const (
		version  = "1.16.5"
		checksum = "V2eREtqZLZeV85yb4O-bfAJCUluHcQP76Qfs0QH5s7RF_Oc8xIP8jD0jl85qFyWk"
	)
	artifactsM[PythonHatchling] = newPythonPackage(
		"hatchling", 16137,
		"the extensible, standards compliant build backend used by Hatch",
		"https://hatch.pypa.io/latest/",
		version, newFromGitHub(
			"pypa/hatch",
			"hatch-v"+version, checksum,
		), nil, &PipHelper{
			// upstream has other unused packages with many dependencies
			Append: []string{"backend"},
			// pytest circular dependency
			SkipCheck: true,
		}, nil,
		PythonPackaging,
		PythonPathspec,
		PythonTroveClassifiers,
		PythonPluggy,
	)
}

func init() {
	const (
		version  = "2.20.0"
		checksum = "L-2P6vn7c_CNZYliE5CJAWLxO1ziDQVVkf8bnZbHj8aSCQ43oWv11wC9KzU9MeCa"
	)
	artifactsM[PythonPygments] = newPythonPackage(
		"pygments", 3986,
		"a syntax highlighting package written in Python",
		"https://pygments.org/",
		version, newFromGitHub(
			"pygments/pygments",
			version, checksum,
		), nil, &PipHelper{
			// pytest circular dependency
			SkipCheck: true,
		}, P{PythonHatchling},
	)
}

func init() {
	const (
		version  = "2.3.0"
		checksum = "mH7VBZaXcYatBPE3RQQZvSzz_Ay8IPPek60NpPHZulPq4ReAFUUsA4EPWfiyMknZ"
	)
	artifactsM[PythonIniConfig] = newPythonPackage(
		"iniconfig", 114778,
		"a small and simple INI-file parser module",
		"https://github.com/pytest-dev/iniconfig",
		version, newFromGitHub(
			"pytest-dev/iniconfig",
			"v"+version, checksum,
		), &PackageAttr{
			Env: []string{
				"SETUPTOOLS_SCM_PRETEND_VERSION_FOR_INICONFIG=" + version,
			},
		}, &PipHelper{
			// pytest circular dependency
			SkipCheck: true,
		}, P{PythonSetuptoolsSCM},
	)
}

func init() {
	const (
		version  = "9.0.3"
		checksum = "qfLL_znWhbJCDbNJvrx9H3-orJ86z4ifhaW0bIn21jl2sDP-FVoX_1yieOypArQe"
	)
	artifactsM[PythonPyTest] = newPythonPackage(
		"pytest", 3765,
		"the pytest framework",
		"https://pytest.org",
		version, newFromGitHub(
			"pytest-dev/pytest",
			version, checksum,
		), &PackageAttr{
			Env: []string{
				"SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST=" + version,
			},
		}, &PipHelper{
			// many dependencies
			SkipCheck: true,
		}, P{PythonSetuptoolsSCM},
		PythonIniConfig,
		PythonPackaging,
		PythonPluggy,
		PythonPygments,
	)
}

func init() {
	const (
		version  = "3.0.3"
		checksum = "txRGYdWE3his1lHHRI-lZADw0-ILvUg2l5OGdFHtFXIb_QowGxwdxHCUSJIgmjQs"
	)
	artifactsM[PythonMarkupSafe] = newPythonPackage(
		"markupsafe", 3918,
		"implements a text object that escapes characters so it is safe to use in HTML and XML",
		"https://markupsafe.palletsprojects.com/",
		version, newFromGitHub(
			"pallets/markupsafe",
			version, checksum,
		), nil, &PipHelper{
			// ModuleNotFoundError: No module named 'markupsafe'
			Install: true,
		}, P{PythonSetuptools},
	)
}

func init() {
	const (
		version  = "1.3.12"
		checksum = "OZbBsQe2MzRuAo5Mr4qRwWHGqU1EEZeBuSprDDIceAtMLIUJtO7SbERlxHIxNhLk"
	)
	artifactsM[PythonMako] = newPythonPackage(
		"mako", 3915,
		"a template library written in Python",
		"https://www.makotemplates.org/",
		version, newFromGitHub(
			"sqlalchemy/mako",
			"rel_"+strings.Join(strings.SplitN(version, ".", 3), "_"),
			checksum,
		), nil, nil, P{PythonSetuptools},
		PythonMarkupSafe,
	)
}

func init() {
	const (
		version  = "6.0.3"
		checksum = "7wDv0RW9chBdu9l5Q4Hun5F2HHdo105ZSIixwdFPKbEYbftW9YxmsegfL-zafnbJ"
	)
	artifactsM[PythonPyYAML] = newPythonPackage(
		"pyyaml", 4123,
		"a YAML parser and emitter for Python",
		"https://pyyaml.org/",
		version, newFromGitHub(
			"yaml/pyyaml",
			version, checksum,
		), nil, &PipHelper{
			// ModuleNotFoundError: No module named 'yaml'
			Install: true,
		}, P{PythonSetuptools},
	)
}

func init() {
	const (
		version  = "3.00"
		checksum = "4qfCMFKp0fLsRsloOAF780tXX_Ce_68RwinCmjNGObAX32WpF_iBafIKW1S1bYlA"
	)
	artifactsM[PythonPycparser] = newPythonPackage(
		"pycparser", 8175,
		"complete C99 parser in pure Python",
		"https://github.com/eliben/pycparser",
		version, newFromGitHub(
			"eliben/pycparser",
			"release_v"+version, checksum,
		), &PackageAttr{
			// test case hard codes gcc
			ScriptEarly: `
ln -s clang /system/bin/gcc
`,
		}, nil, P{PythonSetuptools},
	)
}
