// Copyright The Monogon Project Authors.
// SPDX-License-Identifier: Apache-2.0

package main

import (
	"archive/zip"
	_ "embed"
	"fmt"
	"io"
	"os"
	"path/filepath"

	"github.com/cavaliergopher/cpio"
	"github.com/klauspost/compress/zstd"
	"golang.org/x/sys/unix"
	"google.golang.org/protobuf/proto"

	apb "source.monogon.dev/metropolis/proto/api"
	netapi "source.monogon.dev/osbase/net/proto"

	"source.monogon.dev/osbase/bootparam"
	"source.monogon.dev/osbase/build/mkimage/osimage"
	"source.monogon.dev/osbase/kexec"
	netdump "source.monogon.dev/osbase/net/dump"
	"source.monogon.dev/osbase/structfs"
)

//go:embed third_party/linux/bzImage
var kernel []byte

//go:embed third_party/ucode.cpio
var ucode []byte

//go:embed initramfs.cpio.zst
var initramfs []byte

// newMemfile creates a new file which is not located on a specific filesystem,
// but is instead backed by anonymous memory.
func newMemfile(name string, flags int) (*os.File, error) {
	fd, err := unix.MemfdCreate(name, flags)
	if err != nil {
		return nil, fmt.Errorf("memfd_create failed: %w", err)
	}
	return os.NewFile(uintptr(fd), name), nil
}

func writeCPIO(w io.Writer, root structfs.Tree) error {
	cpioW := cpio.NewWriter(w)
	for path, node := range root.Walk() {
		switch {
		case node.Mode.IsDir():
			err := cpioW.WriteHeader(&cpio.Header{
				Name: "/" + path,
				Mode: cpio.TypeDir | (cpio.FileMode(node.Mode) & cpio.ModePerm),
			})
			if err != nil {
				return err
			}
		case node.Mode.IsRegular():
			err := cpioW.WriteHeader(&cpio.Header{
				Name: "/" + path,
				Size: node.Content.Size(),
				Mode: cpio.TypeReg | (cpio.FileMode(node.Mode) & cpio.ModePerm),
			})
			if err != nil {
				return err
			}
			content, err := node.Content.Open()
			if err != nil {
				return fmt.Errorf("cpio write %q: %w", path, err)
			}
			_, err = io.Copy(cpioW, content)
			content.Close()
			if err != nil {
				return fmt.Errorf("cpio write %q: %w", path, err)
			}
		default:
			return fmt.Errorf("cpio write %q: unsupported file type %s", path, node.Mode.Type().String())
		}
	}
	return cpioW.Close()
}

