// Package billing implements the drive9 hourly metering worker: it closes
// complete UTC hours into a durable usage ledger, snapshots per-tenant
// storage capacity, and delivers aggregated usage to the billing SQS queue
// through a leased outbox.
package billing

import "time"

// Config controls the billing worker. All fields are required unless noted.
type Config struct {
	// Provider and Region are trusted deployment dimensions; they are
	// stamped into billing labels and the CostID, never taken from requests.
	Provider string
	Region   string

	// SQSQueueURL is the billing report queue. Required when SendEnabled.
	SQSQueueURL string
	// SendEnabled gates actual SQS delivery. When false (shadow mode) the
	// ledger and outbox rows are still written so the pipeline can be
	// verified end to end without emitting billable messages.
	SendEnabled bool

	// SnapshotInterval is the storage snapshot cadence (default 5m).
	SnapshotInterval time.Duration
	// CollectInterval is how often the worker looks for closable hours
	// (default 1m).
	CollectInterval time.Duration
	// HourCloseDelay waits after an hour ends before closing it, to absorb
	// scrape lag (default 10m).
	HourCloseDelay time.Duration
	// SnapshotStaleTolerance bounds how far the newest snapshot may lag the
	// hour end before the storage bucket is marked incomplete (default
	// 2*SnapshotInterval).
	SnapshotStaleTolerance time.Duration
	// IncompleteRetryWindow bounds how far back the retry pass re-evaluates
	// incomplete storage hours (default 24h).
	IncompleteRetryWindow time.Duration

	// SendInterval is the outbox send-loop cadence (default 5s).
	SendInterval time.Duration
	// OutboxBatchSize bounds rows claimed per send pass (default 50).
	OutboxBatchSize int
	// OutboxLease is the claim lease for in-flight sends (default 2m).
	OutboxLease time.Duration
	// MaxSendAttempts moves a row to permanent_failed after this many
	// attempts (default 8).
	MaxSendAttempts int
}

func (c *Config) withDefaults() Config {
	out := *c
	if out.SnapshotInterval <= 0 {
		out.SnapshotInterval = 5 * time.Minute
	}
	if out.CollectInterval <= 0 {
		out.CollectInterval = time.Minute
	}
	if out.HourCloseDelay <= 0 {
		out.HourCloseDelay = 10 * time.Minute
	}
	if out.SnapshotStaleTolerance <= 0 {
		out.SnapshotStaleTolerance = 2 * out.SnapshotInterval
	}
	if out.IncompleteRetryWindow <= 0 {
		out.IncompleteRetryWindow = 24 * time.Hour
	}
	if out.SendInterval <= 0 {
		out.SendInterval = 5 * time.Second
	}
	if out.OutboxBatchSize <= 0 {
		out.OutboxBatchSize = 50
	}
	if out.OutboxLease <= 0 {
		out.OutboxLease = 2 * time.Minute
	}
	if out.MaxSendAttempts <= 0 {
		out.MaxSendAttempts = 8
	}
	return out
}
