'use client'

import * as React from 'react'
import type { DateRange } from 'react-day-picker'
import { Button } from '@admin/components/ui/button'
import { Calendar } from '@admin/components/ui/calendar'
import { Input } from '@admin/components/ui/input'
import { Popover, PopoverContent, PopoverTrigger } from '@admin/components/ui/popover'
import { buildDateRange } from '@admin/utils/date/build-date-range'
import { DATE_RANGE_END_TIME } from '@admin/utils/date/date-range-end-time'
import { DATE_RANGE_START_TIME } from '@admin/utils/date/date-range-start-time'
import { formatDateRangeInputDate } from '@admin/utils/date/format-date-range-input-date'
import { formatDateRangeParamDate } from '@admin/utils/date/format-date-range-param-date'
import { getDateRangeTriggerLabel } from '@admin/utils/date/get-date-range-trigger-label'
import { getOrderedDateRange } from '@admin/utils/date/get-ordered-date-range'
import { normalizeDateRangeTime } from '@admin/utils/date/normalize-date-range-time'
import { parseDateInputValue } from '@admin/utils/date/parse-date-input-value'
import { parseEditableDateRangeDate } from '@admin/utils/date/parse-editable-date-range-date'
import { cn } from '@admin/utils/shared/cn'
import { CalendarIcon, ChevronDown, CornerDownLeft } from 'lucide-react'

interface DateRangePickerProps {
  from?: string
  to?: string
  onChange?: (range: { from?: string; to?: string; fromTime?: string; toTime?: string }) => void
  disabled?: boolean
  placeholder?: string
  className?: string
}

