/**
 * Realtime 自動再接続設定 (Issue #193 / G-013)
 *
 * WebRTC 接続断 (peerConnection state=failed/disconnected / datachannel close) を
 * 検知した際の再接続ポリシー。UX 上「復旧する」ことを期待される過渡的な断線
 * (WiFi→4G 遷移、OpenAI 側の瞬断等) を自動で吸収する。
 *
 * 設計値の根拠:
 *   - MAX_RETRIES = 3         : 7秒程度の総試行時間でユーザー許容範囲内
 *   - INITIAL_DELAY_MS = 1000 : ICE 再起動時間を待つ最小値
 *   - BACKOFF_FACTOR = 2      : 1s → 2s → 4s の指数的増加
 *
 * 実装場所: widget-app-persistent.js の handleRealtimeError / _maybeAttemptReconnect
 *
 * 注意事項:
 *   - 定数を変更した場合は tests/unit/widget-reconnect-static-audit.test.js の
 *     regression を実行して、仕様ドリフトが無いことを確認してから commit する
 */

import { t } from "../ns/ns-rest.js";

export const RECONNECT_MAX_RETRIES = 3;
export const RECONNECT_INITIAL_DELAY_MS = 1000;
export const RECONNECT_BACKOFF_FACTOR = 2;
/**
 * Jitter の最大ms (Issue #429)。Thundering Herd 回避のため
 * 0..RECONNECT_JITTER_MS のランダムな ms を待機時間に加算する。
 */
export const RECONNECT_JITTER_MS = 500;

/**
 * n 回目 (1-indexed) の試行の待機時間 ms を計算する純粋関数。
 * Jitter は含まない決定的な base 値。
 *
 * @param {number} attempt - 1 以上の整数 (1=初回試行待機、2=2回目試行待機 ...)
 * @returns {number} 待機時間 (ms)
 *
 * 例: attempt=1 → 1000ms (1s)
 *     attempt=2 → 2000ms (2s)
 *     attempt=3 → 4000ms (4s)
 */
export function calculateBackoffDelayMs(attempt) {
  if (!Number.isInteger(attempt) || attempt < 1) return RECONNECT_INITIAL_DELAY_MS;
  return RECONNECT_INITIAL_DELAY_MS * Math.pow(RECONNECT_BACKOFF_FACTOR, attempt - 1);
}

/**
 * 指数バックオフに jitter (0..RECONNECT_JITTER_MS) を加算した待機時間を返す (Issue #429)。
 * 同時切断した複数クライアントが同タイミングで再接続することによるサーバ側 Thundering Herd を抑制する。
 *
 * 多数クライアントが同時に企業ネットワーク遮断から復帰する際に、
 * realtime-token エンドポイントへの連続発火 → OpenAI Realtime token
 * 大量発行による課金爆発を緩和する。
 *
 * @param {number} attempt - 1 以上の整数
 * @param {() => number} [rng] - 0..1 の乱数を返す関数 (default: Math.random)。テスト用に注入可能。
 * @returns {number} 待機時間 (ms)
 */
export function calculateBackoffDelayWithJitterMs(attempt, rng = Math.random) {
  const base = calculateBackoffDelayMs(attempt);
  const jitter = Math.floor(rng() * RECONNECT_JITTER_MS);
  return base + jitter;
}

/**
 * 試行状況の表示テンプレート。
 * @param {number} attempt
 * @returns {string}
 */
export function formatReconnectStatus(attempt) {
  return t("status_reconnecting", "Reconnecting ({attempt}/{max})...")
    .replace("{attempt}", attempt)
    .replace("{max}", RECONNECT_MAX_RETRIES);
}
