import type { DateRange, DateValue } from 'reka-ui';
import type { Matcher } from 'reka-ui/date';

/**
 * Format options for weekday labels displayed in the calendar header.
 *
 * - `'narrow'` - Single letter (e.g., "M", "T", "W")
 * - `'short'` - Abbreviated (e.g., "Mon", "Tue", "Wed")
 * - `'long'` - Full name (e.g., "Monday", "Tuesday", "Wednesday")
 */
export type UiRangeCalendarWeekdayFormat = 'narrow' | 'short' | 'long';

/**
 * Day of the week to start the calendar on.
 *
 * - `0` - Sunday
 * - `1` - Monday
 * - `2` - Tuesday
 * - `3` - Wednesday
 * - `4` - Thursday
 * - `5` - Friday
 * - `6` - Saturday
 */
export type UiRangeCalendarWeekStartsOn = 0 | 1 | 2 | 3 | 4 | 5 | 6;

/**
 * A calendar for selecting date ranges (start and end dates). Use for
 * booking periods, vacation dates, or any range-based date selection.
 * @category Form Inputs
 * @useCases date range, booking period, vacation dates, filter by dates
 * @keywords calendar, range, daterange, period, booking, from, to, start, end
 * @related UiCalendar, UiPopover
 */
export interface UiRangeCalendarProps {
  /**
   * The controlled selected date range value.
   * Use with v-model for two-way binding.
   */
  modelValue?: DateRange;

  /**
   * The default selected date range when first rendered.
   * Use when you don't need controlled state.
   */
  defaultValue?: DateRange;

  /**
   * The placeholder date used to determine which month/year to display.
   * Defaults to today's date if not provided.
   * Use with `v-model:placeholder` for two-way binding.
   */
  placeholder?: DateValue;

  /**
   * The default placeholder date when first rendered.
   */
  defaultPlaceholder?: DateValue;

  /**
   * The minimum selectable date.
   * Dates before this will be disabled.
   */
  minValue?: DateValue;

  /**
   * The maximum selectable date.
   * Dates after this will be disabled.
   */
  maxValue?: DateValue;

  /**
   * Whether the calendar is disabled.
   * @default false
   */
  disabled?: boolean;

  /**
   * Whether the calendar is read-only.
   * Users can navigate but not select dates.
   * @default false
   */
  readonly?: boolean;

  /**
   * The locale to use for formatting dates and weekday names.
   * @default 'en'
   * @example 'de', 'fr', 'es'
   */
  locale?: string;

  /**
   * The day of the week to start on.
   * @default 0
   */
  weekStartsOn?: UiRangeCalendarWeekStartsOn;

  /**
   * The number of months to display at once.
   * @default 1
   */
  numberOfMonths?: number;

  /**
   * Whether to navigate by page (all visible months) or by single month.
   * @default false
   */
  pagedNavigation?: boolean;

  /**
   * The format to use for weekday labels.
   * @default 'narrow'
   */
  weekdayFormat?: UiRangeCalendarWeekdayFormat;

  /**
   * Whether to always show 6 weeks in the calendar.
   * Useful for consistent height.
   * @default false
   */
  fixedWeeks?: boolean;

  /**
   * Whether to prevent the user from deselecting a date without selecting another date first.
   * @default false
   */
  preventDeselect?: boolean;

  /**
   * The accessible label for the calendar.
   * Used for screen readers.
   */
  calendarLabel?: string;

  /**
   * If true, the calendar will focus the selected day, today, or the first day
   * of the month depending on what is visible when the calendar is mounted.
   * @default false
   */
  initialFocus?: boolean;

  /**
   * A function that returns whether or not a date is disabled.
   * Disabled dates cannot be selected.
   * @example (date) => date.dayOfWeek === 0 // Disable Sundays
   */
  isDateDisabled?: Matcher;

  /**
   * A function that returns whether or not a date is unavailable.
   * Unavailable dates are styled differently but may still be selectable.
   * @example (date) => isHoliday(date)
   */
  isDateUnavailable?: Matcher;

  /**
   * A function that returns the next page of the calendar.
   * Receives the current placeholder as an argument.
   */
  nextPage?: (placeholder: DateValue) => DateValue;

  /**
   * A function that returns the previous page of the calendar.
   * Receives the current placeholder as an argument.
   */
  prevPage?: (placeholder: DateValue) => DateValue;
}

/**
 * Emits for UiRangeCalendar component.
 */
export interface UiRangeCalendarEmits {
  /**
   * Emitted when the selected date range changes.
   */
  (e: 'update:modelValue', value: DateRange): void;

  /**
   * Emitted when the placeholder (displayed month/year) changes.
   */
  (e: 'update:placeholder', value: DateValue): void;
}

export type { DateRange, DateValue, Matcher };
