// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package ffx

import (
	"context"
	"errors"
	"fmt"
	"io/fs"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"go.fuchsia.dev/fuchsia/src/connectivity/network/testing/conformance/util"
	"go.fuchsia.dev/fuchsia/tools/lib/ffxutil"
	"go.fuchsia.dev/fuchsia/tools/lib/jsonutil"
)

const (
	PERM_USER_READ_WRITE_EXECUTE uint32 = 0700
)

type FfxInstance struct {
	outputDir string
	// If true, outputDir should be cleaned up
	// when FfxInstance is closed.
	iOwnOutputDir bool
	mu            struct {
		isClosed bool
		sync.Mutex
	}
	*ffxutil.FFXInstance
}

// Options for creating an FfxInstance.
type FfxInstanceOptions struct {
	// The Target for invocations of FFXInstance.RunWithTarget().
	// Empty string means no target is specified.
	Target string
	// The directory in which the isolated FFX config and daemon socket for this
	// instance should live. Empty string means that a random temp dir should be
	// created, and removed on FfxInstance.Close().
	TestOutputDir string
	// The path to the ffx binary. Empty string means that the default ffx
	// binary in the host out directory will be used.
	FfxBinPath string
}

// GetFfxPath returns the absolute path to the ffx binary.
func GetFfxPath() (string, error) {
	hostToolsDir, err := util.GetHostToolsDirectory()
	if err != nil {
		return "", fmt.Errorf("GetHostToolsDirectory() = %w", err)
	}
	return filepath.Join(hostToolsDir, "ffx"), nil
}

// NewFfxInstance returns a ffxutil.FFXInstance that executes against a
// QemuInstance running on the same machine.
func NewFfxInstance(
	ctx context.Context,
	options FfxInstanceOptions,
) (*FfxInstance, error) {
	ffx := options.FfxBinPath
	if ffx == "" {
		path, err := GetFfxPath()
		if err != nil {
			return nil, fmt.Errorf("getFfxPath() = %w", err)
		}
		ffx = path
	}

	fmt.Printf("os.Environ() = %s\n", os.Environ())

	wrapperFfxInstance := FfxInstance{outputDir: options.TestOutputDir}

	if wrapperFfxInstance.outputDir == "" {
		dir, err := os.MkdirTemp("", "ffx-instance-dir-*")
		if err != nil {
			return nil, fmt.Errorf(
				"os.MkdirTemp(\"\", \"ffx-instance-dir-*\") = %w",
				err,
			)
		}
		wrapperFfxInstance.outputDir = dir
		wrapperFfxInstance.iOwnOutputDir = true
	}

	// Configure the ssh keys to be created in the ffx instance dir
	sshKey := filepath.Join(wrapperFfxInstance.outputDir, "ssh_keys", "ssh_private_key")
	sshAuthKey := filepath.Join(wrapperFfxInstance.outputDir, "ssh_keys", "ssh_auth_keys")

	sdkRoot := filepath.Join(wrapperFfxInstance.outputDir, "sdk")

	if err := os.MkdirAll(sdkRoot, fs.FileMode(PERM_USER_READ_WRITE_EXECUTE)); err != nil {
		return nil, fmt.Errorf(
			"os.MkdirAll(%q, _) = %w",
			sdkRoot,
			err,
		)
	}

	sdkManifestFilePath := filepath.Join(sdkRoot, ffxutil.SDKManifestPath)
	if err := os.MkdirAll(filepath.Dir(sdkManifestFilePath), fs.FileMode(PERM_USER_READ_WRITE_EXECUTE)); err != nil {
		return nil, fmt.Errorf(
			"os.MkdirAll(%q, _) = %w",
			sdkManifestFilePath,
			err,
		)
	}

	hostOutDir, err := util.GetHostOutDirectory()
	if err != nil {
		return nil, fmt.Errorf("util.GetHostOutDirectory() = %w", err)
	}

	// We need to give FFX an SDK manifest that tells it where the `symbolizer`
	// tool is as required by `ffx log`.
	//
	// While the easiest thing to do would be to just point it at the root build
	// directory and tell it to use the real in-tree SDK there, this makes it
	// possible to have it work at desk without having it work in infra due to
	// differences in whether the SDK is "ambiently available" to a host test.
	//
	// To make it easier to debug this the same way at-desk and in infra runs, we
	// instead create our own SDK definition in a temporary directory that
	// explicitly lists all the tools we're making use of. That way we can be sure
	// that we've provided all the right dependencies via `host_test_data`.
	//
	// Most of this manifest JSON is cargo-culted from a very similar thing that
	// the FFX self-tests do in src/developer/ffx/plugins/self-test/src/log.rs
	// (as of commit 6e7a16d197a7d3b3a40d4110394e38bdf51092de).
	if err := jsonutil.WriteToFile(sdkManifestFilePath, map[string]any{
		"atoms": []map[string]any{
			{
				"category": "partner",
				"deps":     []string{},
				"files": []map[string]any{
					{
						"destination": "tools/x64/symbolizer",
						"source":      filepath.Join(hostOutDir, "symbolizer"),
					},
					{
						"destination": "tools/x64/symbolizer-meta.json",
						"source":      filepath.Join(hostOutDir, "gen/tools/symbolizer/sdk.meta.json"),
					},
				},
				"gn-label": "//tools/symbolizer:sdk(//build/toolchain:host_x64)",
				"id":       "sdk://tools/x64/symbolizer",
				"meta":     "tools/x64/symbolizer-meta.json",
				"plasa":    []string{},
				"type":     "host_tool",
			},
		},
	}); err != nil {
		return nil, err
	}

	ffxInstance, err :=
		ffxutil.NewFFXInstance(
			ctx,
			ffx,
			// "dir" is the current directory of any subprocesses spun off by the
			// FFXInstance.
			/* dir= */
			"",
			// NewFFXInstance automatically inherits the current process's
			// os.Environ(), so we don't need to pass it in here.
			/* env= */
			[]string{},
			/* target= */ options.Target,
			sshKey,
			wrapperFfxInstance.outputDir)
	if err != nil {
		return nil, fmt.Errorf("ffxutil.NewFFXInstance(..) = %w", err)
	}
	wrapperFfxInstance.FFXInstance = ffxInstance

	if err := wrapperFfxInstance.SetLogLevel(ctx, ffxutil.Warn); err != nil {
		return nil, fmt.Errorf("wrapperFfxInstance.SetLogLevel(%q) = %w", ffxutil.Warn, err)
	}

	cfgs := map[string]string{
		"sdk.root": sdkRoot,
		"sdk.type": "in-tree",
		"ssh.pub":  sshAuthKey,
	}

	for key, value := range cfgs {
		if err := wrapperFfxInstance.ConfigSet(ctx, key, value); err != nil {
			return nil, fmt.Errorf(
				"wrapperFfxInstance.ConfigSet(_, %q, %q) = %w",
				key,
				value,
				err,
			)
		}
	}

	fmt.Printf("====== Choosing FFX target: %s ======\n", options.Target)
	return &wrapperFfxInstance, nil
}

