package scenario

import (
	"context"
	"sync"
	"time"

	"scrabble/loadtest/internal/edge"
	"scrabble/loadtest/internal/seed"
)

// HammerConfig parameterises the gateway-hammer: how many concurrent callers and for
// how long to deliberately exceed the per-user rate limit from a single account.
type HammerConfig struct {
	Workers  int
	Duration time.Duration
}

// DefaultHammer returns a hammer that comfortably exceeds the 300/min per-user limit.
func DefaultHammer() HammerConfig {
	return HammerConfig{Workers: 20, Duration: 15 * time.Second}
}

// Hammer drives games.list from a single account far above the per-user rate limit to
// verify the limiter holds — rejections surface as the "rate_limited" code — and to
// measure its cost. Every call is recorded under "hammer:games.list" so the report
// shows the ok/rate_limited split and the rejection latency separately from the
// realistic traffic.
func (d *Driver) Hammer(ctx context.Context, acc seed.Account, cfg HammerConfig) {
	runCtx, cancel := context.WithTimeout(ctx, cfg.Duration)
	defer cancel()
	d.log.Info("gateway-hammer", "workers", cfg.Workers, "duration", cfg.Duration)
	c := edge.New(d.gateway)
	var wg sync.WaitGroup
	for w := 0; w < cfg.Workers; w++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for runCtx.Err() == nil {
				t0 := time.Now()
				_, code, _ := c.GamesList(runCtx, acc.Token)
				d.rec.Record("hammer:games.list", code, time.Since(t0))
			}
		}()
	}
	wg.Wait()
}
