/**
 * Tiny native-TS functional toolkit. No dependency — this is the whole "library".
 * Reused by every "impossible states" concept in the POC.
 */

/** Exhaustiveness guard: put in the `default` arm of a union switch. Adding a
    new variant without handling it then fails to compile (x is no longer never). */
export function assertNever(x: never): never {
  throw new Error('Unexpected variant: ' + JSON.stringify(x));
}

/** A computation that either succeeded with a value or failed with an error.
    Plain objects (no classes) to match the signal/httpResource ergonomics. */
export type Result<E, T> =
  | { readonly ok: true; readonly value: T }
  | { readonly ok: false; readonly error: E };

export const ok = <T>(value: T): Result<never, T> => ({ ok: true, value });
export const err = <E>(error: E): Result<E, never> => ({ ok: false, error });

/** Nominal typing: Brand<string, 'Postcode'> is assignable from a plain string
    only through an explicit cast — so a smart constructor is the only minter. */
export type Brand<T, B extends string> = T & { readonly __brand: B };

/** Narrow a tagged union to one variant by its `tag`, or null. The single place
    the cast lives — TS can't narrow through a runtime tag argument, so callers get
    `whenTag(state, 'Editing')?.foo` instead of repeating `as Extract<…>`. */
export function whenTag<U extends { tag: string }, K extends U['tag']>(
  u: U,
  tag: K,
): Extract<U, { tag: K }> | null {
  return u.tag === tag ? (u as Extract<U, { tag: K }>) : null;
}
