/**
 * Browser side: picks the right days for the chosen range using the visitor's
 * current date (so a page built last night still shows "today" correctly),
 * and refreshes open/closed status.
 */
import { addDays, dayKey, TZ } from './time';
import { openStatus } from './view';
import type { Hours } from './types';

type Range = 'today' | 'weekend' | 'week';
const RANGES: Range[] = ['today', 'weekend', 'week'];
const SUFFIX: Record<Range, string> = { today: 'today', weekend: 'this weekend', week: 'in the next 7 days' };

function nowInGainesville() {
  const now = new Date();
  const parts = new Intl.DateTimeFormat('en-US', { timeZone: TZ, weekday: 'short', hour: 'numeric', minute: 'numeric', hourCycle: 'h23' }).formatToParts(now);
  const get = (t: string) => parts.find((p) => p.type === t)!.value;
  return {
    now,
    today: dayKey(now),
    dow: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].indexOf(get('weekday')),
    minutes: Number(get('hour')) * 60 + Number(get('minute')),
  };
}

function daysFor(range: Range, today: string, dow: number): Set<string> {
  const span = (start: string, n: number) => new Set(Array.from({ length: n }, (_, i) => addDays(start, i)));
  if (range === 'today') return span(today, 1);
  if (range === 'week') return span(today, 7);
  // Weekend = Friday–Sunday. During the weekend, from today through Sunday.
  if (dow === 0) return span(today, 1);
  if (dow >= 5) return span(today, 7 - dow + 1);
  return span(addDays(today, 5 - dow), 3);
}

const plural = (n: number, one: string, many: string) => `${n} ${n === 1 ? one : many}`;

export function initPage() {
  const t = nowInGainesville();
  const buttons = [...document.querySelectorAll<HTMLButtonElement>('[data-set-range]')];
  const articles = [...document.querySelectorAll<HTMLElement>('article.brewery')];
  const summary = document.querySelector<HTMLElement>('[data-summary]');

  const dateline = document.querySelector<HTMLElement>('[data-dateline]');
  if (dateline) {
    dateline.textContent = new Intl.DateTimeFormat('en-US', { timeZone: TZ, weekday: 'long', month: 'long', day: 'numeric' }).format(t.now);
  }

  function apply(range: Range) {
    const days = daysFor(range, t.today, t.dow);
    document.body.dataset.range = range;
    for (const btn of buttons) btn.setAttribute('aria-pressed', String(btn.dataset.setRange === range));

    let food = 0;
    let events = 0;
    for (const art of articles) {
      for (const col of art.querySelectorAll<HTMLElement>('.col-food, .col-events')) {
        let shown = 0;
        for (const g of col.querySelectorAll<HTMLElement>('.day')) {
          const on = days.has(g.dataset.day!);
          g.hidden = !on;
          if (on) shown += g.querySelectorAll('.item').length;
        }
        const empty = col.querySelector<HTMLElement>('.empty');
        if (empty) empty.hidden = shown > 0;
        if (col.classList.contains('col-food')) food += shown;
        else events += shown;
      }
    }
    if (summary) {
      summary.textContent = `${plural(food, 'food truck', 'food trucks')} and ${plural(events, 'event', 'events')} at ${articles.length} breweries ${SUFFIX[range]}.`;
    }
  }

  function setRange(range: Range, push = true) {
    apply(range);
    if (push) {
      const url = range === 'today' ? location.pathname : `#${range}`;
      history.replaceState(null, '', url);
    }
  }

  for (const btn of buttons) btn.addEventListener('click', () => setRange(btn.dataset.setRange as Range));

  const fromHash = location.hash.slice(1) as Range;
  let initial: Range = 'today';
  if (RANGES.includes(fromHash)) initial = fromHash;
  setRange(initial, false);

  // Open / closed, as of right now.
  for (const art of articles) {
    const el = art.querySelector<HTMLElement>('[data-status]');
    const raw = art.dataset.hours;
    if (!el || !raw) continue;
    const s = openStatus(JSON.parse(raw) as Hours, t.dow, t.minutes);
    if (s) {
      el.textContent = s.text;
      el.dataset.open = String(s.open);
    }
  }
}
