// Triage an SRE alert and close finished investigation threads.
//
// Documented at https://appcd-dev.github.io/stackgen-sdk/code-samples/sre-triage-alerts/
//
//	go run ./examples/go/sre/triage-alerts.go --dry-run
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")
	alertID := flag.String("alert-id", "", "Alert UUID")
	query := flag.String("q", "", "Alert search when --alert-id is omitted")
	ignoreReason := flag.String("ignore-reason", "", "Ignore reason")
	falsePositive := flag.Bool("false-positive", false, "Set attention to false_positive")
	resolve := flag.Bool("resolve", false, "Resolve finished investigations")
	dryRun := flag.Bool("dry-run", false, "List candidates and exit")
	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})
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	ctx := context.Background()
	id := strings.TrimSpace(*alertID)

	if id == "" {
		q := map[string]string{"status": "active", "page_size": "5"}
		if strings.TrimSpace(*query) != "" {
			q["q"] = *query
		}
		listed, err := client.SRE.ListAlerts(ctx, q)
		if err != nil {
			fmt.Fprintln(os.Stderr, "error:", err)
			os.Exit(1)
		}
		raw, _ := json.MarshalIndent(listed, "", "  ")
		fmt.Println("alerts:", string(raw))
		if body, ok := listed.(map[string]any); ok {
			items, _ := body["alerts"].([]any)
			if len(items) == 0 {
				items, _ = body["items"].([]any)
			}
			if len(items) > 0 {
				if first, ok := items[0].(map[string]any); ok {
					id, _ = first["id"].(string)
				}
			}
		}
	}

	groups, err := client.SRE.ListInvestigationGroups(ctx, map[string]string{"page_size": "5"})
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	raw, _ := json.MarshalIndent(groups, "", "  ")
	fmt.Println("groups:", string(raw))

	if *dryRun {
		if id != "" {
			fmt.Fprintln(os.Stderr, "alert_id=", id)
		}
		return
	}
	if id == "" {
		fmt.Fprintln(os.Stderr, "error: pass --alert-id or ensure list alerts returns a row")
		os.Exit(1)
	}

	if *falsePositive {
		updated, err := client.SRE.SetAlertAttention(ctx, id, "false_positive", *ignoreReason)
		if err != nil {
			fmt.Fprintln(os.Stderr, "error:", err)
			os.Exit(1)
		}
		raw, _ = json.MarshalIndent(updated, "", "  ")
		fmt.Println("attention:", string(raw))
	} else if strings.TrimSpace(*ignoreReason) != "" {
		updated, err := client.SRE.IgnoreAlert(ctx, id, *ignoreReason)
		if err != nil {
			fmt.Fprintln(os.Stderr, "error:", err)
			os.Exit(1)
		}
		raw, _ = json.MarshalIndent(updated, "", "  ")
		fmt.Println("ignored:", string(raw))
	} else if !*resolve {
		fmt.Fprintln(os.Stderr, "pass --false-positive, --ignore-reason TEXT, --resolve, or --dry-run")
		os.Exit(2)
	}

	if *resolve {
		inv, err := client.SRE.ListInvestigations(ctx, map[string]string{"alert_id": id, "page_size": "50"})
		if err != nil {
			fmt.Fprintln(os.Stderr, "error:", err)
			os.Exit(1)
		}
		raw, _ = json.MarshalIndent(inv, "", "  ")
		fmt.Println("investigations:", string(raw))
		var done []string
		if body, ok := inv.(map[string]any); ok {
			for _, item := range body["investigations"].([]any) {
				row, _ := item.(map[string]any)
				status, _ := row["status"].(string)
				rid, _ := row["id"].(string)
				if rid != "" && (status == "completed" || status == "failed" || status == "draft") {
					done = append(done, rid)
				}
			}
		}
		if len(done) == 0 {
			fmt.Fprintln(os.Stderr, "resolve: no completed/failed/draft threads")
			return
		}
		resolved, err := client.SRE.ResolveInvestigations(ctx, done)
		if err != nil {
			fmt.Fprintln(os.Stderr, "error:", err)
			os.Exit(1)
		}
		raw, _ = json.MarshalIndent(resolved, "", "  ")
		fmt.Println("resolved:", string(raw))
	}
}
