// Ask start, wait, then export the session report.
//
// Documented at https://appcd-dev.github.io/stackgen-sdk/code-samples/ask-export-report/
//
//	export STACKGEN_URL=https://app.stackgen.com
//	export STACKGEN_TOKEN=stackgen_…
//	export STACKGEN_WORKSPACE_ID=<workspace-uuid>
//	go run ./examples/go/ask/ask-export-report.go --workflow incident-triage --start-only
//	go run ./examples/go/ask/ask-export-report.go --workflow incident-triage
package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"net/url"
	"os"
	"strings"

	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", "", "Mothership URL")
	apiToken := flag.String("api-token", "", "API token")
	orgID := flag.String("workspace-id", "", "Workspace UUID (sent as orgId)")
	flag.StringVar(orgID, "org-id", *orgID, "Deprecated: use -workspace-id")
	workflow := flag.String("workflow", envOr("STACKGEN_WORKFLOW"), "Workflow name")
	message := flag.String("message", "Investigate the checkout CPU alert in prod", "Ask message")
	correlationID := flag.String("correlation-id", "corr-123", "Correlation id")
	incidentID := flag.String("incident-id", "INC-1001", "Incident id")
	timeoutSeconds := flag.Int("timeout-seconds", 1800, "Overall timeout")
	pollInterval := flag.Int("poll-interval-seconds", 5, "Poll interval")
	startOnly := flag.Bool("start-only", false, "Print the start payload and exit")
	tryArtifact := flag.Bool("try-artifact", false, "Try downloading the session artifact before export")
	artifactName := flag.String("artifact-name", "session-report.md", "Artifact filename")
	outputPath := flag.String("output-path", "session-report.md", "Local artifact path")
	flag.Parse()

	if strings.TrimSpace(*workflow) == "" {
		*workflow = "incident-triage"
	}
	base := strings.TrimSpace(*baseURL)
	if base == "" {
		base = envOr("STACKGEN_URL")
	}
	token := strings.TrimSpace(*apiToken)
	if token == "" {
		token = envOr("STACKGEN_TOKEN")
	}
	org := strings.TrimSpace(*orgID)
	if org == "" {
		org = envOr("STACKGEN_WORKSPACE_ID", "STACKGEN_PROJECT", "STACKGEN_PROJECT_ID")
	}
	if base == "" || token == "" || org == "" {
		fmt.Fprintln(os.Stderr, "set --base-url/--api-token/--workspace-id or STACKGEN_URL / STACKGEN_TOKEN / STACKGEN_WORKSPACE_ID")
		os.Exit(2)
	}
	client, err := stackgen.NewClient(stackgen.Config{
		BaseURL:             base,
		APIToken:            token,
		WorkspaceID:         org,
		TimeoutSeconds:      *timeoutSeconds,
		PollIntervalSeconds: *pollInterval,
		ArtifactName:        *artifactName,
		OutputPath:          *outputPath,
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	ctx := context.Background()
	started, err := client.Aiden.StartAsk(ctx, *message, aiden.StartAskOptions{
		EntityRefs: []aiden.EntityRef{{Name: *workflow, Type: "workflow"}},
		SourceMetadata: map[string]string{
			"correlation_id": *correlationID,
			"incident_id":    *incidentID,
		},
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	raw, _ := json.MarshalIndent(started.Raw, "", "  ")
	fmt.Println("start:", string(raw))
	if *startOnly {
		return
	}
	if started.TraceID == "" {
		fmt.Fprintln(os.Stderr, "error: start response missing trace_id")
		os.Exit(1)
	}
	trace, err := client.Aiden.WaitForExecution(ctx, started.TraceID)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	execution, _ := trace["execution"].(map[string]any)
	sessionID := started.SessionID
	if sessionID == "" {
		if v, ok := trace["session_id"].(string); ok {
			sessionID = v
		}
	}
	fmt.Fprintf(os.Stderr, "settled status=%v trace_settled=%v session_id=%s\n", execution["status"], execution["trace_settled"], sessionID)
	if sessionID == "" {
		fmt.Fprintln(os.Stderr, "error: no session_id after wait")
		os.Exit(1)
	}
	detail, err := client.Aiden.GetSession(ctx, sessionID)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	raw, _ = json.MarshalIndent(detail, "", "  ")
	fmt.Println("get_session:", string(raw))
	sessions, err := client.Aiden.ListSessions(ctx, url.Values{"q": {*correlationID}, "limit": {"5"}})
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	raw, _ = json.MarshalIndent(sessions, "", "  ")
	fmt.Println("list_sessions:", string(raw))
	if *tryArtifact {
		path, err := client.Aiden.DownloadSessionArtifact(ctx, sessionID, *artifactName, *outputPath)
		if err == nil {
			fmt.Fprintf(os.Stderr, "artifact_saved=%s\n", path)
			return
		}
		fmt.Fprintf(os.Stderr, "artifact miss (%v); falling back to export_session\n", err)
	}
	exported, err := client.Aiden.ExportSession(ctx, sessionID, "report", "json")
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	raw, _ = json.MarshalIndent(exported, "", "  ")
	fmt.Println("export:", string(raw))
	parts, _ := exported["parts"].([]any)
	for _, part := range parts {
		row, _ := part.(map[string]any)
		if row["kind"] == "report" {
			return
		}
	}
	fmt.Fprintln(os.Stderr, "error: export missing report part")
	os.Exit(1)
}
