// Start an Aiden agent chat from a Go backend and stream the reply.
//
// Documented on https://appcd-dev.github.io/stackgen-sdk/code-samples/aiden-chat-backend/
//
//	export STACKGEN_URL=https://app.stackgen.com
//	export STACKGEN_TOKEN=stackgen_…
//	export STACKGEN_WORKSPACE_ID=<workspace-uuid>
//	go run ./examples/go/aiden-chat/agent-chat.go \
//	  -agent my-ops-agent \
//	  -message 'List available data sources without changing anything.'
//
// Use -retry-max to control how many times transient failures (network
// errors, 429, 5xx) are retried with exponential backoff before giving up.
package main

import (
	"context"
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/hashicorp/go-retryablehttp"

	stackgen "github.com/appcd-dev/stackgen-sdk/clients/go"
	"github.com/appcd-dev/stackgen-sdk/clients/go/aiden"
)

func envOr(keys ...string) string {
	for _, key := range keys {
		if v := strings.TrimSpace(os.Getenv(key)); v != "" {
			return v
		}
	}
	return ""
}

func main() {
	baseURL := flag.String("base-url", envOr("STACKGEN_URL", "STACKGEN_BASE_URL"), "Mothership URL")
	apiToken := flag.String("api-token", envOr("STACKGEN_TOKEN", "STACKGEN_API_TOKEN"), "API token")
	orgID := flag.String("workspace-id", envOr("STACKGEN_WORKSPACE_ID", "STACKGEN_PROJECT", "STACKGEN_PROJECT_ID", "STACKGEN_ORG_ID", "ORG_ID"), "Workspace UUID (sent as orgId)")
	flag.StringVar(orgID, "org-id", *orgID, "Deprecated: use -workspace-id")
	agent := flag.String("agent", "", "Agent name to chat with")
	message := flag.String("message", "", "User message for this turn")
	sessionID := flag.String("session-id", "", "Optional session to continue")
	timeoutSeconds := flag.Int("timeout-seconds", 600, "Overall timeout")
	retryMax := flag.Int("retry-max", 4, "Max retries for transient HTTP failures (network errors, 429, 5xx)")
	flag.Parse()

	if strings.TrimSpace(*baseURL) == "" || strings.TrimSpace(*apiToken) == "" || strings.TrimSpace(*orgID) == "" {
		fmt.Fprintln(os.Stderr, "error: set -base-url/-api-token/-workspace-id or STACKGEN_URL/STACKGEN_TOKEN/STACKGEN_WORKSPACE_ID")
		os.Exit(2)
	}
	if strings.TrimSpace(*agent) == "" {
		fmt.Fprintln(os.Stderr, "error: -agent is required")
		os.Exit(2)
	}
	if strings.TrimSpace(*message) == "" {
		fmt.Fprintln(os.Stderr, "error: -message is required")
		os.Exit(2)
	}

	rc := retryablehttp.NewClient()
	rc.RetryMax = *retryMax
	rc.Logger = nil
	httpClient := rc.StandardClient()

	client, err := stackgen.NewClient(stackgen.Config{
		BaseURL:        *baseURL,
		APIToken:       *apiToken,
		WorkspaceID:    *orgID,
		TimeoutSeconds: *timeoutSeconds,
		HTTPClient:     httpClient,
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(*timeoutSeconds)*time.Second)
	defer cancel()

	run, err := client.Aiden.StartAgentChat(ctx, *agent, aiden.StartChatRequest{
		Message:   *message,
		SessionID: strings.TrimSpace(*sessionID),
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	fmt.Fprintf(os.Stderr, "session_id=%s trace_id=%s run_id=%s\n", run.SessionID, run.TraceID, run.RunID)

	err = client.Aiden.SubscribeExecution(ctx, run.TraceID, func(event aiden.ExecutionEvent) error {
		if event.Subagent {
			return nil
		}
		if event.Type == "TEXT_MESSAGE_CONTENT" {
			fmt.Print(event.Text("Content", "content"))
		}
		return nil
	})
	if err != nil {
		cleanup, done := context.WithTimeout(context.Background(), 20*time.Second)
		defer done()
		_ = client.Aiden.TerminateSession(cleanup, run.SessionID)
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	fmt.Fprintln(os.Stderr)
	fmt.Fprintln(os.Stderr, "subscribe complete ok=true")
}
