/**
 * Exchange Rate Card — Sparkline chart frontend.
 *
 * Reads initial 24h data from the inline `data-crtoday-chart-points`
 * attribute, renders an SVG sparkline, and handles period tab clicks
 * by fetching fresh data from the REST API.
 */

import { renderSparkline, type ChartPoint } from './frontend/shared/sparkline';

/* ------------------------------------------------------------------ */
/*  Period tab click handler                                          */
/* ------------------------------------------------------------------ */

async function fetchPeriod(wrap: HTMLElement, period: string): Promise<void> {
  const api = wrap.getAttribute('data-crtoday-chart-api') || '';
  const source = wrap.getAttribute('data-crtoday-chart-source') || '';
  const deal = wrap.getAttribute('data-crtoday-chart-deal') || '';
  const from = wrap.getAttribute('data-crtoday-chart-from') || '';
  const to = wrap.getAttribute('data-crtoday-chart-to') || '';

  if (!api) return;

  const url = new URL(api, window.location.origin);
  url.searchParams.set('source', source);
  url.searchParams.set('deal', deal);
  url.searchParams.set('from', from);
  url.searchParams.set('to', to);
  url.searchParams.set('period', period);

  const area = wrap.querySelector<HTMLElement>('.crtoday-chart-area');
  if (!area) return;

  area.classList.add('crtoday-chart-loading');

  try {
    const res = await fetch(url.toString());
    if (!res.ok) return;
    const points: ChartPoint[] = await res.json();
    const chartLabel = wrap.getAttribute('data-crtoday-i18n-chart') || '';
    renderSparkline(area, points, chartLabel);
  } catch {
    /* Network error — keep the old chart */
  } finally {
    area.classList.remove('crtoday-chart-loading');
  }
}

/* ------------------------------------------------------------------ */
/*  Init                                                              */
/* ------------------------------------------------------------------ */

const INIT_FLAG = 'data-crtoday-chart-init';

function initChart(wrap: HTMLElement): void {
  if (wrap.hasAttribute(INIT_FLAG)) return;
  wrap.setAttribute(INIT_FLAG, '1');

  const area = wrap.querySelector<HTMLElement>('.crtoday-chart-area');
  const raw = wrap.getAttribute('data-crtoday-chart-points');
  const chartLabel = wrap.getAttribute('data-crtoday-i18n-chart') || '';
  const loadingLabel = wrap.getAttribute('data-crtoday-i18n-loading') || '';
  let rendered = false;

  /* Try initial render from SSR data */
  if (area && raw) {
    try {
      const points: ChartPoint[] = JSON.parse(raw);
      if (points.length >= 3) {
        renderSparkline(area, points, chartLabel);
        rendered = true;
      }
    } catch {
      /* malformed JSON — fall through to fallback */
    }
  }

  /* If SSR data had insufficient points, trigger the active tab's period
     (PHP already selected the first period with enough data) */
  if (!rendered) {
    const activeTab = wrap.querySelector<HTMLElement>('.crtoday-chart-tab-active');
    if (activeTab) {
      const period = activeTab.getAttribute('data-crtoday-period');
      if (period) {
        fetchPeriod(wrap, period);
      }
    }
  }

  /* Tab click listeners */
  const tabs = wrap.querySelectorAll<HTMLElement>('.crtoday-chart-tab');
  const srStatus = wrap.querySelector<HTMLElement>('.crtoday-chart-sr-status');

  const activateTab = (tab: HTMLElement) => {
    const period = tab.getAttribute('data-crtoday-period');
    if (!period) return;

    /* Update active state + ARIA */
    tabs.forEach((t) => {
      t.classList.remove('crtoday-chart-tab-active');
      t.setAttribute('aria-selected', 'false');
      t.setAttribute('tabindex', '-1');
    });
    tab.classList.add('crtoday-chart-tab-active');
    tab.setAttribute('aria-selected', 'true');
    tab.setAttribute('tabindex', '0');
    tab.focus();

    /* Announce loading */
    if (srStatus) srStatus.textContent = loadingLabel;

    fetchPeriod(wrap, period).then(() => {
      if (srStatus) srStatus.textContent = '';
    });
  };

  tabs.forEach((tab) => {
    tab.addEventListener('click', () => activateTab(tab));
  });

  /* Arrow key navigation between tabs (WAI-ARIA tab pattern) */
  const tablist = wrap.querySelector<HTMLElement>('.crtoday-chart-tabs');
  if (tablist) {
    tablist.addEventListener('keydown', (e: KeyboardEvent) => {
      const tabArr = Array.from(tabs);
      const idx = tabArr.indexOf(e.target as HTMLElement);
      if (idx < 0) return;

      let next = -1;
      if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
        e.preventDefault();
        next = (idx + 1) % tabArr.length;
      } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
        e.preventDefault();
        next = (idx - 1 + tabArr.length) % tabArr.length;
      } else if (e.key === 'Home') {
        e.preventDefault();
        next = 0;
      } else if (e.key === 'End') {
        e.preventDefault();
        next = tabArr.length - 1;
      }

      if (next >= 0) {
        activateTab(tabArr[next]);
      }
    });
  }
}

function initCharts(root: ParentNode = document): void {
  root.querySelectorAll<HTMLElement>('.crtoday-chart-wrap').forEach(initChart);
}

/* ------------------------------------------------------------------ */
/*  MutationObserver — auto-init charts added to the DOM dynamically  */
/* ------------------------------------------------------------------ */

const observer = new MutationObserver((mutations) => {
  for (const mutation of mutations) {
    for (const node of mutation.addedNodes) {
      if (!(node instanceof HTMLElement)) continue;
      if (node.matches('.crtoday-chart-wrap')) {
        initChart(node);
      } else {
        node.querySelectorAll<HTMLElement>('.crtoday-chart-wrap').forEach(initChart);
      }
    }
  }
});

function startObserver(): void {
  initCharts();
  observer.observe(document.body, { childList: true, subtree: true });
}

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