/**
 * Greeting 用の「サイトの現地時刻」ヒント生成。
 *
 * 目的: 挨拶プロンプトに現在時刻を直接埋め込み、
 *       LLM が GET_SYSTEM_DATE ツールを呼んで「時間にあった挨拶をしますね。」と
 *       一次回答するのを構造的に防ぐ。
 *
 * 0.3.0 (i18n): 以前は UTC+9 (JST) 固定だったが、時刻は
 * `__AGENT_CONFIG__.locale.tz_offset_minutes` (= WP の wp_timezone()) から、
 * 表示する時刻帯ラベルは同 `locale.tz_abbr` (Asia/Tokyo なら "JST") から導出する。
 * 挨拶語と指示文は §4.4 の window.__NS_I18N__ 辞書 (t()) 経由で、
 * ソース上のリテラルは英語フォールバックのみ (INV-12)。
 *
 * 時間帯マッピング (system prompt と整合。判定はサイト現地時刻で行う):
 *   - 05:00–10:59 → greeting_morning
 *   - 11:00–17:59 → greeting_afternoon
 *   - 18:00–04:59 → greeting_evening
 */

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

/**
 * サイト設定 (__AGENT_CONFIG__.locale) を安全に読む。
 * フレーム外 (設定未注入) では undefined を返す。
 * @returns {{tz_offset_minutes?: number, tz_abbr?: string, site_name?: string}|undefined}
 */
function localeConfig() {
  if (typeof globalThis === "undefined") return undefined;
  return globalThis.__AGENT_CONFIG__?.locale;
}

/**
 * サイトの UTC オフセット (分)。未設定時はブラウザのローカルオフセットに退避する
 * (getTimezoneOffset() は「UTC - ローカル」の符号なので反転させる)。
 * @param {Date} now
 * @returns {number}
 */
function resolveTzOffsetMinutes(now) {
  const configured = localeConfig()?.tz_offset_minutes;
  if (typeof configured === "number" && Number.isFinite(configured)) return configured;
  return -now.getTimezoneOffset();
}

/**
 * 時刻に添える時間帯ラベル ("JST" 等)。未設定時は付けない。
 * @returns {string}
 */
function resolveZoneLabel() {
  const abbr = localeConfig()?.tz_abbr;
  return typeof abbr === "string" ? abbr : "";
}

// 0.3.0-dev.60: 曜日は英語固定 (製品判断 — 受け手はモデルであり、翻訳された
// 曜日名は非日本語話者のモデルをかえって混乱させる。includes/prompt.php の
// neccospeak_prompt_now_parts() が DateTimeImmutable::format('l') で作る値と
// 同じ方針)。
const WEEKDAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];

/**
 * @param {Date} [now] テスト時に注入可能。省略時は new Date()。
 * @param {number} [tzOffsetMinutes] サイトの UTC オフセット (分)。省略時は設定から導出。
 * @param {string} [zoneLabel] 時間帯ラベル。省略時は設定から導出。
 * @returns {{ hour: number, minute: number, timeOfDay: "morning"|"afternoon"|"evening", greetingWord: string, displayString: string, dateString: string, weekday: string }}
 */
export function getGreetingTimeHint(
  now = new Date(),
  tzOffsetMinutes = resolveTzOffsetMinutes(now),
  zoneLabel = resolveZoneLabel()
) {
  // 絶対時刻 (getTime) にサイトのオフセットを足し、shifted Date の UTC 時刻を
  // 読むことで、ブラウザのローカル TZ に依存せずサイト現地時刻を得る。
  const shifted = new Date(now.getTime() + tzOffsetMinutes * 60 * 1000);

  const hour = shifted.getUTCHours();
  const minute = shifted.getUTCMinutes();

  let timeOfDay;
  let greetingWord;
  if (hour >= 5 && hour < 11) {
    timeOfDay = "morning";
    greetingWord = t("greeting_morning", "Good morning");
  } else if (hour >= 11 && hour < 18) {
    timeOfDay = "afternoon";
    greetingWord = t("greeting_afternoon", "Hello");
  } else {
    // 18:00–04:59
    timeOfDay = "evening";
    greetingWord = t("greeting_evening", "Good evening");
  }

  const pad = (n) => String(n).padStart(2, "0");
  const clock = `${pad(hour)}:${pad(minute)}`;
  const displayString = zoneLabel ? `${clock} ${zoneLabel}` : clock;
  // getUTCFullYear/Month/Date は shifted (=サイト現地時刻を UTC ゲッタで読む
  // トリック) から読むので、hour/minute と同じ非ローカルTZ方式で一貫する。
  const dateString = `${shifted.getUTCFullYear()}-${pad(shifted.getUTCMonth() + 1)}-${pad(shifted.getUTCDate())}`;
  const weekday = WEEKDAYS[shifted.getUTCDay()];

  return { hour, minute, timeOfDay, greetingWord, displayString, dateString, weekday };
}

/**
 * 挨拶プロンプトに差し込む 1 行ヒント (人間可読 + LLM 解釈容易)。
 *
 * [CURRENT_JST_TIME] は widget-app-persistent.js の挨拶指示文が参照する
 * 凍結済みマーカーなので、辞書側でも改名しない。
 *
 * 0.3.0-dev.60: チップ質問の初回回答は response.instructions がセッション
 * 指示を「置換」するため includes/prompt.php の current_datetime セクション
 * (システムプロンプト側) を失う。そのためこのヒント自身が日付/曜日を運ぶ
 * (get_system_date 等ツール名の名指しは削除 — ツール自体を 0.3.0-dev.60 で
 * 撤去したため)。
 *
 * @param {Date} [now]
 * @returns {string}
 */
export function buildGreetingTimeHintLine(now = new Date()) {
  const { displayString, greetingWord, dateString, weekday } = getGreetingTimeHint(now);
  return t(
    "greeting_time_hint",
    '[CURRENT_JST_TIME] The current site date and time is {date} ({weekday}) {time}. Do not call any tool to check the time; greet with "{greeting}" according to this value.'
  )
    .replace("{date}", dateString)
    .replace("{weekday}", weekday)
    .replace("{time}", displayString)
    .replace("{greeting}", greetingWord);
}
