/* ============================================================
   RC-PAGE-013 — Canonical 16-range comparison math.
   Given a preset + anchor date + comparison mode, returns
   { start, end, priorStart, priorEnd } as local Date objects.
   ============================================================ */

// Anchor — in a real app this is "today". We use a fixed anchor so
// the static fixtures line up with DATE_RANGES labels above.
const ANCHOR = new Date(2026, 3, 22); // Apr 22, 2026 (month 0-indexed)

const d = (y, m, day) => new Date(y, m, day);
const addDays = (dt, n) => { const r = new Date(dt); r.setDate(r.getDate() + n); return r; };
const addMonths = (dt, n) => { const r = new Date(dt); r.setMonth(r.getMonth() + n); return r; };
const addYears = (dt, n) => { const r = new Date(dt); r.setFullYear(r.getFullYear() + n); return r; };
const daysBetween = (a, b) => Math.round((b - a) / 86400000) + 1;
const startOfMonth = (dt) => new Date(dt.getFullYear(), dt.getMonth(), 1);
const endOfMonth = (dt) => new Date(dt.getFullYear(), dt.getMonth() + 1, 0);
const startOfWeek = (dt) => { const r = new Date(dt); r.setDate(dt.getDate() - dt.getDay()); return r; }; // Sun-start

/* PRESET → current {start, end} */
function presetRange(preset, anchor = ANCHOR) {
  switch (preset) {
    case 'wtd':       return { start: startOfWeek(anchor),                     end: anchor };
    case 'lastWeek': {
      const thisSun = startOfWeek(anchor);
      return { start: addDays(thisSun, -7), end: addDays(thisSun, -1) };
    }
    case 'mtd':       return { start: startOfMonth(anchor),                    end: anchor };
    case 'lastMonth': { const s = startOfMonth(addMonths(anchor, -1)); return { start: s, end: endOfMonth(s) }; }
    case 'l7':        return { start: addDays(anchor, -6),                     end: anchor };
    case 'l30':       return { start: addDays(anchor, -29),                    end: anchor };
    case 'l60':       return { start: addDays(anchor, -59),                    end: anchor };
    case 'l90':       return { start: addDays(anchor, -89),                    end: anchor };
    case 'l6m':       return { start: addMonths(anchor, -6),                   end: anchor };
    case 't12m':      return { start: startOfMonth(addMonths(anchor, -12)),    end: endOfMonth(addMonths(anchor, -1)) };
    case 't12mPlusMtd': return { start: startOfMonth(addMonths(anchor, -12)),  end: anchor };
    case 'ytd':       return { start: d(anchor.getFullYear(), 0, 1),           end: anchor };
    default:          return { start: addDays(anchor, -29), end: anchor };
  }
}

/* 16-RANGE COMPARISON MATH — RC-PAGE-013 authoritative table.
   mode: 'pp' | 'py' | 'none' */
function comparisonRange(preset, mode, anchor = ANCHOR) {
  if (mode === 'none') return { start: null, end: null };
  const { start, end } = presetRange(preset, anchor);
  const len = daysBetween(start, end);

  if (mode === 'py') {
    // Prior Year — shift by 1 year, preserve shape (incl. partial month end).
    return { start: addYears(start, -1), end: addYears(end, -1) };
  }

  // Prior Period: shape-preserving offset
  switch (preset) {
    case 'mtd': {
      // Same # days into prior month
      const prevMonthStart = startOfMonth(addMonths(start, -1));
      return { start: prevMonthStart, end: addDays(prevMonthStart, len - 1) };
    }
    case 'wtd': {
      const prevWeekStart = addDays(start, -7);
      return { start: prevWeekStart, end: addDays(prevWeekStart, len - 1) };
    }
    case 'lastMonth': {
      const prevStart = startOfMonth(addMonths(start, -1));
      return { start: prevStart, end: endOfMonth(prevStart) };
    }
    case 'lastWeek': {
      return { start: addDays(start, -7), end: addDays(end, -7) };
    }
    case 'ytd': {
      // Prior year same-to-date
      return { start: d(start.getFullYear() - 1, 0, 1), end: addYears(end, -1) };
    }
    case 't12m': {
      return { start: addYears(start, -1), end: addYears(end, -1) };
    }
    case 't12mPlusMtd': {
      return { start: addYears(start, -1), end: addYears(end, -1) };
    }
    case 'l6m': {
      return { start: addMonths(start, -6), end: addMonths(end, -6) };
    }
    default: {
      // rolling N-day windows: shift back by length
      return { start: addDays(start, -len), end: addDays(end, -len) };
    }
  }
}

/* Format helper — MM/DD/YY */
function fmtShort(dt) {
  if (!dt) return '—';
  const mm = String(dt.getMonth() + 1).padStart(2, '0');
  const dd = String(dt.getDate()).padStart(2, '0');
  const yy = String(dt.getFullYear()).slice(-2);
  return `${mm}/${dd}/${yy}`;
}

/* Canonical range label — "Apr 1 → Apr 22" */
function fmtRangeLabel(start, end) {
  if (!start || !end) return '—';
  const m = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
  const sameYear = start.getFullYear() === end.getFullYear();
  const sameMonth = sameYear && start.getMonth() === end.getMonth();
  if (sameMonth) return `${m[start.getMonth()]} ${start.getDate()} – ${end.getDate()}, ${end.getFullYear()}`;
  if (sameYear) return `${m[start.getMonth()]} ${start.getDate()} – ${m[end.getMonth()]} ${end.getDate()}, ${end.getFullYear()}`;
  return `${m[start.getMonth()]} ${start.getDate()}, ${start.getFullYear()} – ${m[end.getMonth()]} ${end.getDate()}, ${end.getFullYear()}`;
}

Object.assign(window, {
  RC_ANCHOR: ANCHOR,
  presetRange,
  comparisonRange,
  fmtShort,
  fmtRangeLabel,
});
