// Adapted from jalcoui (MIT) — github.com/jal-co/ui

import type { ActivityEntry } from './types';
import { GAP } from './types';

export interface WeekDay {
  date: Date;
  count: number;
}

/**
 * Bucket the supplied entries into a fixed-size grid that ends on the
 * current week and spans `weekCount` weeks. Missing dates fill with 0.
 */
export function buildWeeks(data: ActivityEntry[], weekCount: number): WeekDay[][] {
  const countMap = new Map<string, number>();
  for (const entry of data) {
    countMap.set(entry.date, (countMap.get(entry.date) ?? 0) + entry.count);
  }

  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const todayDay = today.getDay();

  const endOfWeek = new Date(today);
  endOfWeek.setDate(today.getDate() + (6 - todayDay));

  const totalDays = weekCount * 7;
  const startDate = new Date(endOfWeek);
  startDate.setDate(endOfWeek.getDate() - totalDays + 1);

  const weeks: WeekDay[][] = [];
  let currentWeek: WeekDay[] = [];

  for (let i = 0; i < totalDays; i++) {
    const d = new Date(startDate);
    d.setDate(startDate.getDate() + i);
    const key = d.toISOString().slice(0, 10);
    currentWeek.push({ date: d, count: countMap.get(key) ?? 0 });

    if (currentWeek.length === 7) {
      weeks.push(currentWeek);
      currentWeek = [];
    }
  }

  if (currentWeek.length > 0) {
    weeks.push(currentWeek);
  }

  return weeks;
}

/**
 * Find the column offset for the first week of every new month. Used to
 * lay month labels along the top of the grid.
 */
export function getMonthLabels(
  weeks: WeekDay[][],
  blockSize: number,
): { label: string; offset: number }[] {
  const months: { label: string; offset: number }[] = [];
  let lastKey = '';

  for (let w = 0; w < weeks.length; w++) {
    const firstDay = weeks[w][0];
    const key = `${firstDay.date.getFullYear()}-${firstDay.date.getMonth()}`;

    if (key !== lastKey) {
      months.push({
        label: firstDay.date.toLocaleString('en-US', { month: 'short' }),
        offset: w * (blockSize + GAP),
      });
      lastKey = key;
    }
  }

  return months;
}

export function formatDate(date: Date): string {
  return date.toLocaleDateString('en-US', {
    weekday: 'short',
    month: 'short',
    day: 'numeric',
    year: 'numeric',
  });
}
