// Crash-/refresh-safe persistence for an active or paused timer session.
//
// The stopwatch tracks elapsed time using performance.now() which is reset to
// zero on every page load — so a running timer silently resets to 0:00 on
// refresh. This module mirrors the timer state into localStorage with
// wall-clock anchoring (Date.now()) so it can be reconstructed after a reload.
//
// Pure and framework-agnostic so it is unit-testable without a DOM. The React
// component injects `window.localStorage`; tests inject an in-memory stand-in.

export type ActiveTimerState = 'running' | 'paused'

export interface ActiveTimerRecord {
  /** Timer is running or was paused */
  timerState: ActiveTimerState
  /**
   * Wall-clock epoch (ms) at which the current run segment was started.
   * Only meaningful when timerState === 'running'. Anchored with Date.now()
   * so it survives a page reload (performance.now() does not).
   */
  segmentStartEpochMs: number
  /** Total elapsed ms accumulated in all previous segments (before this one). */
  pausedElapsedMs: number
  /** Elapsed at the start of the current lap, in ms. */
  lapStartElapsedMs: number
  /** Active process step id. */
  stepId: string | null
  /** Selected time type (e.g. 'prozesszeit'). */
  timeType: string
  /** Current machine phase when split mode is active. */
  machinePhase: 'manual1' | 'machine_running' | 'manual2'
  /** Elapsed (ms) at which the machine phase started. */
  machineStartElapsedMs: number
}

/** Injected storage interface — identical to PendingStorage for consistency. */
export interface PendingStorage {
  getItem(key: string): string | null
  setItem(key: string, value: string): void
}

const KEY_PREFIX = 'kadi:active-timer:v1:'

function storageKey(projectId: string): string {
  return `${KEY_PREFIX}${projectId}`
}

function resolveStorage(storage?: PendingStorage | null): PendingStorage | null {
  if (storage !== undefined) return storage
  if (typeof window === 'undefined') return null
  try {
    return window.localStorage
  } catch {
    return null
  }
}

/** Persist the active timer record. */
export function saveActiveTimer(
  projectId: string,
  record: ActiveTimerRecord,
  storage?: PendingStorage | null
): void {
  const store = resolveStorage(storage)
  if (!store) return
  try {
    store.setItem(storageKey(projectId), JSON.stringify(record))
  } catch {
    // Quota or serialization failure — silently ignore.
  }
}

/** Load the active timer record, or null if nothing is stored. */
export function loadActiveTimer(
  projectId: string,
  storage?: PendingStorage | null
): ActiveTimerRecord | null {
  const store = resolveStorage(storage)
  if (!store) return null
  try {
    const raw = store.getItem(storageKey(projectId))
    if (!raw) return null
    const parsed = JSON.parse(raw)
    if (!parsed || typeof parsed !== 'object') return null
    // Minimal sanity check — timerState must be one of the two valid values.
    if (parsed.timerState !== 'running' && parsed.timerState !== 'paused') return null
    return parsed as ActiveTimerRecord
  } catch {
    return null
  }
}

/** Remove the active timer record (call on Record / Reset / session complete). */
export function clearActiveTimer(
  projectId: string,
  storage?: PendingStorage | null
): void {
  const store = resolveStorage(storage)
  if (!store) return
  try {
    // PendingStorage only requires getItem/setItem; write empty string as a
    // sentinel because removeItem is not in the interface.
    store.setItem(storageKey(projectId), '')
  } catch {
    // Silently ignore.
  }
}

/**
 * Reconstruct elapsed milliseconds from a stored record given the current
 * wall-clock time. Callers pass `nowEpochMs` (= Date.now()) so the function
 * stays pure and easily unit-testable.
 *
 * For a running timer the total elapsed is:
 *   pausedElapsedMs + (nowEpochMs - segmentStartEpochMs)
 *
 * For a paused timer the total elapsed is simply pausedElapsedMs.
 */
export function restoreElapsedMs(record: ActiveTimerRecord, nowEpochMs: number): number {
  if (record.timerState === 'running') {
    return record.pausedElapsedMs + Math.max(0, nowEpochMs - record.segmentStartEpochMs)
  }
  return record.pausedElapsedMs
}
