import * as React from 'react'
import { CalendarBlankIcon, XIcon } from '@phosphor-icons/react'
import * as PopoverPrimitive from '@radix-ui/react-popover'
import type { DateRange } from 'react-day-picker'
import { Popover, PopoverTrigger, PopoverContent } from './popover'
import { FieldLabel, FieldHint, FieldError } from './field'
import { cn } from '@/lib/utils'

/**
 * DateRangePicker — single popover trigger c react-day-picker calendar внутри,
 * выбор start/end в одном UI. Stage 3.8b: замена пары двух DatePicker'ов
 * (audit page from/to) на компактный range picker.
 *
 * <p>react-day-picker загружается lazily через React.lazy — модуль ~80kb gz
 * чтобы не утяжелять main bundle (DateRangePicker используется только на
 * audit page + filtering screens, не в каждом form'е).
 *
 * <p>Trigger показывает «{from} — {to}», или placeholder если пусто.
 * Clear button (X) появляется когда есть выбор.
 *
 * <p>API:
 * <ul>
 *   <li>value: {from?: Date, to?: Date} — undefined start/end OK (open range).</li>
 *   <li>onChange: ({from, to}) => void.</li>
 *   <li>locale: ru (default) или en — формат шапки месяца и weekday labels.</li>
 * </ul>
 */

// Lazy react-day-picker — компонент Suspense'ит calendar UI на open. До open
// bundle не подтягивается. Trigger button + state работают eager.
const DayPickerLazy = React.lazy(async () => {
  // Подгружаем компонент И стили (vite bundles css side-effect через `?inline`?
  // нет — обычный import достаточен, vite collect'ит css в build pipeline).
  const [{ DayPicker }] = await Promise.all([
    import('react-day-picker'),
    import('react-day-picker/style.css'),
  ])
  return { default: DayPicker }
})

export type DateRangePickerValue = {
  from?: Date
  to?: Date
}

export type DateRangePickerProps = {
  label?: React.ReactNode
  hint?: React.ReactNode
  error?: React.ReactNode
  required?: boolean
  /** Range value. undefined = пустой пик, partial = open-ended. */
  value?: DateRangePickerValue
  onChange?: (value: DateRangePickerValue) => void
  /** ru (default) или en — для weekday/month labels. */
  locale?: 'ru' | 'en'
  /** Min / max bounds. Calendar disables вне диапазона. */
  fromDate?: Date
  toDate?: Date
  /** Placeholder когда range пустой. */
  placeholder?: string
  /** Trigger button id. */
  id?: string
  disabled?: boolean
  rootClassName?: string
  triggerClassName?: string
}

const formatDateLabel = (d: Date | undefined, locale: 'ru' | 'en' = 'ru'): string => {
  if (!d) return ''
  return d.toLocaleDateString(locale === 'ru' ? 'ru-RU' : 'en-US', {
    day: '2-digit',
    month: '2-digit',
    year: 'numeric',
  })
}

export function DateRangePicker({
  label,
  hint,
  error,
  required,
  value,
  onChange,
  locale = 'ru',
  fromDate,
  toDate,
  placeholder,
  id,
  disabled,
  rootClassName,
  triggerClassName,
}: DateRangePickerProps) {
  const autoId = React.useId()
  const triggerId = id ?? autoId
  const hintId = hint ? `${triggerId}-hint` : undefined
  const errorId = error ? `${triggerId}-error` : undefined

  const fromLabel = formatDateLabel(value?.from, locale)
  const toLabel = formatDateLabel(value?.to, locale)
  const hasValue = Boolean(value?.from || value?.to)

  const display = hasValue
    ? `${fromLabel || '…'} — ${toLabel || '…'}`
    : placeholder ?? (locale === 'ru' ? 'Выберите период' : 'Pick a range')

  // react-day-picker DateRange type uses `from`/`to` тоже — direct passthrough.
  const dpRange: DateRange | undefined = hasValue
    ? { from: value?.from, to: value?.to }
    : undefined

  const handleSelect = (next: DateRange | undefined) => {
    if (!next) {
      onChange?.({})
      return
    }
    onChange?.({ from: next.from, to: next.to })
  }

  const handleClear = (e: React.MouseEvent) => {
    e.stopPropagation()
    e.preventDefault()
    onChange?.({})
  }

  return (
    <div className={cn('flex flex-col gap-1', rootClassName)}>
      {label && (
        <FieldLabel htmlFor={triggerId} required={required}>
          {label}
        </FieldLabel>
      )}
      <Popover>
        <PopoverTrigger asChild>
          <button
            type="button"
            id={triggerId}
            disabled={disabled}
            aria-invalid={error ? true : undefined}
            aria-describedby={[hintId, errorId].filter(Boolean).join(' ') || undefined}
            className={cn(
              'flex items-center justify-between gap-2 h-9 w-full rounded-md border border-line bg-surface px-3 text-body text-ink',
              'hover:border-line-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
              'disabled:cursor-not-allowed disabled:opacity-50',
              error && 'border-pink focus-visible:ring-pink/40',
              triggerClassName,
            )}
          >
            <span className="flex items-center gap-2 flex-1 min-w-0">
              <CalendarBlankIcon size={14} weight="regular" className="shrink-0 text-mute" />
              <span className={cn('truncate', !hasValue && 'text-mute')}>{display}</span>
            </span>
            {hasValue && !disabled && (
              <span
                role="button"
                aria-label={locale === 'ru' ? 'Очистить' : 'Clear'}
                onClick={handleClear}
                className="shrink-0 rounded-sm p-0.5 text-mute hover:text-ink hover:bg-surface-2"
              >
                <XIcon size={12} weight="bold" />
              </span>
            )}
          </button>
        </PopoverTrigger>
        <PopoverContent align="start" className="p-3">
          <PopoverPrimitive.Close className="hidden" />
          <React.Suspense
            fallback={
              <div className="h-64 w-64 flex items-center justify-center text-mute text-cap">
                {locale === 'ru' ? 'Загрузка календаря…' : 'Loading calendar…'}
              </div>
            }
          >
            <DayPickerLazy
              mode="range"
              selected={dpRange}
              onSelect={handleSelect}
              numberOfMonths={2}
              showOutsideDays
              startMonth={fromDate}
              endMonth={toDate}
              weekStartsOn={1}
              // ISO 8601 weekday order matches RU calendar convention; en тоже
              // OK (просто Monday first). Если когда-нибудь нужен Sunday-first
              // — отдельный prop.
              className="ord-day-picker"
            />
          </React.Suspense>
        </PopoverContent>
      </Popover>
      {hint && !error && <FieldHint id={hintId}>{hint}</FieldHint>}
      {error && <FieldError id={errorId}>{error}</FieldError>}
    </div>
  )
}
