// ------------------------------------------------------------------------
//  events.js - Cosmic & weather event engine for SunScope.
//
//  This is the public-facing barrel module. It composes the smaller files
//  under ./events/ and exposes the same API as before, so callers
//  (app.js, components.js) keep working without changes.
//
//  Returns the "active event" (or null) based on:
//    1. PROMO_OVERRIDE  - manually set a message for promotions etc.
//    2. Hardcoded cosmic calendar (eclipses, meteor showers, alignments)
//    3. Weather-derived events (stargazing, sunset, heat spike, storm)
//
//  To set a promo banner, edit PROMO_OVERRIDE below.
//  Set it back to null when done.
//
//  Each event object:
//    { id, emoji, title, message, color, textColor, type }
//
//  type: 'cosmic' | 'weather' | 'promo'
//
//  Where to find things:
//    Cosmic calendar data ........ ./events/cosmic-calendar.js
//    Almanac calendar data ....... ./events/almanac-calendar.js
//    Weather check functions ..... ./events/weather-checks.js
//    Dynamic message helper ...... ./events/dynamic-message.js
//    Lens overlay SVG renderer ... ./events/lens-overlay.js
// ------------------------------------------------------------------------

import { COSMIC_CALENDAR } from './events/cosmic-calendar.js';
import {
  checkStargazing,
  checkSunset,
  checkHeatSpike,
  checkWind,
  checkWet,
  checkStorm,
  checkFrost,
} from './events/weather-checks.js';
import { dynamicCosmicMessage } from './events/dynamic-message.js';

// Re-export so callers that imported these from events.js keep working.
export { getUpcomingEvents } from './events/almanac-calendar.js';
export { getLensOverlaySVG } from './events/lens-overlay.js';

// --- PROMO OVERRIDE ------------------------------------------------------
// Set this to show a custom banner regardless of weather or cosmic events.
// Leave as null for automatic event detection.
//
// Example:
//   export const PROMO_OVERRIDE = {
//     id: 'promo-summer',
//     emoji: '--',
//     title: 'Summer Sale',
//     message: 'SunScope Extra - 20% off this weekend only.',
//     color: '#c8922a',
//     textColor: '#fff',
//     type: 'promo',
//   };
//
export const PROMO_OVERRIDE = null;

// --- CELL TAG LOGIC ------------------------------------------------------
// Returns the subset of active events that should show an icon for this row.
export function getCellTagEvents(events, row) {
  if (!events || events.length === 0) return [];
  return events.filter(ev => {
    if (ev.type === 'promo') return false;
    if (ev.nightOnly && row.elev >= -5) return false;
    if (ev.id === 'heat-spike' && row.elev < 0) return false;
    // Sunset/sunrise events: only show icon during the actual twilight window.
    // For bucketed table rows the span is [row.iso .. row.isoEnd]; show the
    // icon if the event window overlaps that span at all.
    if (ev.isoRange) {
      const hi = row.isoEnd || row.iso;
      if (hi < ev.isoRange[0] || row.iso > ev.isoRange[1]) return false;
    }
    return true;
  });
}

// --- BANNER PRIORITY -----------------------------------------------------
// Weather event IDs that are safety-relevant and should always appear as the
// first banner slide, ahead of cosmic events and lower-priority weather items.
const PRIORITY_WEATHER_IDS = new Set(['heat-spike', 'frost', 'storm', 'wind', 'wet']);

// --- MAIN EXPORT ---------------------------------------------------------
// Returns ALL active events for the given rows/date as an array.
// Empty array = nothing active.
//
// Order within array:
//   1. PROMO_OVERRIDE (if set, returned alone)
//   2. Priority weather events (heat spike, frost, storm) — always slide 1
//   3. All matching cosmic calendar events for this date
//   4. Remaining weather-derived events (sunset, stargazing, …)

export function getActiveEvents(rows, location) {
  // 1. Manual promo override - shown alone, no mixing with other events
  if (PROMO_OVERRIDE) return [PROMO_OVERRIDE];

  // 2. Cosmic calendar - use the date of the rows being viewed, not today.
  const dateStr = (rows && rows.length > 0)
    ? rows[0].iso.slice(0, 10)
    : new Date().toISOString().slice(0, 10);
  const cosmicHits = COSMIC_CALENDAR
    .filter(ev => dateStr >= ev.start && dateStr <= ev.end)
    .map(ev => Object.assign({}, ev, { message: dynamicCosmicMessage(ev, dateStr) }));

  // 3. Weather-derived events (all that match, not just first)
  const weatherEvents = [];
  if (rows && rows.length > 0) {
    const checks = [
      checkHeatSpike(rows),
      checkStorm(rows),
      checkWind(rows),
      checkWet(rows),
      checkFrost(rows),
      checkSunset(rows, location),
      checkStargazing(rows),
    ];
    checks.forEach(ev => { if (ev) weatherEvents.push(ev); });
  }

  // Sort so priority weather warnings (heat, frost, storm) always lead,
  // then cosmic events, then the remaining weather items.
  const priorityWeather = weatherEvents.filter(ev => PRIORITY_WEATHER_IDS.has(ev.id));
  const otherWeather    = weatherEvents.filter(ev => !PRIORITY_WEATHER_IDS.has(ev.id));

  return [...priorityWeather, ...cosmicHits, ...otherWeather];
}

// --- LENS EVENT PICKER ---------------------------------------------------
// From an array of active events, returns the single one closest to its peak
// (most "intense"). Weather events without a peak use today's date.
// Returns null if events array is empty.

export function getLensEvent(events) {
  if (!events || events.length === 0) return null;
  if (events.length === 1) return events[0];
  const today = new Date().toISOString().slice(0, 10);
  return events.reduce((best, ev) => {
    const peakB = best.peak || today;
    const peakE = ev.peak || today;
    const distB = Math.abs(new Date(today) - new Date(peakB));
    const distE = Math.abs(new Date(today) - new Date(peakE));
    return distE < distB ? ev : best;
  });
}
