/**
 * Resolution-date helper — classifies and formats a raw per-metric
 * `resolution_date` value for read-only display in the asset sidebar.
 *
 * Spec: .kiro/specs/compliance-metric-estimated-resolution-date
 * Requirements: 1.1, 1.4, 1.6, 2.1
 *
 * Pure and deterministic: the result depends only on `raw`. It does not read
 * the system clock, timezone, or locale. Validation is strict YYYY-MM-DD with
 * a real-calendar-date check (correct month lengths and leap years), which
 * matches how the value is produced by the <input type="date"> editor.
 */

// Display constants (single source of truth for component + tests)
export const RESOLUTION_DATE_LABEL = 'Est. Resolution';
export const NO_DATE_PLACEHOLDER = 'not set';
export const INVALID_DATE_PLACEHOLDER = 'invalid date';

// Strict YYYY-MM-DD shape: four-digit year, two-digit month, two-digit day.
const YMD_SHAPE = /^\d{4}-\d{2}-\d{2}$/;

/**
 * Returns the number of days in the given month for the given year,
 * accounting for leap years. `month` is 1-based (1 = January).
 *
 * @param {number} year
 * @param {number} month - 1-based month (1–12)
 * @returns {number} days in that month
 */
function daysInMonth(year, month) {
  // Leap year: divisible by 4, except centuries not divisible by 400.
  const isLeap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
  const lengths = [31, isLeap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  return lengths[month - 1];
}

/**
 * Classify and format a raw per-metric resolution_date value for display.
 *
 * @param {string|null|undefined} raw - the metric's resolution_date field
 * @returns {{ state: 'set', value: string } | { state: 'none' } | { state: 'invalid' }}
 *   - { state: 'set', value }  the value is a valid calendar date; `value` is YYYY-MM-DD
 *   - { state: 'none' }        the value is null, undefined, empty, or whitespace-only
 *   - { state: 'invalid' }     the value is non-empty but not a valid calendar date
 */
export function formatResolutionDate(raw) {
  // Null/undefined → no date set.
  if (raw === null || raw === undefined) {
    return { state: 'none' };
  }

  // Anything that is not a string is treated as not-a-valid-date once it is
  // non-empty; coerce defensively so the helper never throws on bad input.
  if (typeof raw !== 'string') {
    return { state: 'invalid' };
  }

  const trimmed = raw.trim();

  // Empty or whitespace-only → no date set.
  if (trimmed === '') {
    return { state: 'none' };
  }

  // Must match the strict YYYY-MM-DD shape.
  // Also accept ISO datetime strings (e.g. "2026-07-03T00:00:00.000Z") by
  // extracting the date prefix — the pg driver returns DATE columns this way.
  let candidate = trimmed;
  if (!YMD_SHAPE.test(candidate) && /^\d{4}-\d{2}-\d{2}T/.test(candidate)) {
    candidate = candidate.slice(0, 10);
  }
  if (!YMD_SHAPE.test(candidate)) {
    return { state: 'invalid' };
  }

  // Shape is correct; verify it is a real calendar date.
  const year = Number(candidate.slice(0, 4));
  const month = Number(candidate.slice(5, 7));
  const day = Number(candidate.slice(8, 10));

  if (month < 1 || month > 12) {
    return { state: 'invalid' };
  }

  if (day < 1 || day > daysInMonth(year, month)) {
    return { state: 'invalid' };
  }

  // Valid calendar date; the candidate value is the canonical
  // zero-padded YYYY-MM-DD form.
  return { state: 'set', value: candidate };
}
