/**
 * NS REST アダプタ — neccospeak/v1 への唯一の窓口 (計画書 §1.2.3 / §3)。
 *
 * フレーム内アプリの全ての fetch() はこのモジュールを経由すること。
 * - `credentials: 'same-origin'` を必ず付与する (INV-T7)。BASIC 認証環境では
 *   `omit` にすると Apache 層で 401 になり全滅する (実証済)。
 * - `window.__NS_REST__` (PHP が `rest_url('neccospeak/v1/')` を注入) を
 *   ベースURLとして相対パスを解決する。
 *
 * `t()` は §4.4 の JS 用 i18n 辞書 (`window.__NS_I18N__`) の参照ヘルパ。
 * 新規ファイルを増やさない方針のためここに同居させる (計画書の指示どおり)。
 */

/**
 * NS REST のベースURL を取得する。
 * @returns {string} 末尾に `/` を含むベースURL
 */
function restBase() {
  const base = (typeof window !== "undefined" && window.__NS_REST__) || "/wp-json/neccospeak/v1/";
  return base.endsWith("/") ? base : `${base}/`;
}

/**
 * NS REST へ fetch する。credentials: 'same-origin' を常に強制する。
 * @param {string} path - `restUrl` からの相対パス (先頭の `/` はあってもなくてもよい)
 * @param {RequestInit} [init]
 * @returns {Promise<Response>}
 */
export function nsFetch(path, init = {}) {
  const url = `${restBase()}${String(path || "").replace(/^\/+/, "")}`;
  const headers = Object.assign({}, init.headers || {});
  const hasContentType = Object.keys(headers).some((k) => k.toLowerCase() === "content-type");
  if (init.body && typeof init.body === "string" && !hasContentType) {
    headers["Content-Type"] = "application/json";
  }
  const finalInit = Object.assign({}, init, {
    credentials: "same-origin",
    headers,
  });
  return fetch(url, finalInit);
}

/**
 * NS REST へ fetch し、非 2xx を Error として throw する JSON ヘルパ。
 * @param {string} path
 * @param {RequestInit} [init]
 * @returns {Promise<any>}
 */
export async function nsFetchJson(path, init = {}) {
  const res = await nsFetch(path, init);
  if (!res.ok) {
    let detail = null;
    try {
      detail = await res.json();
    } catch (_e) {
      /* body may be empty or non-JSON */
    }
    const err = new Error(`NS REST error: ${res.status}`);
    err.status = res.status;
    err.detail = detail;
    throw err;
  }
  return res.json();
}

/**
 * Response が SSE (`text/event-stream`) かどうかを判定する。
 * @param {Response} res
 * @returns {boolean}
 */
export function isSseResponse(res) {
  const ct = (res && res.headers && typeof res.headers.get === "function")
    ? (res.headers.get("Content-Type") || res.headers.get("content-type") || "")
    : "";
  return ct.indexOf("text/event-stream") !== -1;
}

/**
 * §4.4 の i18n 辞書からキーを引く。未登録キーは fallback を返す。
 * @param {string} key
 * @param {string} [fallback]
 * @returns {string}
 */
export function t(key, fallback) {
  const dict = (typeof window !== "undefined" && window.__NS_I18N__) || {};
  if (Object.prototype.hasOwnProperty.call(dict, key) && dict[key]) {
    return dict[key];
  }
  return fallback !== undefined ? fallback : key;
}