func (f *FfxInstance) IsClosed() bool {
	f.mu.Lock()
	defer f.mu.Unlock()

	return f.mu.isClosed
}

func (f *FfxInstance) Close() error {
	f.mu.Lock()
	defer f.mu.Unlock()

	f.mu.isClosed = true

	err := f.Stop()
	if f.iOwnOutputDir {
		err = errors.Join(err, os.RemoveAll(f.outputDir))
	}

	if errors.Is(err, context.DeadlineExceeded) {
		// ffxutil sometimes returns a context.DeadlineExceeded error when stopping an FFXInstance when
		// the ffx daemon takes too long to shut down. This isn't really an actionable error, so it
		// makes sense to swallow it here.
		return nil
	}
	return err
}

const ffxIsolateDirKey = "FFX_ISOLATE_DIR="

func (f *FfxInstance) FfxIsolateDir() (string, error) {
	for _, envPair := range f.Env() {
		if strings.HasPrefix(envPair, ffxIsolateDirKey) {
			return envPair[len(ffxIsolateDirKey):], nil
		}
	}
	return "", fmt.Errorf("no FFX_ISOLATE_DIR in (%#v).Env()", f)
}

func (ffxInstance *FfxInstance) WaitUntilTargetIsAccessible(
	ctx context.Context,
	nodename string,
) error {
	if err := ffxInstance.TargetWait(ctx); err != nil {
		return fmt.Errorf(
			"Error while doing `ffx -t %s target wait`: %w",
			nodename,
			err,
		)
	}
	return nil
}

// CreateStdoutStderrTempFiles creates new files within the FfxInstance's output directory to write
// ffx's stdout and stderr to, returning the stdout and stderr files. The caller has
// responsibility for closing the os.Files returned.
func (f *FfxInstance) CreateStdoutStderrTempFiles() (*os.File, *os.File, error) {
	stdout, err := ioutil.TempFile(f.outputDir, "ffx-stdout-*.log")
	if err != nil {
		return nil, nil, err
	}

	stderr, err := ioutil.TempFile(f.outputDir, "ffx-stderr-*.log")
	if err != nil {
		return nil, nil, errors.Join(err, stdout.Close())
	}

	f.SetStdoutStderr(stdout, stderr)
	return stdout, stderr, nil
}
