package main

import (
	"fmt"
	"os"
	"slices"
	"strings"

	"tobi/internal/app"
	"tobi/internal/remote"
	"tobi/internal/session"
)

func main() {
	if err := dispatch(os.Args[1:]); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

const usage = `tobi - persistent terminals across your devices

usage:
  tobi                   attach to a session with the fuzzy selector
  tobi <query>           attach using fuzzy search (tobi hx, tobi host.id)
  tobi <target> -- cmd   spawn cmd in a session on target

target is [user@][host.]id and host is optional, so tobi .id -- nu creates a
local session with that id. the daemon detaches when the terminal window
closes and detached sessions are cleaned up after 24h. sessions are
reachable from any device on the tailscale network by running tobi. tobi
doesn't nest: running it inside a tobi session replaces it.

requires tssh (or ssh) and tailscale in PATH.
`

func dispatch(args []string) error {
	switch op := os.Getenv("TOBI_RPC"); {
	case os.Getenv("TOBI_COMPLETE") == "1":
		return app.Complete(strings.Join(args, " "))
	case os.Getenv("TOBI_OWNER") == "1":
		id := os.Getenv("TOBI_ID")
		for _, k := range []string{"TOBI_OWNER", "TOBI_ID", "TOBI_RPC", "TOBI_COMPLETE"} {
			os.Unsetenv(k)
		}
		return wrapErr("owner", session.RunOwner(id, args))
	case op != "":
		return wrapErr("rpc "+op, remote.RunRPC(op, os.Getenv("TOBI_ID")))
	}
	if len(args) > 0 && (args[0] == "--help" || args[0] == "-h") {
		fmt.Print(usage)
		return nil
	}
	if i := slices.Index(args, "--"); i != -1 {
		return app.Spawn(strings.Join(args[:i], " "), args[i+1:])
	}
	return app.Interactive(strings.Join(args, " "))
}

func wrapErr(prefix string, err error) error {
	if err != nil {
		return fmt.Errorf("%s: %w", prefix, err)
	}
	return nil
}
