//go:build linux

package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"tailscale.com/cmd/mirage-qt/internal/bridge"
)

var (
	bridgeMode       = flag.Bool("bridge", false, "run the LocalAPI bridge")
	bridgeWatch      = flag.Bool("watch", false, "emit a long-lived event stream")
	bridgeAction     = flag.String("action", "", "run a single bridge action and exit")
	actionJSON       = flag.Bool("json", false, "emit JSON for bridge actions")
	actionController = flag.String("controller", "", "controller short code or full URL for bridge actions")
	actionStableID   = flag.String("stable-id", "", "stable node ID for bridge actions")
	actionEnabled    = flag.Bool("enabled", false, "boolean toggle value for bridge actions")
	trayFrontendPath = flag.String("tray-frontend", "", "path to Qt tray frontend binary")
)

func chooseFrontendBinary(explicit string) string {
	bridgeProgram, err := os.Executable()
	if err != nil {
		bridgeProgram = os.Args[0]
	}
	return chooseFrontendBinaryWithBridge(explicit, bridgeProgram)
}

func chooseFrontendBinaryWithBridge(explicit, bridgeProgram string) string {
	sibling := ""
	if bridgeProgram != "" {
		sibling = filepath.Join(filepath.Dir(bridgeProgram), "mirage-qt-ui")
	}
	for _, candidate := range []string{
		strings.TrimSpace(explicit),
		os.Getenv("MIRAGE_QT_FRONTEND"),
		sibling,
		"/usr/libexec/mirage/mirage-qt-ui",
		"/usr/lib/mirage/mirage-qt-ui",
		"mirage-qt-ui",
	} {
		candidate = strings.TrimSpace(candidate)
		if candidate == "" {
			continue
		}
		if strings.Contains(candidate, "/") {
			if _, err := os.Stat(candidate); err == nil {
				return candidate
			}
			continue
		}
		if path, err := exec.LookPath(candidate); err == nil {
			return path
		}
	}
	return ""
}

func runFrontend(app *bridge.App) error {
	frontend := chooseFrontendBinary(*trayFrontendPath)
	if frontend == "" {
		if *trayFrontendPath != "" {
			return fmt.Errorf("Qt tray frontend not found: %s", *trayFrontendPath)
		}
		return errors.New("Qt tray frontend not found; expected mirage-qt-ui in PATH, /usr/libexec/mirage, or /usr/lib/mirage")
	}

	bridgeProgram, err := os.Executable()
	if err != nil {
		bridgeProgram = os.Args[0]
	}

	cmd := exec.Command(frontend)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Env = append(os.Environ(),
		"MIRAGE_BRIDGE_PROGRAM="+bridgeProgram,
		"MIRAGE_SOCKET_PATH="+app.SocketPath(),
		"MIRAGE_CONTROL_DEFAULT="+bridge.DefaultControllerInput,
		"MIRAGE_QT_ROOT="+filepath.Dir(frontend),
	)
	return cmd.Run()
}

func run() error {
	flag.CommandLine.SetOutput(os.Stderr)
	flag.Parse()

	app, err := bridge.NewApp()
	if err != nil {
		return err
	}

	switch {
	case *bridgeWatch:
		if *bridgeAction != "" {
			return errors.New("--watch cannot be combined with --action")
		}
		return app.RunWatch(os.Stdout)
	case *bridgeMode || *bridgeAction != "":
		return app.RunAction(os.Stdout, bridge.ActionRequest{
			Name:            strings.TrimSpace(*bridgeAction),
			JSON:            *actionJSON,
			ControllerInput: strings.TrimSpace(*actionController),
			StableID:        strings.TrimSpace(*actionStableID),
			Enabled:         *actionEnabled,
		})
	default:
		return runFrontend(app)
	}
}

func main() {
	if err := run(); err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}
}
