---
Analytics context. Tracks how many times each short code has been resolved.

Exposes two services — `record` and `count` — callable from other contexts.
The per-code hit state lives in a `Hits` agent: one instance per short code,
keyed by the code itself.
---
context shortener.analytics

uses shortener.core

exports transparent { AnalyticsError }

type AnalyticsError = enum {
	NotTracked,
}

---
Per-code hit counter. One agent instance per ShortCode.

State note: this agent assumes its `count` field initialises to 0 for a
freshly-seen code. The test "a fresh Hits key reads count as 0" probes exactly
this — if the runtime does not zero-initialise Int state, that probe is where it
surfaces (finding #10).
---
agent Hits {
	key code: ShortCode

	store count: Cell[Int]

	---
	Record a hit, returning the new running total.
	---
	on call increment() -> Effect[Result[Int, AnalyticsError]] {
		let next = count + 1
		count := next
		Ok(next)
	}

	---
	Read the current hit count without modifying it.
	---
	on call current() -> Effect[Result[Int, AnalyticsError]] {
		Ok(count)
	}
}

---
The analytics context's boundary: one service per operation. The service name
*is* the operation name, so cross-context callers reach these as
`Analytics.track(...)` and `Analytics.count(...)`.
---
service track {
	---
	Record a hit against a code and return the new total.
	---
	on call(code: ShortCode) -> Effect[Result[Int, AnalyticsError]] {
		let hits = Hits(code)
		let total <- hits.increment()
		total
	}
}

service count {
	---
	Read the current hit count for a code without modifying it.
	---
	on call(code: ShortCode) -> Effect[Result[Int, AnalyticsError]] {
		let hits = Hits(code)
		let total <- hits.current()
		total
	}
}
