"use client"

import * as React from "react"
import { format, parse, isValid } from "date-fns"
import { ko } from "date-fns/locale"
import { CalendarIcon, ChevronLeft, ChevronRight } from "lucide-react"
import { DayPicker } from "react-day-picker"

import { cn } from "@/lib/utils"
import { Button, buttonVariants } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover"

export interface DatePickerWithInputProps {
  value?: Date
  onChange?: (date: Date | undefined) => void
  disabled?: boolean
  placeholder?: string
  className?: string
  minDate?: Date
  maxDate?: Date
  dateFormat?: string
  inputClassName?: string
  locale?: "ko" | "en"
}

/**
 * DatePickerWithInput - 캘린더 선택 및 직접 입력이 가능한 날짜 선택기
 * 
 * 사용법:
 * ```tsx
 * <DatePickerWithInput
 *   value={selectedDate}
 *   onChange={(date) => setSelectedDate(date)}
 *   placeholder="날짜를 선택하세요"
 *   minDate={new Date()}
 * />
 * ```
 */
export function DatePickerWithInput({
  value,
  onChange,
  disabled = false,
  placeholder = "YYYY-MM-DD",
  className,
  minDate,
  maxDate,
  dateFormat = "yyyy-MM-dd",
  inputClassName,
  locale: localeProp = "en",
}: DatePickerWithInputProps) {
  const [open, setOpen] = React.useState(false)
  const [inputValue, setInputValue] = React.useState<string>("")
  const [month, setMonth] = React.useState<Date>(value || new Date())
  const [hasError, setHasError] = React.useState(false)
  const [errorMessage, setErrorMessage] = React.useState<string>("")

  // 외부 value가 변경되면 inputValue도 업데이트
  React.useEffect(() => {
    if (value && isValid(value)) {
      setInputValue(format(value, dateFormat))
      setMonth(value)
      setHasError(false)
      setErrorMessage("")
    } else {
      setInputValue("")
    }
  }, [value, dateFormat])

  // 날짜 유효성 검사 및 에러 메시지 설정
  const validateDate = (date: Date): { valid: boolean; message: string } => {
    if (minDate) {
      const minDateStart = new Date(minDate)
      minDateStart.setHours(0, 0, 0, 0)
      const dateToCheck = new Date(date)
      dateToCheck.setHours(0, 0, 0, 0)
      if (dateToCheck < minDateStart) {
        return {
          valid: false,
          message: `${format(minDate, dateFormat)} 이후 날짜를 선택해주세요`
        }
      }
    }
    if (maxDate) {
      const maxDateEnd = new Date(maxDate)
      maxDateEnd.setHours(23, 59, 59, 999)
      if (date > maxDateEnd) {
        return {
          valid: false,
          message: `${format(maxDate, dateFormat)} 이전 날짜를 선택해주세요`
        }
      }
    }
    return { valid: true, message: "" }
  }

  // 캘린더에서 날짜 선택
  const handleCalendarSelect = React.useCallback((date: Date | undefined, e?: React.MouseEvent) => {
    // 이벤트 전파 중지
    if (e) {
      e.preventDefault()
      e.stopPropagation()
    }
    
    if (date) {
      const validation = validateDate(date)
      if (validation.valid) {
        setInputValue(format(date, dateFormat))
        setHasError(false)
        setErrorMessage("")
        onChange?.(date)
        setMonth(date)
      } else {
        setHasError(true)
        setErrorMessage(validation.message)
      }
    }
    setOpen(false)
  }, [dateFormat, onChange, minDate, maxDate])

  // 직접 입력값 변경
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const newValue = e.target.value
    setInputValue(newValue)
    
    // 입력 중에는 에러 상태 초기화
    if (hasError) {
      setHasError(false)
      setErrorMessage("")
    }

    // YYYY-MM-DD 형식인 경우에만 파싱 시도
    if (/^\d{4}-\d{2}-\d{2}$/.test(newValue)) {
      const parsedDate = parse(newValue, dateFormat, new Date())
      
      if (isValid(parsedDate)) {
        const validation = validateDate(parsedDate)
        if (validation.valid) {
          setHasError(false)
          setErrorMessage("")
          onChange?.(parsedDate)
          setMonth(parsedDate)
        } else {
          setHasError(true)
          setErrorMessage(validation.message)
        }
      } else {
        setHasError(true)
        setErrorMessage("유효하지 않은 날짜 형식입니다")
      }
    }
  }

  // 입력 완료 시 (blur) 유효성 검사
  const handleInputBlur = () => {
    if (!inputValue) {
      setHasError(false)
      setErrorMessage("")
      onChange?.(undefined)
      return
    }

    const parsedDate = parse(inputValue, dateFormat, new Date())
    
    if (isValid(parsedDate)) {
      const validation = validateDate(parsedDate)
      if (validation.valid) {
        setHasError(false)
        setErrorMessage("")
        onChange?.(parsedDate)
      } else {
        setHasError(true)
        setErrorMessage(validation.message)
        // 유효 범위를 벗어난 경우 입력값은 유지하되 에러 표시
      }
    } else {
      // 유효하지 않은 형식인 경우
      setHasError(true)
      setErrorMessage("YYYY-MM-DD 형식으로 입력해주세요")
    }
  }

  // 키보드 이벤트 처리 (Enter 키로 완료)
  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter") {
      handleInputBlur()
    }
  }

  // 날짜 비활성화 체크 (캘린더용)
  const isDateDisabled = (date: Date) => {
    if (disabled) return true
    if (minDate) {
      const minDateStart = new Date(minDate)
      minDateStart.setHours(0, 0, 0, 0)
      const dateToCheck = new Date(date)
      dateToCheck.setHours(0, 0, 0, 0)
      if (dateToCheck < minDateStart) return true
    }
    if (maxDate) {
      const maxDateEnd = new Date(maxDate)
      maxDateEnd.setHours(23, 59, 59, 999)
      if (date > maxDateEnd) return true
    }
    return false
  }

  // 캘린더 버튼 클릭 핸들러
  const handleCalendarButtonClick = (e: React.MouseEvent) => {
    e.preventDefault()
    e.stopPropagation()
    setOpen(!open)
  }

  // Popover 상태 변경 핸들러
  const handleOpenChange = (newOpen: boolean) => {
    setOpen(newOpen)
  }

  return (
    <div className={cn("relative", className)}>
      <div className="flex items-center gap-1">
        <Input
          type="text"
          value={inputValue}
          onChange={handleInputChange}
          onBlur={handleInputBlur}
          onKeyDown={handleKeyDown}
          placeholder={placeholder}
          disabled={disabled}
          className={cn(
            "pr-10",
            hasError && "border-red-500 focus-visible:ring-red-500",
            inputClassName
          )}
        />
        <Popover open={open} onOpenChange={handleOpenChange} modal={true}>
          <PopoverTrigger asChild>
            <Button
              variant="ghost"
              size="icon"
              className="absolute right-0 h-full px-3 hover:bg-transparent"
              disabled={disabled}
              type="button"
              onClick={handleCalendarButtonClick}
            >
              <CalendarIcon className={cn(
                "h-4 w-4",
                hasError ? "text-red-500" : "text-muted-foreground"
              )} />
            </Button>
          </PopoverTrigger>
          <PopoverContent 
            className="w-auto p-0" 
            align="end"
            onPointerDownOutside={(e) => e.preventDefault()}
            onInteractOutside={(e) => e.preventDefault()}
          >
            <div 
              onClick={(e) => e.stopPropagation()}
              onMouseDown={(e) => e.stopPropagation()}
            >
              <DayPicker
                mode="single"
                selected={value}
                onSelect={(date, selectedDay, activeModifiers, e) => {
                  handleCalendarSelect(date, e as unknown as React.MouseEvent)
                }}
                month={month}
                onMonthChange={setMonth}
                disabled={isDateDisabled}
                locale={localeProp === "ko" ? ko : undefined}
                showOutsideDays
                className="p-3"
                classNames={{
                  months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
                  month: "space-y-4",
                  caption: "flex justify-center pt-1 relative items-center",
                  caption_label: "text-sm font-medium",
                  nav: "space-x-1 flex items-center",
                  nav_button: cn(
                    buttonVariants({ variant: "outline" }),
                    "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
                  ),
                  nav_button_previous: "absolute left-1",
                  nav_button_next: "absolute right-1",
                  table: "w-full border-collapse space-y-1",
                  head_row: "flex",
                  head_cell: "text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]",
                  row: "flex w-full mt-2",
                  cell: "relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected])]:rounded-md",
                  day: cn(
                    buttonVariants({ variant: "ghost" }),
                    "h-8 w-8 p-0 font-normal aria-selected:opacity-100"
                  ),
                  day_selected: "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
                  day_today: "bg-accent text-accent-foreground",
                  day_outside: "text-muted-foreground opacity-50",
                  day_disabled: "text-muted-foreground opacity-50",
                  day_hidden: "invisible",
                }}
                components={{
                  IconLeft: () => <ChevronLeft className="h-4 w-4" />,
                  IconRight: () => <ChevronRight className="h-4 w-4" />,
                }}
              />
            </div>
          </PopoverContent>
        </Popover>
      </div>
      {/* 에러 메시지 표시 */}
      {hasError && errorMessage && (
        <p className="text-xs text-red-500 mt-1">{errorMessage}</p>
      )}
    </div>
  )
}

