// List SRE alerts and optionally start an investigation, waiting for the RCA.
//
// Documented at https://appcd-dev.github.io/stackgen-sdk/code-samples/sre-investigate-alert/
//
//	go run ./examples/go/sre/investigate-alert.go --list-only --q checkout
package main

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

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

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")
	status := flag.String("status", "active", "Alert status filter")
	query := flag.String("q", "checkout", "Alert search query")
	alertID := flag.String("alert-id", "", "Skip list; investigate this id")
	listOnly := flag.Bool("list-only", false, "List matching alerts and exit")
	poll := flag.Bool("poll", false, "Wait until the RCA is ready")
	exportSession := flag.Bool("export-session", false, "Export the Aiden session report when present")
	timeoutSeconds := flag.Int("timeout-seconds", 1800, "Wait timeout")
	pollInterval := flag.Int("poll-interval-seconds", 5, "Poll interval")
	operatorMessage := flag.String("operator-message", "Investigate checkout CPU in prod", "Message sent with investigate")
	flag.Parse()

	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_ORG_ID", "STACKGEN_PROJECT", "STACKGEN_PROJECT_ID")
	}
	if base == "" || token == "" {
		fmt.Fprintln(os.Stderr, "set STACKGEN_URL and STACKGEN_TOKEN")
		os.Exit(2)
	}
	client, err := stackgen.NewClient(stackgen.Config{
		BaseURL:             base,
		APIToken:            token,
		WorkspaceID:         org,
		TimeoutSeconds:      *timeoutSeconds,
		PollIntervalSeconds: *pollInterval,
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	ctx := context.Background()
	id := strings.TrimSpace(*alertID)
	if id == "" {
		alerts, err := client.SRE.ListAlerts(ctx, map[string]string{"status": *status, "q": *query})
		if err != nil {
			fmt.Fprintln(os.Stderr, "error:", err)
			os.Exit(1)
		}
		raw, _ := json.MarshalIndent(alerts, "", "  ")
		fmt.Println("list_alerts:", string(raw))
		if *listOnly {
			return
		}
		body, _ := alerts.(map[string]any)
		items, _ := body["alerts"].([]any)
		if len(items) == 0 {
			items, _ = body["items"].([]any)
		}
		if len(items) == 0 {
			fmt.Fprintln(os.Stderr, "error: no matching alert (pass --alert-id or use --list-only)")
			os.Exit(1)
		}
		first, _ := items[0].(map[string]any)
		id, _ = first["id"].(string)
		if id == "" {
			fmt.Fprintln(os.Stderr, "error: alert item missing id")
			os.Exit(1)
		}
	}

	body := map[string]any{"operator_message": *operatorMessage}
	if !*poll {
		started, err := client.SRE.InvestigateAlert(ctx, id, body)
		if err != nil {
			fmt.Fprintln(os.Stderr, "error:", err)
			os.Exit(1)
		}
		raw, _ := json.MarshalIndent(started, "", "  ")
		fmt.Println("investigate:", string(raw))
		return
	}

	investigation, err := client.SRE.InvestigateAlertAndWait(ctx, id, body)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	raw, _ := json.MarshalIndent(investigation, "", "  ")
	fmt.Println("investigation:", string(raw))

	if rca, ok := investigation["structured_rca"].(map[string]any); ok {
		if plain, ok := rca["plain_summary"].(map[string]any); ok {
			p, _ := json.MarshalIndent(plain, "", "  ")
			fmt.Println("plain_summary:", string(p))
		}
		if root := fmt.Sprint(rca["root_cause"]); root != "" && root != "<nil>" {
			fmt.Fprintln(os.Stderr, "root_cause=", root)
		}
	}

	if *exportSession {
		if sessionID, _ := investigation["guild_session_id"].(string); sessionID != "" {
			export, err := client.Aiden.ExportSession(ctx, sessionID, "report", "")
			if err != nil {
				fmt.Fprintln(os.Stderr, "error:", err)
				os.Exit(1)
			}
			raw, _ = json.MarshalIndent(export, "", "  ")
			fmt.Println("export:", string(raw))
		}
	}
}
