// FreshnessBanner.jsx — top-level data-freshness indicator bar.
// Displays contextual banners for stale, offline, or error states with
// a retry button and human-readable "last updated" timestamp.
//
// Props:
//   freshness {string}  — "live" | "stale" | "offline" | "error"
//   fetchedAt {string}  — ISO 8601 timestamp of last successful API fetch
//   error     {string}  — optional error message to display in error state
//   onRetry   {func}    — callback fired when the Retry / Refresh button is pressed
//   loading   {bool}    — whether a retry/refresh is currently in progress
//
// Freshness states (mirrors _classifyDataFreshness in screens-overview.jsx):
//   live    → banner hidden (returns null)
//   stale   → warning-toned banner (amber) — data is ageing but usable
//   offline → critical-toned banner (red) — data is outdated / source unreachable
//   error   → danger-toned banner (red) — explicit API or network error

(function () {
  // ── i18n helper (local copy, same pattern as App.jsx) ───────────────
  function t(key, fallback, params) {
    if (window.Keeper && window.Keeper.i18n && typeof window.Keeper.i18n.t === "function") {
      return window.Keeper.i18n.t(key, params, { fallback: fallback });
    }
    if (params && typeof fallback === "string") {
      return fallback.replace(/\{(\w+)\}/g, function (_, k) {
        return params[k] !== undefined ? params[k] : "{" + k + "}";
      });
    }
    return fallback;
  }

  // ── Relative time formatter ─────────────────────────────────────────
  function formatAge(isoString) {
    if (!isoString) return null;
    var d = new Date(isoString);
    if (Number.isNaN(d.getTime())) return null;
    var diffSec = Math.max(0, Math.floor((Date.now() - d.getTime()) / 1000));
    if (diffSec < 5) return t("freshness.age.justNow", "just now");
    if (diffSec < 60) return t("freshness.age.seconds", "{count}s ago", { count: diffSec });
    var min = Math.floor(diffSec / 60);
    if (min < 60) return t("freshness.age.minutes", "{count} min ago", { count: min });
    var hr = Math.floor(min / 60);
    if (hr < 24) return t("freshness.age.hours", "{count}h ago", { count: hr });
    var days = Math.floor(hr / 24);
    return t("freshness.age.days", "{count}d ago", { count: days });
  }

  // ── State configuration ─────────────────────────────────────────────
  var STATE_CONFIG = {
    stale: {
      icon: "ri-time-line",
      cls: "freshness-banner--stale",
      role: "status",
      ariaLive: "polite",
      messageKey: "freshness.stale.message",
      messageFallback: "Data may be outdated \u00b7 last updated {age}",
      noAgeKey: "freshness.stale.noAge",
      messageNoAge: "Data may be outdated",
      retryKey: "freshness.retry",
      retryFallback: "Refresh",
    },
    offline: {
      icon: "ri-wifi-off-line",
      cls: "freshness-banner--offline",
      role: "alert",
      ariaLive: "assertive",
      messageKey: "freshness.offline.message",
      messageFallback: "Connection lost \u00b7 showing last known data from {age}",
      noAgeKey: "freshness.offline.noAge",
      messageNoAge: "Connection lost \u00b7 showing last known data",
      retryKey: "freshness.reconnect",
      retryFallback: "Reconnect",
    },
    error: {
      icon: "ri-error-warning-line",
      cls: "freshness-banner--error",
      role: "alert",
      ariaLive: "assertive",
      messageKey: "freshness.error.message",
      messageFallback: "Could not load dashboard data \u2014 try again or check your connection",
      noAgeKey: "freshness.error.noAge",
      messageNoAge: "Could not load dashboard data \u2014 try again or check your connection",
      retryKey: "freshness.retryLoad",
      retryFallback: "Retry",
    },
  };

  // ── Component ───────────────────────────────────────────────────────
  function FreshnessBanner(props) {
    var safeProps = props || {};
    var freshness = safeProps.freshness || "live";
    var fetchedAt = safeProps.fetchedAt || null;
    var error = safeProps.error || "";
    var onRetry = typeof safeProps.onRetry === "function" ? safeProps.onRetry : null;
    var loading = !!safeProps.loading;

    // Live state → no banner
    if (freshness === "live") return null;

    var config = STATE_CONFIG[freshness] || STATE_CONFIG.stale;
    var age = formatAge(fetchedAt);

    // Build the display message
    var message;
    if (freshness === "error" && error) {
      message = error;
    } else if (age) {
      message = t(config.messageKey, config.messageFallback, { age: age });
    } else {
      message = t(config.noAgeKey, config.messageNoAge);
    }

    // Tick the "X min ago" label once per minute
    var _forceUpdate = React.useState(0)[1];
    React.useEffect(function () {
      if (freshness === "live" || !fetchedAt) return undefined;
      var timer = setInterval(function () {
        _forceUpdate(function (c) { return c + 1; });
      }, 60000);
      return function () { clearInterval(timer); };
    }, [freshness, fetchedAt]);

    // Show the separate <time> element only for 'offline' state where
    // the message text uses different phrasing. For 'stale' the age is
    // already embedded in the message so repeating it is redundant.
    var showSeparateTimestamp = age && freshness === "offline";

    return (
      <div
        className={"freshness-banner " + config.cls}
        role={config.role}
        aria-live={config.ariaLive}
        aria-atomic={freshness !== "stale" ? "true" : undefined}
      >
        <span className="freshness-banner__icon" aria-hidden="true">
          <i className={loading ? "ri-loader-4-line freshness-banner__spin" : config.icon}></i>
        </span>

        <span className="freshness-banner__message">{message}</span>

        {showSeparateTimestamp && (
          <time
            className="freshness-banner__ts"
            dateTime={fetchedAt}
            title={fetchedAt ? new Date(fetchedAt).toLocaleString() : ""}
          >
            {t("freshness.lastUpdated", "Last updated: {age}", { age: age })}
          </time>
        )}

        {onRetry && (
          <button
            type="button"
            className="btn btn--sm freshness-banner__retry"
            onClick={onRetry}
            disabled={loading}
            aria-label={t(config.retryKey, config.retryFallback)}
          >
            {loading
              ? t("freshness.retrying", "Retrying\u2026")
              : t(config.retryKey, config.retryFallback)}
          </button>
        )}
      </div>
    );
  }

  window.FreshnessBanner = FreshnessBanner;
})();
