/**
 * Pure helpers for the video → background-audio handoff (UR-040).
 *
 * TRACES: UR-040 | DR-052 | UT-060
 *
 * Kept free of Svelte/DOM so the handoff arithmetic and state transitions are
 * unit-testable without mounting the player. The component
 * (VideoPlayer.svelte) owns the actual `<video>` teardown and IPC calls.
 */

/**
 * Absolute playback position to resume the audio stream at.
 *
 * Transcoded HLS playback tracks time as `videoElement.currentTime + seekOffset`
 * (the element resets to 0 after each transcode reload; `seekOffset` carries the
 * cumulative offset). Background audio must resume at that ABSOLUTE position, so
 * both terms are summed here — mirroring the `effectiveTime` used elsewhere in
 * the player.
 */
export function computeHandoffPosition(elementCurrentTime: number, seekOffset: number): number {
  const pos = elementCurrentTime + seekOffset;
  return pos > 0 ? pos : 0;
}

/**
 * The handoff state. `wasPlaying` is captured on the way out so play/pause is
 * restored when the app returns to the foreground.
 */
export interface BackgroundAudioState {
  active: boolean;
  wasPlaying: boolean;
}

export const initialHandoffState: BackgroundAudioState = {
  active: false,
  wasPlaying: false,
};

/**
 * Whether a background signal should trigger the audio handoff right now.
 * Only when the toggle is on and we're not already handed off.
 */
export function shouldEnterBackgroundAudio(
  toggleOn: boolean,
  state: BackgroundAudioState
): boolean {
  return toggleOn && !state.active;
}

/**
 * Whether a foreground signal should trigger the return to WebView video.
 * Only when we actually handed off (regardless of the current toggle value, so
 * turning the toggle off while backgrounded still returns cleanly).
 */
export function shouldExitBackgroundAudio(state: BackgroundAudioState): boolean {
  return state.active;
}

/**
 * Whether the `<video>` should start playing again once it reloads on foreground.
 *
 * `wasPlaying` is what the video was doing when we handed off, but the native
 * audio player kept going after that — and the lockscreen/notification can pause
 * it while backgrounded. The player is the authoritative source of play/pause,
 * so an explicit `paused` from it overrides the handoff snapshot; anything less
 * definite (loading, seeking, already-stopped, no state at all) falls back to
 * the snapshot.
 *
 * TRACES: UR-040, UR-005 | DR-052 | UT-060
 */
export function shouldResumeOnForeground(
  wasPlaying: boolean,
  nativeStateKind: string | undefined
): boolean {
  return wasPlaying && nativeStateKind !== "paused";
}

/** What has to be restarted to put picture back on screen, and how. */
export interface HandoffReturn {
  /** Which renderer must be brought back. */
  target: "html5-element" | "native-backend";
  /** Absolute position the background audio reached. */
  position: number;
  /** Whether playback should be running once it is back. */
  shouldPlay: boolean;
}

/**
 * How to come back when the app returns to the foreground.
 *
 * The two render paths resume by completely different means, and conflating
 * them is what broke the native one:
 *
 *  - **html5-element** — assigning the stream URL is enough. An `$effect` in the
 *    component watches it, (re)initialises HLS or sets `videoElement.src`, and
 *    `canplay` then drives the seek and play.
 *  - **native-backend** — ExoPlayer owns no element, and nothing reacts to the
 *    stream URL on its behalf. Native playback is only ever started by an
 *    explicit backend load, which the component issues once, from `onMount`. So
 *    the return has to re-issue it; reassigning the URL restarts nothing.
 *
 * The component previously did only the URL assignment, for both paths. On the
 * native path that left the backend holding no item at all: a black screen with
 * a play overlay, a play button that did nothing, and the position pinned at
 * 0:00 — the handoff's own audio player having been stopped on the way out.
 *
 * `shouldPlay` folds in [shouldResumeOnForeground], so a lockscreen pause during
 * the handoff still wins over the snapshot taken on the way out.
 *
 * TRACES: UR-040, UR-003 | DR-196 | UT-060
 */
export function planHandoffReturn(opts: {
  useHtml5Element: boolean;
  position: number;
  wasPlaying: boolean;
  nativeStateKind: string | undefined;
}): HandoffReturn {
  return {
    target: opts.useHtml5Element ? "html5-element" : "native-backend",
    position: opts.position > 0 ? opts.position : 0,
    shouldPlay: shouldResumeOnForeground(opts.wasPlaying, opts.nativeStateKind),
  };
}
