package main

import (
	"os"
	"path/filepath"
	"time"
)

// installDeps installs the AmneziaWG stack and userspace tooling for the host
// OS, then records completion in the state file. This step is now fully
// decoupled from init-server: it must be run first, and init-server only
// verifies the recorded flag rather than installing anything itself.
func installDeps() {
	os := detectOS()
	info("Installing AmneziaWG dependencies for %s %s...", os.ID, os.Version)

	switch os.ID {
	case "ubuntu", "debian", "linuxmint":
		env := []string{"DEBIAN_FRONTEND=noninteractive"}
		runOrDie2(env, "apt-get", "update", "-qq")
		// Prerequisites for adding the PPA and building the kernel module.
		runOrDie2(env, "apt-get", "install", "-y",
			"software-properties-common", "python3-launchpadlib", "gnupg2",
			"linux-headers-"+unameRelease(), "curl")
		if os.ID == "linuxmint" {
			// Mint's official docs require "Source code repositories" to be
			// enabled (Software Sources → Optional Sources) before adding a
			// PPA; the CLI equivalent is uncommenting the deb-src lines that
			// Mint ships disabled by default.
			run("sed", "-i", "s/^# deb-src/deb-src/",
				"/etc/apt/sources.list.d/official-package-repositories.list")
			runOrDie2(env, "apt-get", "update", "-qq")
		}
		// AmneziaWG kernel module + userspace tools via the official PPA.
		runOrDie2(env, "add-apt-repository", "-y", "ppa:amnezia/ppa")
		runOrDie2(env, "apt-get", "update", "-qq")
		runOrDie2(env, "apt-get", "install", "-y",
			"amneziawg", "amneziawg-tools",
			"jq", "qrencode", "nftables")
	case "alpine":
		runOrDie("apk", "update")
		runOrDie("apk", "add",
			"jq", "libqrencode-tools", "nftables", "curl", "util-linux")
		buildAmneziawgToolsFromSource()
		warn("On Alpine the AmneziaWG kernel module may need to be provided")
		warn("separately (DKMS/akmods or a prebuilt module for your kernel)")
	}

	// Record that dependency installation completed so init-server can verify it.
	saveState(&State{
		DepsInstalled: true,
		InstalledAt:   time.Now().UTC().Format(time.RFC3339),
		OSID:          os.ID,
		OSVersion:     os.Version,
	})

	info("Dependencies installed")
	info("State recorded: %s (deps_installed=true)", stateFile)
	info("Next step: run 'init-server' to configure and start the server")
}

// runOrDie2 is runEnv + abort-on-failure (env-aware variant of runOrDie).
func runOrDie2(env []string, name string, args ...string) {
	if err := runEnv(env, name, args...); err != nil {
		die("%s failed: %v", name, err)
	}
}

// buildAmneziawgToolsFromSource builds and installs `awg`/`awg-quick` on an
// Alpine host. Unlike Ubuntu/Debian/Mint (served by the official
// ppa:amnezia/ppa), amneziawg-tools has no Alpine apk package — the container
// image already builds it from source for exactly this reason (see the
// tools-builder stage in Dockerfile); this mirrors that same build for a bare
// Alpine host.
func buildAmneziawgToolsFromSource() {
	info("No Alpine package exists for amneziawg-tools — building from source...")
	runOrDie("apk", "add", "git", "build-base", "linux-headers", "bash")

	dir, err := os.MkdirTemp("", "amneziawg-tools-*")
	if err != nil {
		die("Failed to create temp build dir: %v", err)
	}
	defer os.RemoveAll(dir)

	runOrDie("git", "clone", "--depth=1",
		"https://github.com/amnezia-vpn/amneziawg-tools", dir)
	src := filepath.Join(dir, "src")
	runOrDieIn(src, "make")
	runOrDieIn(src, "make", "install",
		"WITH_WGQUICK=yes", "WITH_BASHCOMPLETION=no", "WITH_SYSTEMDUNITS=no",
		"PREFIX=/usr")

	info("amneziawg-tools built and installed (awg, awg-quick)")
}
