/**
 * Grid snapping utilities for the planning grid drag/resize system.
 *
 * All dates are handled as local-timezone strings ('YYYY-MM-DD') to avoid
 * UTC-shift bugs. Never use toISOString() for date keys.
 */

/** Width constants — must match planning-grid.tsx. */
export const SNAP_NAME_COL_W = 160
export const SNAP_DAY_COL_W  = 40

/**
 * Converts a mouse clientX position to a 0-based day-column index.
 * tableRect must come from tableEl.getBoundingClientRect() — viewport-relative,
 * so scroll position is already factored in.
 *
 * Returns a raw (potentially out-of-bounds) index; callers must clamp it.
 */
export function snapDayIndex(
  clientX: number,
  tableRect: DOMRect,
  nameColW = SNAP_NAME_COL_W,
  dayColW  = SNAP_DAY_COL_W,
): number {
  return Math.floor((clientX - tableRect.left - nameColW) / dayColW)
}

/**
 * Returns the number of calendar days between two date keys (inclusive).
 * E.g. calculateDuration('2025-01-06', '2025-01-10') === 5
 */
export function calculateDuration(startKey: string, endKey: string): number {
  const s = new Date(startKey + 'T00:00:00').getTime()
  const e = new Date(endKey   + 'T00:00:00').getTime()
  return Math.round((e - s) / 86_400_000) + 1
}

/**
 * Shifts a date key by `deltaDays` calendar days (positive = forward).
 * Preserves local timezone — does NOT use toISOString().
 */
export function offsetDateKey(dateKey: string, deltaDays: number): string {
  const d = new Date(dateKey + 'T00:00:00')
  d.setDate(d.getDate() + deltaDays)
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
}

/**
 * Shifts both start and end dates by the same delta, preserving duration.
 */
export function offsetDates(
  startKey: string,
  endKey:   string,
  deltaDays: number,
): { start: string; end: string } {
  return {
    start: offsetDateKey(startKey, deltaDays),
    end:   offsetDateKey(endKey,   deltaDays),
  }
}
