// src/welcome/welcome.ts — Plan 01-10 D-17-onboarding welcome page
// entrypoint.
//
// Vanilla DOM. Populates two attribute-selector flows:
//   - [data-mokosh-key='<key>'] from the COPY map (non-tagline strings;
//     engineering placeholders per D-03 Sober voice register).
//   - [data-mokosh-i18n-key='<key>'] from chrome.i18n.getMessage with
//     `|| <en-const>` fallback per the Plan 01-12 Wave 4 popup pattern.
//     The two D-08 tagline keys (welcomeHeroRu + welcomeHeroEn) live in
//     _locales/{en,ru}/messages.json (Plan 01-12 Wave 3; 16 keys total).
//
// NO event handlers — the welcome tab is informational + read-only per
// D-16-toolbar charter (toolbar onClicked owns the start path; the
// welcome page TELLS the operator where the icon is, does NOT host a
// "Start Mokosh" actionable button).
//
// Style/naming:
//   - filter-pipeline form per project rule "no `continue` statements";
//   - full-word variable names;
//   - no `as any`;
//   - centralized Logger from src/shared/logger.ts.
//
// References:
//   - D-17-onboarding (CONTEXT.md line 537+)
//   - D-16-toolbar (01-09-SUMMARY.md)
//   - Plan 01-12 Wave 4 fallback pattern (src/popup/index.ts:41 i18n
//     helper). Plan 01-10 inlines the pattern into the filter-pipeline
//     so the per-element resolution stays branch-free.

import { Logger } from '../shared/logger';
import {
  COPY,
  WELCOME_HERO_RU_FALLBACK,
  WELCOME_HERO_EN_FALLBACK,
} from './copy';
// Plan 01-10 must_have #9 path-A swap-in (landed 2026-05-20 per debug
// session 01-10-welcome-page-missing-mark): import the canonical mark
// SVG as a Vite-bundled asset URL. The `?url` suffix instructs Vite to
// emit the SVG verbatim to `dist/assets/<hash>.svg` and replace the
// import with the hashed asset URL at build time. The @crxjs/vite-plugin
// ^2.0.0-beta.25 in this project auto-generates web_accessible_resources
// entries for resources transitively reachable from extension pages
// (welcome.html → welcome.ts → markUrl) — confirmed by Plan 01-12
// RESEARCH §155 and the existing dist/assets/*.woff2 precedent.
// Reference: https://vite.dev/guide/assets.html#explicit-url-imports
import markUrl from '../shared/brand/mokosh-mark.svg?url';

const logger = new Logger('Welcome');

/**
 * Walk every [data-mokosh-key='<key>'] element and write its
 * textContent (or document.title for the <title> element) from the
 * COPY map. Filter-pipeline form: any element whose attribute is
 * missing or whose key is absent from COPY is dropped from the
 * applied set; we log the missing count once at the end so an unwired
 * attribute is visible in the SW devtools console without spamming.
 */
function populateCopy(): void {
  const els = Array.from(
    document.querySelectorAll<HTMLElement>('[data-mokosh-key]'),
  );
  const pairs = els
    .map((el) => ({ el, key: el.getAttribute('data-mokosh-key') }))
    .filter(
      (p): p is { el: HTMLElement; key: string } => typeof p.key === 'string',
    )
    .map((p) => ({ ...p, value: COPY[p.key] }))
    .filter(
      (p): p is { el: HTMLElement; key: string; value: string } =>
        typeof p.value === 'string',
    );
  for (const { el, value } of pairs) {
    if (el.tagName === 'TITLE') {
      document.title = value;
    } else {
      el.textContent = value;
    }
  }
  const missing = els.length - pairs.length;
  if (missing > 0) {
    logger.warn(
      'populateCopy: '
        + String(missing)
        + ' [data-mokosh-key] elements had missing COPY entries',
    );
  }
}