export function DateRangePicker({
  from,
  to,
  onChange,
  disabled,
  placeholder = 'Pick a date range',
  className
}: DateRangePickerProps) {
  const [open, setOpen] = React.useState(false)
  const [draftRange, setDraftRange] = React.useState<DateRange | undefined>(() =>
    buildDateRange(from, to)
  )
  const [fromInput, setFromInput] = React.useState(() =>
    formatDateRangeInputDate(parseDateInputValue(from))
  )
  const [toInput, setToInput] = React.useState(() =>
    formatDateRangeInputDate(parseDateInputValue(to))
  )
  const [fromTime, setFromTime] = React.useState(DATE_RANGE_START_TIME)
  const [toTime, setToTime] = React.useState(DATE_RANGE_END_TIME)
  const [calendarMonth, setCalendarMonth] = React.useState<Date | undefined>(
    () => parseDateInputValue(from) ?? parseDateInputValue(to)
  )

  const committedFrom = parseDateInputValue(from)
  const committedTo = parseDateInputValue(to)
  const triggerLabel = getDateRangeTriggerLabel(committedFrom, committedTo, placeholder)

  const syncDraftFromProps = () => {
    const nextRange = buildDateRange(from, to)
    setDraftRange(nextRange)
    setFromInput(formatDateRangeInputDate(nextRange?.from))
    setToInput(formatDateRangeInputDate(nextRange?.to))
    setFromTime(DATE_RANGE_START_TIME)
    setToTime(DATE_RANGE_END_TIME)
    setCalendarMonth(nextRange?.from ?? nextRange?.to)
  }

  const handleApply = () => {
    const orderedRange = getOrderedDateRange({
      from: parseEditableDateRangeDate(fromInput) ?? draftRange?.from,
      to: parseEditableDateRangeDate(toInput) ?? draftRange?.to
    })

    onChange?.({
      from: orderedRange?.from ? formatDateRangeParamDate(orderedRange.from) : undefined,
      to: orderedRange?.to ? formatDateRangeParamDate(orderedRange.to) : undefined,
      fromTime: normalizeDateRangeTime(fromTime, DATE_RANGE_START_TIME),
      toTime: normalizeDateRangeTime(toTime, DATE_RANGE_END_TIME)
    })
    setOpen(false)
  }

  const handleRangeSelect = (nextRange: DateRange | undefined, selectedDay?: Date) => {
    const nextDraftRange =
      draftRange?.from && draftRange.to && selectedDay
        ? { from: selectedDay, to: undefined }
        : nextRange
    const orderedRange = getOrderedDateRange(nextDraftRange)
    setDraftRange(orderedRange)
    setFromInput(formatDateRangeInputDate(orderedRange?.from))
    setToInput(formatDateRangeInputDate(orderedRange?.to))
    setCalendarMonth(orderedRange?.from ?? orderedRange?.to)
  }

  const handleDateInputChange = (field: 'from' | 'to', value: string) => {
    const parsedDate = parseEditableDateRangeDate(value)

    if (field === 'from') {
      setFromInput(value)
      if (parsedDate) setCalendarMonth(parsedDate)
      setDraftRange((currentRange) =>
        getOrderedDateRange({
          from: parsedDate,
          to: currentRange?.to
        })
      )
      return
    }

    setToInput(value)
    if (parsedDate) setCalendarMonth(parsedDate)
    setDraftRange((currentRange) =>
      getOrderedDateRange({
        from: currentRange?.from,
        to: parsedDate
      })
    )
  }

  const canApply = Boolean(parseEditableDateRangeDate(fromInput) ?? draftRange?.from)

  return (
    <Popover
      open={open}
      onOpenChange={(nextOpen) => {
        setOpen(nextOpen)
        if (nextOpen) {
          syncDraftFromProps()
        }
      }}
    >
      <PopoverTrigger
        render={
          <Button variant="outline" className={cn('w-[206px]', className)} disabled={disabled} />
        }
      >
        <CalendarIcon />
        <span className="min-w-0 flex-1 truncate text-left tabular-nums">{triggerLabel}</span>
        <ChevronDown />
      </PopoverTrigger>
      <PopoverContent className="w-[282px] gap-0 overflow-hidden rounded-sm p-0" align="start">
        <Calendar
          mode="range"
          month={calendarMonth}
          onMonthChange={setCalendarMonth}
          selected={draftRange}
          onSelect={handleRangeSelect}
          numberOfMonths={1}
          weekStartsOn={1}
          className="w-full"
          classNames={{
            root: 'w-full',
            months: 'relative flex flex-col',
            month: 'flex w-full flex-col gap-2',
            nav: 'absolute right-0 top-0 flex items-center gap-1',
            month_caption: 'flex h-8 items-center justify-start pr-18',
            caption_label: 'text-sm font-semibold text-foreground',
            weekdays: 'flex',
            weekday:
              'flex-1 text-center text-xs font-normal leading-8 text-muted-foreground select-none',
            week: 'mt-1 flex w-full'
          }}
        />
        <div className="flex flex-col gap-2 border-t p-3">
          <div className="flex flex-col gap-1">
            <label className="text-sm text-muted-foreground" htmlFor="date-range-start-date">
              Start
            </label>
            <div className="grid grid-cols-[1fr_96px] gap-2">
              <Input
                id="date-range-start-date"
                value={fromInput}
                onChange={(event) => handleDateInputChange('from', event.target.value)}
                placeholder="Apr 10, 2026"
                className="h-8 rounded-md px-3 text-sm"
              />
              <Input
                type="time"
                value={fromTime}
                onChange={(event) => setFromTime(event.target.value)}
                aria-label="Start time"
                className="h-8 rounded-md px-3 text-sm tabular-nums"
              />
            </div>
          </div>
          <div className="flex flex-col gap-1">
            <label className="text-sm text-muted-foreground" htmlFor="date-range-end-date">
              End
            </label>
            <div className="grid grid-cols-[1fr_96px] gap-2">
              <Input
                id="date-range-end-date"
                value={toInput}
                onChange={(event) => handleDateInputChange('to', event.target.value)}
                placeholder="Apr 30, 2026"
                className="h-8 rounded-md px-3 text-sm"
              />
              <Input
                type="time"
                value={toTime}
                onChange={(event) => setToTime(event.target.value)}
                aria-label="End time"
                className="h-8 rounded-md px-3 text-sm tabular-nums"
              />
            </div>
          </div>
          <Button variant="outline" onClick={handleApply} disabled={!canApply}>
            Apply
            <CornerDownLeft data-icon="inline-end" />
          </Button>
        </div>
      </PopoverContent>
    </Popover>
  )
}
