"use client"

import * as React from "react"

import { useState, useCallback } from "react"
import { CalendarDays } from "lucide-react"
import { cn } from "@/lib/utils"
import { formatDate, parseDate, type Locale, locales } from "@/lib/date-utils"
import { Input } from "@/components/ui/input"

interface DateInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'value'> {
  value: Date | null
  onChange: (date: Date | null) => void
  locale: Locale
  placeholder?: string
  formatValue?: (date: Date) => string
  disabled?: boolean
  minDate?: Date
  maxDate?: Date
  className?: string
  id?: string
}

export const DateInput = React.forwardRef<HTMLInputElement, DateInputProps>(
  (
    {
      value,
      onChange,
      onFocus,
      locale,
      placeholder,
      formatValue,
      disabled,
      minDate,
      maxDate,
      className,
      id,
      "aria-label": ariaLabel,
      "aria-describedby": ariaDescribedBy,
      ...props
    },
    ref,
  ) => {
  const config = locales[locale]
  const isRTL = config.direction === "rtl"
  const formattedValue = value ? (formatValue ? formatValue(value) : formatDate(value, locale)) : ""
  const [inputValue, setInputValue] = useState(formattedValue)
  const [isValid, setIsValid] = useState(true)
  const [isEditing, setIsEditing] = useState(false)

  const handleChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const newValue = e.target.value
      setInputValue(newValue)

      if (newValue === "") {
        onChange(null)
        setIsValid(true)
        return
      }

      const parsedDate = parseDate(newValue, locale)
      if (parsedDate) {
        if (minDate) {
          const startOfMinDate = new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), 0, 0, 0, 0)
          if (parsedDate < startOfMinDate) {
            setIsValid(false)
            return
          }
        }
        if (maxDate) {
          const endOfMaxDate = new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate(), 23, 59, 59, 999)
          if (parsedDate > endOfMaxDate) {
            setIsValid(false)
            return
          }
        }
        onChange(parsedDate)
        setIsValid(true)
      } else {
        setIsValid(false)
      }
    },
    [locale, onChange, minDate, maxDate],
  )

  const handleFocus = useCallback((e: React.FocusEvent<HTMLInputElement>) => {
    setInputValue(formattedValue)
    setIsEditing(true)
    onFocus?.(e)
  }, [formattedValue, onFocus])

  const handleBlur = useCallback(() => {
    setIsEditing(false)

    if (value) {
      setInputValue(formatValue ? formatValue(value) : formatDate(value, locale))
      setIsValid(true)
    }
  }, [value, locale, formatValue])

  return (
    <div
      ref={ref}
      className={cn("relative", className)}
      dir={isRTL ? "rtl" : "ltr"}
      {...props}
    >
      <Input
        id={id}
        type="text"
        value={isEditing ? inputValue : formattedValue}
        onChange={handleChange}
        onFocus={handleFocus}
        onBlur={handleBlur}
        placeholder={placeholder || config.dateFormat}
        disabled={disabled}
        aria-label={ariaLabel}
        aria-describedby={ariaDescribedBy}
        aria-invalid={!isValid}
        className={cn(
          "pr-10 rtl:pr-3 rtl:pl-10",
          !isValid && "border-destructive focus-visible:ring-destructive"
        )}
      />
      <CalendarDays
        className={cn(
          "absolute top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground pointer-events-none",
          isRTL ? "left-3" : "right-3"
        )}
        aria-hidden="true"
      />
    </div>
  )
})

DateInput.displayName = "DateInput"
