"use client";

/**
 * ForecastMetaLine — compact freshness / traceability footer for Section 6 (§22).
 *
 * Surfaces the report `meta` provenance that, until now, lived only in the
 * exports («Сформировано» row): WHEN the forecast was computed, over WHICH
 * horizons, and the schema version. For a forecasting tool «прогноз рассчитан
 * <дата>» is a trust/staleness signal — without it the horizons appear only
 * implicitly via the chart axis and the compute date is invisible.
 *
 * Three independently-guarded segments joined by a middot, caption typography,
 * muted tokens (schema is the MOST muted — traceability, not headline):
 *
 *   Прогноз рассчитан: 7 июня 2026 · горизонты 6 / 12 / 18 / 24 мес · схема 1.0
 *
 * Date source: the run's persist time (`runCreatedAt` — the forecast envelope's
 * `created_at`, always set for a persisted run) is preferred; `meta.generated_at`
 * is the fallback. The PURE assembler / orchestrator deliberately do NOT stamp
 * `generated_at` (determinism), so it is frequently null in real runs — but the
 * persisted run always carries `created_at`, which is the real «когда рассчитан».
 *
 * GRACEFUL: renders null when every segment is empty (e.g. 202-pending or a thin
 * report). When neither date source resolves, only that segment is skipped while
 * horizons + schema still render. An invalid/unparseable date is treated as
 * missing. A date-only ISO string («2026-06-03») renders date-only; a datetime
 * with a meaningful (non-midnight) time appends «, ЧЧ:ММ» — a real run timestamp
 * carries a genuine time, so it shows «7 июня 2026, 14:20» (precise compute time).
 */

import type { ReportMeta } from "@/types/forecast";

/** «6 / 12 / 18 / 24 мес» — horizons joined; "" when the list is empty. */
function formatHorizons(horizons: number[]): string {
  if (horizons.length === 0) return "";
  return `${horizons.join(" / ")} мес`;
}

/**
 * «7 июня 2026» (date-only) or «7 июня 2026, 10:30» (meaningful time) — RU long
 * date from an ISO 8601 string. Returns "" for null/empty/unparseable input.
 *
 * A bare date («2026-06-03») parses to local midnight, so a 00:00 time is treated
 * as «no time» to avoid a misleading «, 00:00». A datetime carrying a real time
 * (and an explicit time component in the source string) appends «, ЧЧ:ММ».
 */
function formatComputedAt(computedAt: string | null): string {
  if (computedAt == null || computedAt.trim() === "") return "";
  const ts = Date.parse(computedAt);
  if (Number.isNaN(ts)) return "";

  const date = new Date(ts);
  const datePart = date.toLocaleDateString("ru", {
    day: "numeric",
    month: "long",
    year: "numeric",
  });

  const hasTimeComponent = computedAt.includes("T");
  const isMidnight = date.getHours() === 0 && date.getMinutes() === 0;
  if (!hasTimeComponent || isMidnight) return datePart;

  const timePart = date.toLocaleTimeString("ru", {
    hour: "2-digit",
    minute: "2-digit",
  });
  return `${datePart}, ${timePart}`;
}

const SEP_STYLE: React.CSSProperties = {
  color: "var(--fg-tertiary)",
  // hair spaces around the middot for RU typographic breathing room.
  padding: "0 2px",
};

export function ForecastMetaLine({
  meta,
  runCreatedAt,
}: {
  meta: ReportMeta;
  /**
   * The forecast envelope's `created_at` (the run's persist time) — the real
   * «когда рассчитан» signal, always set for a persisted run. Preferred over the
   * frequently-null `meta.generated_at`.
   */
  runCreatedAt?: string | null;
}) {
  // Run persist time wins; the (often null) deterministic meta stamp is fallback.
  const computedAt = formatComputedAt(runCreatedAt ?? meta.generated_at);
  const horizons = formatHorizons(meta.horizons);
  const schemaVersion = meta.schema_version?.trim() ?? "";

  const segments: React.ReactNode[] = [];
  if (computedAt) {
    segments.push(
      <span key="generated" style={{ color: "var(--fg-secondary)" }}>
        Прогноз рассчитан: {computedAt}
      </span>,
    );
  }
  if (horizons) {
    segments.push(
      <span key="horizons" style={{ color: "var(--fg-secondary)" }}>
        горизонты {horizons}
      </span>,
    );
  }
  if (schemaVersion) {
    segments.push(
      <span key="schema" style={{ color: "var(--fg-tertiary)" }}>
        схема {schemaVersion}
      </span>,
    );
  }

  if (segments.length === 0) return null;

  return (
    <p
      style={{
        margin: 0,
        display: "flex",
        flexWrap: "wrap",
        alignItems: "baseline",
        rowGap: 4,
        fontSize: 12,
        lineHeight: 1.5,
        color: "var(--fg-secondary)",
      }}
    >
      {segments.map((segment, i) => (
        <span
          key={i}
          style={{ display: "inline-flex", alignItems: "baseline" }}
        >
          {i > 0 && (
            <span aria-hidden style={SEP_STYLE}>
              ·
            </span>
          )}
          {segment}
        </span>
      ))}
    </p>
  );
}
