import {
  type CalendarDate,
  parseDate,
  toCalendarDate,
} from "@internationalized/date";
import { useCallback } from "react";
import type { DateValue } from "@react-aria/datepicker";

/** ISO 8601 formatted date string. */
export type DateString = string;

export function useStringAdapters({
  stringDefaultValue,
  stringValue,
  onChangeString,
  stringMinValue,
  stringMaxValue,
}: {
  stringDefaultValue?: DateString;
  stringValue?: DateString;
  onChangeString?: (event: { target: { value: DateString } }) => void;
  stringMinValue?: DateString;
  stringMaxValue?: DateString;
}) {
  const defaultValue = parseDateMaybe(stringDefaultValue);
  const minValue = parseDateMaybe(stringMinValue) ?? undefined;
  const maxValue = parseDateMaybe(stringMaxValue) ?? undefined;

  const value = parseDateMaybe(stringValue);

  const onChange = useCallback(
    (newDate: DateValue | null) =>
      onChangeString?.({ target: { value: newDate?.toString() ?? "" } }),
    [onChangeString]
  );

  return { defaultValue, value, onChange, minValue, maxValue };
}

/** Try to parse a nullish or potentially malformed ISO 8601 date string. */
function parseDateMaybe<NullType extends undefined | null>(
  date: DateString | NullType
): CalendarDate | NullType | null {
  let pureDate = date;
  if (date?.includes("T")) {
    pureDate = date.split("T")[0];
  }

  try {
    return pureDate == null ? pureDate : toCalendarDate(parseDate(pureDate));
  } catch {
    return null;
  }
}
