package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"math"
	"os"
	"sync"
)

type Workload struct {
	Requests        int64 `json:"requests"`
	MemoryMiB       int64 `json:"memory_mib"`
	BilledMS        int64 `json:"billed_ms"`
	Rate            int64 `json:"requests_per_second"`
	MeanMS          int64 `json:"mean_duration_ms"`
	MaxInstances    int64 `json:"max_instances"`
	PoolPerInstance int64 `json:"pool_per_instance"`
	DBMax           int64 `json:"db_max_connections"`
	DBReserve       int64 `json:"db_reserved_connections"`
}
type Result struct {
	MeanInFlight                      float64
	GiBSeconds                        float64
	Connections, Budget, FitInstances int64
}

func mul(a, b int64) (int64, error) {
	if a < 0 || b < 0 || (b != 0 && a > math.MaxInt64/b) {
		return 0, errors.New("negative value or integer overflow")
	}
	return a * b, nil
}
func Analyze(w Workload) (Result, error) {
	if w.Requests <= 0 || w.MemoryMiB <= 0 || w.BilledMS <= 0 || w.Rate <= 0 || w.MeanMS <= 0 || w.MaxInstances <= 0 || w.PoolPerInstance <= 0 || w.DBMax <= 0 || w.DBReserve < 0 || w.DBReserve >= w.DBMax {
		return Result{}, errors.New("positive inputs required; DB reserve must be below DB max")
	}
	units, err := mul(w.Requests, w.MemoryMiB)
	if err != nil {
		return Result{}, err
	}
	units, err = mul(units, w.BilledMS)
	if err != nil {
		return Result{}, err
	}
	inflight, err := mul(w.Rate, w.MeanMS)
	if err != nil {
		return Result{}, err
	}
	conns, err := mul(w.MaxInstances, w.PoolPerInstance)
	if err != nil {
		return Result{}, err
	}
	budget := w.DBMax - w.DBReserve
	return Result{float64(inflight) / 1000, float64(units) / (1024 * 1000), conns, budget, budget / w.PoolPerInstance}, nil
}
func readWorkload(path string) (Workload, error) {
	var w Workload
	f, err := os.Open(path)
	if err != nil {
		return w, err
	}
	defer f.Close()
	d := json.NewDecoder(f)
	d.DisallowUnknownFields()
	if err = d.Decode(&w); err != nil {
		return w, err
	}
	var extra any
	if err = d.Decode(&extra); err != io.EOF {
		return w, errors.New("expected exactly one JSON value")
	}
	return w, nil
}

// Ledger is an in-memory transaction model, not durable storage.
// One event ID identifies exactly one reservation payload.
type Event struct {
	ID    string
	Units int
}
type Ledger struct {
	mu    sync.Mutex
	stock int
	done  map[string]int
}

func NewLedger(stock int) *Ledger { return &Ledger{stock: stock, done: make(map[string]int)} }
func (l *Ledger) Reserve(e Event, failBeforeCommit bool) (bool, error) {
	if e.ID == "" || e.Units <= 0 {
		return false, errors.New("invalid event")
	}
	l.mu.Lock()
	defer l.mu.Unlock()
	if units, ok := l.done[e.ID]; ok {
		if units != e.Units {
			return false, errors.New("event ID payload conflict")
		}
		return false, nil
	}
	if l.stock < e.Units {
		return false, errors.New("insufficient stock")
	}
	if failBeforeCommit {
		return false, errors.New("injected before commit")
	}
	// The business change and deduplication mark share this critical section.
	l.stock -= e.Units
	l.done[e.ID] = e.Units
	return true, nil
}
func (l *Ledger) Stock() int { l.mu.Lock(); defer l.mu.Unlock(); return l.stock }

// Deliberately wrong: the marker is committed before the business change.
// A simulated interruption leaves an event marked done without its effect.
func badMarkFirst(stock *int, done map[string]bool, e Event, interrupt bool) bool {
	if done[e.ID] {
		return false
	}
	done[e.ID] = true
	if interrupt {
		return false
	}
	*stock -= e.Units
	return true
}
func demo() {
	e := Event{"evt-42", 2}
	l := NewLedger(10)
	a, err := l.Reserve(e, false)
	fmt.Printf("first: applied=%v stock=%d err=%v\n", a, l.Stock(), err)
	a, err = l.Reserve(e, false)
	fmt.Printf("redelivery: applied=%v stock=%d err=%v\n", a, l.Stock(), err)
	_, err = l.Reserve(Event{"evt-42", 3}, false)
	fmt.Printf("conflict: %v\n", err)
	// Model: business stock survived elsewhere, but the worker lost dedup state.
	restarted := NewLedger(l.Stock())
	a, _ = restarted.Reserve(e, false)
	fmt.Printf("new-worker-without-dedup: applied=%v stock=%d\n", a, restarted.Stock())
	stock := 10
	seen := make(map[string]bool)
	badMarkFirst(&stock, seen, e, true)
	a = badMarkFirst(&stock, seen, e, false)
	fmt.Printf("bad-mark-first retry: applied=%v stock=%d\n", a, stock)
}
func run(args []string) int {
	if len(args) != 1 {
		fmt.Fprintln(os.Stderr, "usage: cloudmodels workload.json")
		return 2
	}
	w, err := readWorkload(args[0])
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 2
	}
	r, err := Analyze(w)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 2
	}
	fmt.Printf("mean-in-flight=%.1f (not a peak bound)\n", r.MeanInFlight)
	fmt.Printf("modeled-memory-GiB-seconds=%.0f (not a money quote)\n", r.GiBSeconds)
	fmt.Printf("pool-envelope=%d budget=%d fit-instances=%d over-budget=%v\n", r.Connections, r.Budget, r.FitInstances, r.Connections > r.Budget)
	demo()
	return 0
}
func main() { os.Exit(run(os.Args[1:])) }