/**
 * Walk every [data-mokosh-i18n-key='<key>'] element and write its
 * textContent from chrome.i18n.getMessage(key). Plan 01-12 Wave 4
 * fallback pattern: when getMessage returns '' (unknown key OR
 * chrome.i18n undefined in non-extension contexts), fall back to the
 * en-const string exported from ./copy. Empty resolutions are dropped
 * from the applied set; missing count surfaces via logger.warn for
 * post-mortem visibility.
 *
 * The two Plan 01-10 tagline keys (welcomeHeroRu + welcomeHeroEn)
 * resolve from _locales/{en,ru}/messages.json (Plan 01-12 Wave 3).
 */
function populateI18n(): void {
  const fallbacks: Readonly<Record<string, string>> = Object.freeze({
    welcomeHeroRu: WELCOME_HERO_RU_FALLBACK,
    welcomeHeroEn: WELCOME_HERO_EN_FALLBACK,
  });
  const els = Array.from(
    document.querySelectorAll<HTMLElement>('[data-mokosh-i18n-key]'),
  );
  const pairs = els
    .map((el) => ({ el, key: el.getAttribute('data-mokosh-i18n-key') }))
    .filter(
      (p): p is { el: HTMLElement; key: string } => typeof p.key === 'string',
    )
    .map((p) => {
      const fromI18n = chrome?.i18n?.getMessage?.(p.key) ?? '';
      const fromFallback = fallbacks[p.key] ?? '';
      const value = fromI18n.length > 0 ? fromI18n : fromFallback;
      return { ...p, value };
    })
    .filter((p) => p.value.length > 0);
  for (const { el, value } of pairs) {
    el.textContent = value;
  }
  const missing = els.length - pairs.length;
  if (missing > 0) {
    logger.warn(
      'populateI18n: '
        + String(missing)
        + ' [data-mokosh-i18n-key] elements had missing chrome.i18n + fallback values',
    );
  }
}

/**
 * Walk every [data-mokosh-slot='mark'] wrapper and replace its inner
 * placeholder content with an <img> referencing the bundled canonical
 * mark SVG. Plan 01-10 must_have #9 path-A swap-in (landed 2026-05-20).
 *
 * The wrapper itself (.welcome-hero__mark) keeps its CSS-driven circle
 * background + sizing (welcome.css:64-73) — the SVG renders INSIDE the
 * styled wrapper at the existing dimensions. We preserve the
 * data-mokosh-slot='mark' attribute on the wrapper for forward-compat
 * (future plans can locate the slot generically).
 *
 * Filter-pipeline form per project rule "no `continue` statements".
 * Missing-slot count is logged once via logger.warn for visibility.
 *
 * Img dimensions: width/height attributes match the wrapper inner
 * dimensions implicit from --mks-space-20 minus negligible padding;
 * we use percentage sizing so the SVG fills the wrapper responsively
 * without coupling to the exact px value of the space token.
 *
 * Alt text resolves from COPY['welcome.hero.mark.alt'] when present,
 * else falls back to a literal Russian default ('Знак Mokosh'). The
 * alt is presentational (the mark is a decorative brand element, not
 * a structural content element), but a non-empty alt aids screen-
 * reader landmark identification.
 */
function populateMark(): void {
  const slots = Array.from(
    document.querySelectorAll<HTMLElement>('[data-mokosh-slot="mark"]'),
  );
  const altText = COPY['welcome.hero.mark.alt'] ?? 'Знак Mokosh';
  for (const slot of slots) {
    const img = document.createElement('img');
    img.src = markUrl;
    img.alt = altText;
    img.width = 64;
    img.height = 64;
    img.className = 'welcome-hero__mark-img';
    img.setAttribute('aria-hidden', 'true');
    slot.replaceChildren(img);
  }
  if (slots.length === 0) {
    logger.warn(
      'populateMark: no [data-mokosh-slot="mark"] element found in DOM',
    );
  }
}

/**
 * Initialize the welcome page. populateMark first (replace the mark
 * slot with the bundled SVG so the hero never shows the text
 * placeholder), then populateCopy (non-tagline strings), then
 * populateI18n (the two D-08 tagline strings via chrome.i18n).
 */
function init(): void {
  populateMark();
  populateCopy();
  populateI18n();
  logger.log('welcome page ready');
}

if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', init);
} else {
  init();
}
