---
Tests for the links context.

These exercise the `Link` agent (state: `target: Option[Url]`) plus the create
service. Links consumes analytics and depends on CodeGen, so both are mocked.

STATE-INITIALISATION HYPOTHESIS
  A fresh `Link` key has `target == None`. The first probe test isolates this:
  it resolves a code that was never registered, with no prior write.
    - If it returns Err(NotFound): the Option state initialises to None.
      (Hypothesis holds — the resolve handler matches None => NotFound.)
    - If the assertion fails or the test errors: fresh Option state is not None
      (undefined, or loadState rejects the missing key) — finding #10, the
      Option-typed counterpart to the analytics Int probe.

This is the second half of the agent-state-initialisation experiment: the
analytics fixture probes a fresh Int field, this one a fresh Option field.

Construction note: `ShortCode.of(...)` / `Url.of(...)` return Result and are
unwrapped with a match (finding #7 outstanding).
---
test shortener.links

uses shortener.core

---
Provider mock: a deterministic code generator returning a raw String.
---
mocks CodeGen = TestCodeGen {
	fn next() -> Effect[String] {
		"test01"
	}
}

---
Consumed-context mock: stands in for analytics' track service.
---
mocks Analytics = MockAnalytics {
	fn track(code: ShortCode) -> Effect[Result[Int, AnalyticsError]] {
		Ok(1)
	}
}

---
STATE-INIT PROBE. A fresh Link key, resolved before any registration, should
report NotFound — which holds only if the Option state initialises to None.
---
test "a fresh Link key resolves to NotFound" {
	match ShortCode.of("fresh2") {
		Err(_) => assert false
		Ok(code) => {
			let link = Link(code)
			let outcome <- link.resolve()
			match outcome {
				Ok(_) => assert false
				Err(linkError) => match linkError {
					NotFound      => assert true
					AlreadyExists => assert false
				}
			}
		}
	}
}

test "creating a link stores the target and returns its code" {
	match ShortCode.of("test01") {
		Err(_) => assert false
		Ok(code) => match Url.of("https://example.com") {
			Err(_) => assert false
			Ok(url) => {
				let outcome <- create.call(code, url)
				match outcome {
					Ok(_)  => assert true
					Err(_) => assert false
				}
			}
		}
	}
}

test "creating the same code twice is rejected" {
	match ShortCode.of("dup001") {
		Err(_) => assert false
		Ok(code) => match Url.of("https://example.com") {
			Err(_) => assert false
			Ok(url) => {
				let _ <- create.call(code, url)
				let second <- create.call(code, url)
				match second {
					Ok(_) => assert false
					Err(linkError) => match linkError {
						AlreadyExists => assert true
						NotFound      => assert false
					}
				}
			}
		}
	}
}

test "resolving a registered code returns its target" {
	match ShortCode.of("res001") {
		Err(_) => assert false
		Ok(code) => match Url.of("https://example.com/page") {
			Err(_) => assert false
			Ok(url) => {
				let _ <- create.call(code, url)
				let link = Link(code)
				let outcome <- link.resolve()
				match outcome {
					Ok(target) => assert target == url
					Err(_)     => assert false
				}
			}
		}
	}
}
