/**
 * `@platform-modules/util/datetime` — civil-date resolution in an IANA time zone.
 *
 * Pure `Intl` (zero-dep, Workers-safe). This leaf answers exactly one question:
 * "what calendar date is this instant, in this zone?" — no display formatting
 * (that is `@platform-modules/i18n/format`'s axis), no `util/timezone` import
 * (so an R-only consumer tree-shakes the validation leaf away).
 *
 * The inverse (civil wall-time → instant, via a DST offset-fixpoint) is a designed-next
 * sibling, not yet built — adding it here later is non-breaking.
 */

/** Thrown when `instant` is not a valid `Date` (e.g. `new Date('nope')`). */
export class InvalidInstantError extends Error {
  constructor() {
    super('civilDateInZone: instant must be a valid Date')
    this.name = 'InvalidInstantError'
  }
}

/** Thrown when `zone` is not a runtime-recognized IANA time zone. */
export class InvalidTimeZoneError extends Error {
  constructor(zone: string) {
    super(`civilDateInZone: unknown IANA time zone: ${JSON.stringify(zone)}`)
    this.name = 'InvalidTimeZoneError'
  }
}

/**
 * The civil calendar date (`YYYY-MM-DD`) that `instant` falls on in `zone`.
 *
 * Uses the production-proven, pinned `en-CA` locale with explicit numeric fields → ISO order,
 * zero-padded, Gregorian, Latin digits on every runtime. Validate at the trust boundary:
 * a non-valid `Date` or unknown zone throws, never returns a wrong / `Invalid Date` string.
 */
export function civilDateInZone(instant: Date, zone: string): string {
  if (Number.isNaN(instant.getTime())) throw new InvalidInstantError()
  let formatter: Intl.DateTimeFormat
  try {
    formatter = new Intl.DateTimeFormat('en-CA', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      timeZone: zone,
    })
  } catch {
    throw new InvalidTimeZoneError(zone)
  }
  return formatter.format(instant)
}