func setupTakeover(nodeParamsRaw []byte, target string) ([]string, error) {
	// Validate we are running via EFI.
	if _, err := os.Stat("/sys/firmware/efi"); os.IsNotExist(err) {
		//nolint:ST1005
		return nil, fmt.Errorf("Monogon OS can only be installed on EFI-booted machines, this one is not")
	}

	currPath, err := os.Executable()
	if err != nil {
		return nil, err
	}

	bundleBlob, err := structfs.OSPathBlob(filepath.Join(filepath.Dir(currPath), "bundle.zip"))
	if err != nil {
		return nil, err
	}

	bundleRaw, err := bundleBlob.Open()
	if err != nil {
		return nil, err
	}
	defer bundleRaw.Close()
	bundle, err := zip.NewReader(bundleRaw.(io.ReaderAt), bundleBlob.Size())
	if err != nil {
		return nil, fmt.Errorf("failed to open node bundle: %w", err)
	}

	// Dump the current network configuration
	netconf, warnings, err := netdump.Dump()
	if err != nil {
		return nil, fmt.Errorf("failed to dump network configuration: %w", err)
	}

	if len(netconf.Nameserver) == 0 {
		netconf.Nameserver = []*netapi.Nameserver{{
			Ip: "8.8.8.8",
		}, {
			Ip: "1.1.1.1",
		}}
	}

	var params apb.NodeParameters
	if err := proto.Unmarshal(nodeParamsRaw, &params); err != nil {
		return nil, fmt.Errorf("failed to unmarshal node parameters: %w", err)
	}

	// Override the NodeParameters.NetworkConfig with the current NetworkConfig
	// if it's missing.
	if params.NetworkConfig == nil {
		params.NetworkConfig = netconf
	}

	// Marshal NodeParameters again.
	nodeParamsRaw, err = proto.Marshal(&params)
	if err != nil {
		return nil, fmt.Errorf("failed marshaling: %w", err)
	}

	oParams, err := setupOSImageParams(bundle, nodeParamsRaw, target)
	if err != nil {
		return nil, err
	}

	// Validate that this installation will not fail because of disk issues
	if _, err := osimage.Plan(oParams); err != nil {
		return nil, fmt.Errorf("failed to plan installation: %w", err)
	}

	// Load data from embedded files into memfiles as the kexec load syscall
	// requires file descriptors.
	kernelFile, err := newMemfile("kernel", 0)
	if err != nil {
		return nil, fmt.Errorf("failed to create kernel memfile: %w", err)
	}
	initramfsFile, err := newMemfile("initramfs", 0)
	if err != nil {
		return nil, fmt.Errorf("failed to create initramfs memfile: %w", err)
	}
	if _, err := kernelFile.Write(kernel); err != nil {
		return nil, fmt.Errorf("failed to write kernel into memory-backed file: %w", err)
	}
	if _, err := initramfsFile.Write(ucode); err != nil {
		return nil, fmt.Errorf("failed to write ucode into memory-backed file: %w", err)
	}
	if _, err := initramfsFile.Write(initramfs); err != nil {
		return nil, fmt.Errorf("failed to write initramfs into memory-backed file: %w", err)
	}

	// Append this executable, the bundle and node params to initramfs
	self, err := structfs.OSPathBlob("/proc/self/exe")
	if err != nil {
		return nil, err
	}
	root := structfs.Tree{
		structfs.File("init", self, structfs.WithPerm(0o755)),
		structfs.File("params.pb", structfs.Bytes(nodeParamsRaw)),
		structfs.File("bundle.zip", bundleBlob),
	}
	compressedW, err := zstd.NewWriter(initramfsFile, zstd.WithEncoderLevel(1))
	if err != nil {
		return nil, fmt.Errorf("while creating zstd writer: %w", err)
	}
	err = writeCPIO(compressedW, root)
	if err != nil {
		return nil, err
	}
	err = compressedW.Close()
	if err != nil {
		return nil, err
	}

	initParams := bootparam.Params{
		bootparam.Param{Param: "quiet"},
		bootparam.Param{Param: launchModeEnv, Value: launchModeInit},
		bootparam.Param{Param: EnvInstallTarget, Value: target},
		bootparam.Param{Param: "init", Value: "/init"},
	}

	var customConsoles bool
	cmdline, err := os.ReadFile("/proc/cmdline")
	if err != nil {
		warnings = append(warnings, fmt.Errorf("unable to read current kernel command line: %w", err))
	} else {
		params, _, err := bootparam.Unmarshal(string(cmdline))
		// If the existing command line is well-formed, add all existing console
		// parameters to the console for the agent
		if err == nil {
			for _, p := range params {
				if p.Param == "console" {
					initParams = append(initParams, p)
					customConsoles = true
				}
			}
		}
	}
	if !customConsoles {
		// Add the "default" console on x86
		initParams = append(initParams, bootparam.Param{Param: "console", Value: "ttyS0,115200"})
	}
	agentCmdline, err := bootparam.Marshal(initParams, "")
	if err != nil {
		return nil, fmt.Errorf("failed to marshal bootparams: %w", err)
	}
	// Stage agent payload into kernel memory
	if err := kexec.FileLoad(kernelFile, initramfsFile, agentCmdline); err != nil {
		return nil, fmt.Errorf("failed to load kexec payload: %w", err)
	}
	var warningsStrs []string
	for _, w := range warnings {
		warningsStrs = append(warningsStrs, w.Error())
	}
	return warningsStrs, nil
}
