// Attach a deny policy, open break-glass, then restore guardrails.
//
// Documented at https://appcd-dev.github.io/stackgen-sdk/code-samples/policy-break-glass/
//
//	go run ./examples/go/automation/policy-break-glass.go --agent my-oncall-agent
package main

import (
	"context"
	"crypto/rand"
	"encoding/hex"
	"flag"
	"fmt"
	"os"
	"strings"

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

const denyRego = `package policy

import rego.v1

default allow := true

allow := false if {
  endswith(input.tool.name, "_execute_parallel")
  some c in input.tool.arguments.commands
  contains(c.command, "sdk-btg-emergency-marker")
}

deny_reason := "sdk sample: emergency marker denied without break-glass" if {
  not allow
}
`

// envOr returns the first non-empty environment variable among keys.
func envOr(keys ...string) string {
	for _, key := range keys {
		if v := strings.TrimSpace(os.Getenv(key)); v != "" {
			return v
		}
	}
	return ""
}

func main() {
	agent := flag.String("agent", "", "existing agent name")
	flag.Parse()
	if strings.TrimSpace(*agent) == "" {
		fmt.Fprintln(os.Stderr, "--agent is required")
		os.Exit(2)
	}
	base, token, org := envOr("STACKGEN_URL"), envOr("STACKGEN_TOKEN"), envOr("STACKGEN_WORKSPACE_ID", "STACKGEN_PROJECT")
	if base == "" || token == "" || org == "" {
		fmt.Fprintln(os.Stderr, "set STACKGEN_URL, STACKGEN_TOKEN, and STACKGEN_WORKSPACE_ID")
		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)
	}
	var buf [4]byte
	_, _ = rand.Read(buf[:])
	ctx := context.Background()
	policy, err := client.Aiden.CreatePolicy(ctx, map[string]any{
		"name":        "deny-emergency-marker-" + hex.EncodeToString(buf[:]),
		"description": "SDK sample: deny emergency marker command",
		"type":        "logic",
		"rego_source": denyRego,
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	policyID, _ := policy["id"].(string)
	fmt.Printf("created policy id=%s\n", policyID)
	defer func() {
		_, _ = client.Aiden.EndBreakGlass(context.Background(), *agent)
		_, _ = client.Aiden.DetachPolicy(context.Background(), *agent, policyID)
		_, _ = client.Aiden.DeletePolicy(context.Background(), policyID)
	}()
	if _, err := client.Aiden.AttachPolicy(ctx, *agent, map[string]any{
		"policy_id": policyID,
		"shadow":    true,
		"priority":  10,
	}); err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	if _, err := client.Aiden.WhenPoliciesDisagree(ctx, *agent, "any_deny_blocks"); err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	opened, err := client.Aiden.BreakGlass(ctx, *agent, "sdk sample outage bypass", 15)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	fmt.Printf("break-glass active=%v activated_by=%v\n", opened["active"], opened["activated_by"])
	state, err := client.Aiden.GetBreakGlass(ctx, *agent)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	fmt.Printf("confirmed active=%v reason=%v\n", state["active"], state["reason"])
}
