package cli

import (
	"context"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"runtime"
	"strings"

	"github.com/spf13/cobra"

	"github.com/aoagents/agent-orchestrator/backend/internal/agentlaunch"
)

func newLaunchCommand(ctx *commandContext) *cobra.Command {
	return &cobra.Command{
		Use:    "launch",
		Short:  "Launch an AO-managed agent process (internal)",
		Hidden: true,
		Args:   noArgs,
		RunE: func(cmd *cobra.Command, _ []string) error {
			return ctx.launchAgent(cmd.Context())
		},
	}
}

func (c *commandContext) launchAgent(ctx context.Context) error {
	specPath := strings.TrimSpace(os.Getenv(agentlaunch.EnvSpecPath))
	if specPath == "" {
		return errors.New("launch: AO_LAUNCH_SPEC is required")
	}
	spec, err := agentlaunch.ReadAndRemove(specPath)
	if err != nil {
		return fmt.Errorf("launch: %w", err)
	}

	env := withoutLaunchSpecEnv(os.Environ())
	launchErr := c.runLaunchCommand(ctx, spec.WorkspacePath, spec.Argv, env)
	if len(spec.FallbackArgv) == 0 {
		return launchErr
	}
	if launchErr != nil {
		_, _ = fmt.Fprintf(c.deps.Err, "\r\n[ao launch] agent process exited: %v\r\n", launchErr)
	}
	return c.runLaunchCommand(ctx, spec.WorkspacePath, spec.FallbackArgv, env)
}

func (c *commandContext) runLaunchCommand(ctx context.Context, dir string, argv, env []string) error {
	if len(argv) == 0 {
		return errors.New("launch: command argv is required")
	}
	cmd := exec.CommandContext(ctx, argv[0], argv[1:]...)
	cmd.Dir = dir
	cmd.Env = env
	cmd.Stdin = c.deps.In
	cmd.Stdout = c.deps.Out
	cmd.Stderr = c.deps.Err
	return cmd.Run()
}

func withoutLaunchSpecEnv(env []string) []string {
	cleaned := env[:0]
	for _, pair := range env {
		key, _, ok := strings.Cut(pair, "=")
		if !ok {
			cleaned = append(cleaned, pair)
			continue
		}
		if envKeyEqual(key, agentlaunch.EnvSpecPath) {
			continue
		}
		cleaned = append(cleaned, pair)
	}
	return cleaned
}

func envKeyEqual(a, b string) bool {
	if runtime.GOOS == "windows" {
		return strings.EqualFold(a, b)
	}
	return a == b
}
