package main

import (
	"encoding/json"
	"fmt"
	"os"
	"strconv"
	"strings"
)

type Plan struct {
	Format  string            `json:"format_version"`
	Changes *[]ResourceChange `json:"resource_changes"`
}
type ResourceChange struct {
	Address string `json:"address"`
	Change  struct {
		Actions []string `json:"actions"`
	} `json:"change"`
}

// Deletions checks only the documented resource-change actions. It is not a
// complete policy engine and never applies a plan or contacts a cloud API.
func Deletions(data []byte) ([]string, error) {
	var p Plan
	if err := json.Unmarshal(data, &p); err != nil {
		return nil, fmt.Errorf("decode: %w", err)
	}
	major, minor, ok := strings.Cut(p.Format, ".")
	n, err := strconv.Atoi(minor)
	if !ok || major != "1" || err != nil || n < 0 {
		return nil, fmt.Errorf("unsupported format %q", p.Format)
	}
	if p.Changes == nil {
		return nil, fmt.Errorf("resource_changes missing or null")
	}
	var deletes []string
	for _, r := range *p.Changes {
		if r.Address == "" {
			return nil, fmt.Errorf("empty resource address")
		}
		key := strings.Join(r.Change.Actions, ",")
		switch key {
		case "no-op", "create", "read", "update":
		case "delete", "delete,create", "create,delete":
			deletes = append(deletes, r.Address+"="+key)
		default:
			return nil, fmt.Errorf("%s: unsupported actions %q", r.Address, key)
		}
	}
	return deletes, nil
}
func run(args []string) int {
	if len(args) != 1 {
		fmt.Fprintln(os.Stderr, "usage: iaccheck plan.json")
		return 2
	}
	b, err := os.ReadFile(args[0])
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 2
	}
	d, err := Deletions(b)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 2
	}
	if len(d) > 0 {
		fmt.Printf("REVIEW deletions: %s\n", strings.Join(d, "; "))
		return 1
	}
	fmt.Println("PASS deletion check only; no apply performed")
	return 0
}
func main() { os.Exit(run(os.Args[1:])) }
