// The client-version gate's two client signals (docs/ARCHITECTURE.md §2).
//
// HARD tier ("client too old"): the gateway refuses a foreground call with the update_required
// sentinel (the Execute result_code, the Subscribe FailedPrecondition). The transport reports it here,
// which drives the net-state machine into offlineVersionLocked; the notice (UpdateOverlay.svelte) reads
// netState.versionLocked and offers "Update" (store / reload) or "Play offline" (dismiss → stay
// offline). Offline play never trips it — the kill switch refuses the call before it leaves the device,
// and the background guest reconcile swallows it (stays a local guest, no notice).
//
// SOFT tier ("update available"): a served response carries the X-Update-Recommended header, which the
// transport reports here. It drives the machine (versionRecommended), whose setNudge effect — fired
// only from online — latches the dismissible nudge (UpdateNudge.svelte). The hard notice supersedes the
// nudge naturally: the nudge shows only while online, and version-locked is an offline state.

import { emit } from './netstate.svelte';
import { clientChannel } from './channel';

/** UPDATE_REQUIRED is the stable sentinel the gateway returns (the Execute result_code, and the
 *  GatewayError code the Subscribe FailedPrecondition maps to) for a client too old to be served. */
export const UPDATE_REQUIRED = 'update_required';

/** openUpdate sends the user to the fix, shared by the hard-tier notice and the soft-tier nudge: the
 *  store listing on a native build (VITE_RUSTORE_URL, handed to the OS via '_system'), or a plain
 *  reload on the web (which fetches the current client). */
export function openUpdate(): void {
  const ch = clientChannel();
  if (ch === 'android' || ch === 'ios') {
    const url = import.meta.env.VITE_RUSTORE_URL;
    if (url) window.open(url, '_system');
  } else {
    location.reload();
  }
}

/** reportUpdateRequired drives the net-state machine into offlineVersionLocked (the hard tier). The
 *  transport calls it only for a foreground update_required — the background reconcile swallows it and
 *  stays offline. The notice reads netState.versionLocked; there is no separate latch. */
export function reportUpdateRequired(): void {
  emit('versionRejected');
}

// The soft "update available" nudge. `active` latches when the machine accepts a versionRecommended
// from online (via the setNudge effect → latchUpdateNudge); `dismissed` hides the banner for the
// session once the user closes it. A fresh launch re-evaluates the version, so both reset on reload.
let recommended = $state(false);
let nudgeDismissed = $state(false);

export const updateRecommended = {
  /** active is true once the gateway has signalled an available (non-blocking) update. */
  get active(): boolean {
    return recommended;
  },
  /** dismissed is true once the user has closed the nudge for this session. */
  get dismissed(): boolean {
    return nudgeDismissed;
  },
};

/** latchUpdateNudge raises the soft-nudge latch. It is wired to the machine's setNudge effect
 *  (registerNetNudge), which fires only from online, so the nudge is never raised while offline or
 *  version-locked. */
export function latchUpdateNudge(): void {
  recommended = true;
}

/** dismissUpdateNudge hides the nudge for the session (a fresh launch re-evaluates the version). */
export function dismissUpdateNudge(): void {
  nudgeDismissed = true;
}

/** reportUpdateRecommended signals an available update (the soft tier). The transport calls it when a
 *  served response carries the X-Update-Recommended header; it drives the machine (versionRecommended),
 *  which latches the nudge from online. */
export function reportUpdateRecommended(): void {
  emit('versionRecommended');
}
