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

/**
 * Selection mode for the date picker.
 *
 * - `'single'` - Select a single date
 * - `'range'` - Select a date range (start and end dates)
 */
export type UiDatePickerMode = 'single' | 'range';

/**
 * Layout options for the calendar header in the date picker.
 * Controls which dropdown selectors are shown for quick navigation.
 *
 * - `'month-and-year'` - Show dropdowns for both month and year
 * - `'month-only'` - Show dropdown for month only
 * - `'year-only'` - Show dropdown for year only
 */
export type UiDatePickerLayout = 'month-and-year' | 'month-only' | 'year-only';

/**
 * 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 UiDatePickerWeekdayFormat = '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 UiDatePickerWeekStartsOn = 0 | 1 | 2 | 3 | 4 | 5 | 6;

/**
 * A date picker combining a button trigger with a popover calendar.
 * Provides an accessible way to select dates or date ranges.
 * @category Form Inputs
 * @useCases date selection, booking form, event picker, schedule, deadline
 * @keywords date, picker, calendar, datepicker, range, schedule
 * @related UiCalendar, UiPopover
 */
export interface UiDatePickerProps {
  /**
   * Additional CSS classes to apply to the trigger button.
   */
  class?: HTMLAttributes['class'];

  /**
   * The controlled open state of the popover.
   *
   * - Omit for uncontrolled mode (the component manages its own open state)
   * - Use `v-model:open` for controlled mode
   */
  open?: boolean;

  /**
   * The selection mode of the date picker.
   * - `'single'` - Select a single date (default)
   * - `'range'` - Select a date range
   * @default 'single'
   */
  mode?: UiDatePickerMode;

  /**
   * The controlled selected date value (for mode='single').
   * Use with v-model for two-way binding.
   */
  modelValue?: DateValue | DateRange;

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

  /**
   * Placeholder text displayed when no date is selected.
   * @default 'Pick a date' (single mode)
   * @default 'Pick a date range' (range mode)
   */
  placeholder?: string;

  /**
   * 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 date picker is disabled.
   * @default false
   */
  disabled?: boolean;

  /**
   * Whether the date picker is read-only.
   * Users can view but not change the selected date.
   * @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?: UiDatePickerWeekStartsOn;

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

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

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

  /**
   * Layout mode for the calendar header.
   * Controls dropdown selectors for quick month/year navigation.
   * When undefined, shows simple text heading.
   */
  layout?: UiDatePickerLayout;

  /**
   * 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;

  /**
   * 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;

  /**
   * The format to use when displaying the selected date.
   * Uses Intl.DateTimeFormat options.
   * @default { dateStyle: 'long' }
   */
  dateFormat?: Intl.DateTimeFormatOptions;

  /**
   * Whether to close the popover after selecting a date.
   * - In 'single' mode: Closes after selecting a date
   * - In 'range' mode: Closes after selecting both start and end dates
   * @default true
   */
  closeOnSelect?: boolean;

  /**
   * Whether to navigate by page (all visible months) or by single month.
   * Only applicable in range mode when numberOfMonths > 1.
   * @default false
   */
  pagedNavigation?: boolean;

  /**
   * Accessible label for the trigger button.
   * Applied as `aria-label` attribute.
   */
  ariaLabel?: string;

  /**
   * The separator string displayed between start and end dates in range mode.
   * @default ' - '
   */
  rangeSeparator?: string;
}

export type { DateRange, DateValue, Matcher };
