"use client";

import { getAdaptiveLabelColor } from "@/lib/utils/darkModeColor";

/**
 * V2Date
 *
 * 통합 날짜/시간 컴포넌트
 * - date: 날짜 선택
 * - time: 시간 선택
 * - datetime: 날짜+시간 선택
 * - range 옵션: 범위 선택 (시작~종료)
 */

import React, { forwardRef, useCallback, useMemo, useState, useEffect } from "react";
import {
  format,
  parse,
  isValid,
  addMonths,
  subMonths,
  startOfMonth,
  endOfMonth,
  eachDayOfInterval,
  isSameMonth,
  isSameDay,
  isToday as isTodayFn,
} from "date-fns";
import { ko } from "date-fns/locale";
import { Calendar as CalendarIcon, Clock, ChevronLeft, ChevronRight } from "lucide-react";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { V2DateProps, V2DateType } from "@/types/v2-components";

// 날짜 형식 매핑
const DATE_FORMATS: Record<string, string> = {
  "YYYY-MM-DD": "yyyy-MM-dd",
  "YYYY/MM/DD": "yyyy/MM/dd",
  "DD-MM-YYYY": "dd-MM-yyyy",
  "DD/MM/YYYY": "dd/MM/yyyy",
  "MM-DD-YYYY": "MM-dd-yyyy",
  "MM/DD/YYYY": "MM/dd/yyyy",
  "YYYY-MM-DD HH:mm": "yyyy-MM-dd HH:mm",
  "YYYY-MM-DD HH:mm:ss": "yyyy-MM-dd HH:mm:ss",
};

// 날짜 문자열 → Date 객체
function parseDate(value: string | undefined, formatStr: string): Date | undefined {
  if (!value) return undefined;

  const dateFnsFormat = DATE_FORMATS[formatStr] || formatStr;

  try {
    // ISO 형식 먼저 시도
    const isoDate = new Date(value);
    if (isValid(isoDate)) return isoDate;

    // 포맷에 맞게 파싱
    const parsed = parse(value, dateFnsFormat, new Date());
    return isValid(parsed) ? parsed : undefined;
  } catch {
    return undefined;
  }
}

// Date 객체 → 날짜 문자열
function formatDate(date: Date | undefined, formatStr: string): string {
  if (!date || !isValid(date)) return "";
  const dateFnsFormat = DATE_FORMATS[formatStr] || formatStr;
  return format(date, dateFnsFormat);
}

// YYYYMMDD 또는 YYYY-MM-DD 문자열 → 유효한 Date 객체 반환 (유효하지 않으면 null)
function parseManualDateInput(raw: string): Date | null {
  const digits = raw.replace(/\D/g, "");
  if (digits.length !== 8) return null;
  const y = parseInt(digits.slice(0, 4), 10);
  const m = parseInt(digits.slice(4, 6), 10) - 1;
  const d = parseInt(digits.slice(6, 8), 10);
  const date = new Date(y, m, d);
  if (date.getFullYear() !== y || date.getMonth() !== m || date.getDate() !== d) return null;
  if (y < 1900 || y > 2100) return null;
  return date;
}

/**
 * 단일 날짜 선택 컴포넌트
 */
const SingleDatePicker = forwardRef<
  HTMLDivElement,
  {
    value?: string;
    onChange?: (value: string) => void;
    dateFormat: string;
    showToday?: boolean;
    minDate?: string;
    maxDate?: string;
    disabled?: boolean;
    readonly?: boolean;
    className?: string;
    placeholder?: string;
  }
>(
  (
    {
      value,
      onChange,
      dateFormat = "YYYY-MM-DD",
      showToday = true,
      minDate,
      maxDate,
      disabled,
      readonly,
      className,
      placeholder = "날짜 선택",
    },
    ref,
  ) => {
    const [open, setOpen] = useState(false);
    const [currentMonth, setCurrentMonth] = useState(new Date());
    const [viewMode, setViewMode] = useState<"calendar" | "year" | "month">("calendar");
    const [yearRangeStart, setYearRangeStart] = useState(() => Math.floor(new Date().getFullYear() / 12) * 12);
    const [isTyping, setIsTyping] = useState(false);
    const [typingValue, setTypingValue] = useState("");
    const inputRef = React.useRef<HTMLInputElement>(null);

    const date = useMemo(() => parseDate(value, dateFormat), [value, dateFormat]);

    const displayText = useMemo(() => {
      if (!value) return "";
      if (date && isValid(date)) return formatDate(date, dateFormat);
      return value;
    }, [value, date, dateFormat]);

    useEffect(() => {
      if (open) {
        setViewMode("calendar");
        if (date && isValid(date)) {
          setCurrentMonth(new Date(date.getFullYear(), date.getMonth(), 1));
          setYearRangeStart(Math.floor(date.getFullYear() / 12) * 12);
        } else {
          setCurrentMonth(new Date());
          setYearRangeStart(Math.floor(new Date().getFullYear() / 12) * 12);
        }
      } else {
        setIsTyping(false);
        setTypingValue("");
      }
    }, [open]);

    const handleDateClick = useCallback(
      (clickedDate: Date) => {
        onChange?.(formatDate(clickedDate, dateFormat));
        setIsTyping(false);
        setOpen(false);
      },
      [dateFormat, onChange],
    );

    const handleToday = useCallback(() => {
      onChange?.(formatDate(new Date(), dateFormat));
      setIsTyping(false);
      setOpen(false);
    }, [dateFormat, onChange]);

    const handleClear = useCallback(() => {
      onChange?.("");
      setIsTyping(false);
      setOpen(false);
    }, [onChange]);

    const handleTriggerInput = useCallback(
      (raw: string) => {
        setIsTyping(true);
        setTypingValue(raw);
        if (!open) setOpen(true);
        const digitsOnly = raw.replace(/\D/g, "");
        if (digitsOnly.length === 8) {
          const parsed = parseManualDateInput(digitsOnly);
          if (parsed) {
            onChange?.(formatDate(parsed, dateFormat));
            setCurrentMonth(new Date(parsed.getFullYear(), parsed.getMonth(), 1));
            setTimeout(() => {
              setIsTyping(false);
              setOpen(false);
            }, 400);
          }
        }
      },
      [dateFormat, onChange, open],
    );

    const mStart = startOfMonth(currentMonth);
    const mEnd = endOfMonth(currentMonth);
    const days = eachDayOfInterval({ start: mStart, end: mEnd });
    const dow = mStart.getDay();
    const padding = dow === 0 ? 6 : dow - 1;
    const allDays = [...Array(padding).fill(null), ...days];

    return (
      <Popover
        open={open}
        onOpenChange={(v) => {
          if (!v) {
            setOpen(false);
            setIsTyping(false);
          }
        }}
      >
        <PopoverTrigger asChild>
          <div
            ref={ref}
            className={cn(
              "border-input bg-background flex h-full w-full cursor-pointer items-center rounded-md border px-3",
              (disabled || readonly) && "cursor-not-allowed opacity-50",
              className,
            )}
            onClick={() => {
              if (!disabled && !readonly) setOpen(true);
            }}
          >
            <CalendarIcon className="text-muted-foreground mr-2 h-4 w-4 shrink-0" />
            <input
              ref={inputRef}
              type="text"
              inputMode="numeric"
              value={isTyping ? typingValue : displayText || ""}
              placeholder={placeholder}
              disabled={disabled || readonly}
              onChange={(e) => handleTriggerInput(e.target.value)}
              onClick={(e) => e.stopPropagation()}
              onFocus={() => {
                if (!disabled && !readonly && !open) setOpen(true);
              }}
              onBlur={() => {
                if (!open) setIsTyping(false);
              }}
              className={cn(
                "h-full w-full bg-transparent text-sm outline-none",
                "placeholder:text-muted-foreground disabled:cursor-not-allowed",
                !displayText && !isTyping && "text-muted-foreground",
              )}
            />
          </div>
        </PopoverTrigger>
        <PopoverContent className="w-auto p-0" align="start" onOpenAutoFocus={(e) => e.preventDefault()}>
          <div className="p-4">
            <div className="mb-3 flex items-center gap-2">
              {showToday && (
                <Button variant="outline" size="sm" className="h-7 text-xs" onClick={handleToday}>
                  오늘
                </Button>
              )}
              <Button variant="outline" size="sm" className="h-7 text-xs" onClick={handleClear}>
                초기화
              </Button>
            </div>

            {viewMode === "year" ? (
              <>
                <div className="mb-4 flex items-center justify-between">
                  <Button
                    variant="ghost"
                    size="sm"
                    className="h-8 w-8 p-0"
                    onClick={() => setYearRangeStart(yearRangeStart - 12)}
                  >
                    <ChevronLeft className="h-4 w-4" />
                  </Button>
                  <div className="text-sm font-medium">
                    {yearRangeStart} - {yearRangeStart + 11}
                  </div>
                  <Button
                    variant="ghost"
                    size="sm"
                    className="h-8 w-8 p-0"
                    onClick={() => setYearRangeStart(yearRangeStart + 12)}
                  >
                    <ChevronRight className="h-4 w-4" />
                  </Button>
                </div>
                <div className="grid grid-cols-4 gap-2">
                  {Array.from({ length: 12 }, (_, i) => yearRangeStart + i).map((year) => (
                    <Button
                      key={year}
                      variant="ghost"
                      size="sm"
                      className={cn(
                        "h-9 text-xs",
                        year === currentMonth.getFullYear() && "bg-primary text-primary-foreground hover:bg-primary",
                        year === new Date().getFullYear() &&
                          year !== currentMonth.getFullYear() &&
                          "border-primary border",
                      )}
                      onClick={() => {
                        setCurrentMonth(new Date(year, currentMonth.getMonth(), 1));
                        setViewMode("month");
                      }}
                    >
                      {year}
                    </Button>
                  ))}
                </div>
              </>
            ) : viewMode === "month" ? (
              <>
                <div className="mb-4 flex items-center justify-between">
                  <Button
                    variant="ghost"
                    size="sm"
                    className="h-8 w-8 p-0"
                    onClick={() =>
                      setCurrentMonth(new Date(currentMonth.getFullYear() - 1, currentMonth.getMonth(), 1))
                    }
                  >
                    <ChevronLeft className="h-4 w-4" />
                  </Button>
                  <button
                    type="button"
                    className="hover:bg-accent rounded-md px-2 py-1 text-sm font-medium transition-colors"
                    onClick={() => {
                      setYearRangeStart(Math.floor(currentMonth.getFullYear() / 12) * 12);
                      setViewMode("year");
                    }}
                  >
                    {currentMonth.getFullYear()}년
                  </button>
                  <Button
                    variant="ghost"
                    size="sm"
                    className="h-8 w-8 p-0"
                    onClick={() =>
                      setCurrentMonth(new Date(currentMonth.getFullYear() + 1, currentMonth.getMonth(), 1))
                    }
                  >
                    <ChevronRight className="h-4 w-4" />
                  </Button>
                </div>
                <div className="grid grid-cols-4 gap-2">
                  {Array.from({ length: 12 }, (_, i) => i).map((month) => (
                    <Button
                      key={month}
                      variant="ghost"
                      size="sm"
                      className={cn(
                        "h-9 text-xs",
                        month === currentMonth.getMonth() && "bg-primary text-primary-foreground hover:bg-primary",
                        month === new Date().getMonth() &&
                          currentMonth.getFullYear() === new Date().getFullYear() &&
                          month !== currentMonth.getMonth() &&
                          "border-primary border",
                      )}
                      onClick={() => {
                        setCurrentMonth(new Date(currentMonth.getFullYear(), month, 1));
                        setViewMode("calendar");
                      }}
                    >
                      {month + 1}월
                    </Button>
                  ))}
                </div>
              </>
            ) : (
              <>
                <div className="mb-4 flex items-center justify-between">
                  <Button
                    variant="ghost"
                    size="sm"
                    className="h-8 w-8 p-0"
                    onClick={() => setCurrentMonth(subMonths(currentMonth, 1))}
                  >
                    <ChevronLeft className="h-4 w-4" />
                  </Button>
                  <button
                    type="button"
                    className="hover:bg-accent rounded-md px-2 py-1 text-sm font-medium transition-colors"
                    onClick={() => {
                      setYearRangeStart(Math.floor(currentMonth.getFullYear() / 12) * 12);
                      setViewMode("year");
                    }}
                  >
                    {format(currentMonth, "yyyy년 MM월", { locale: ko })}
                  </button>
                  <Button
                    variant="ghost"
                    size="sm"
                    className="h-8 w-8 p-0"
                    onClick={() => setCurrentMonth(addMonths(currentMonth, 1))}
                  >
                    <ChevronRight className="h-4 w-4" />
                  </Button>
                </div>
                <div className="mb-2 grid grid-cols-7 gap-1">
                  {["월", "화", "수", "목", "금", "토", "일"].map((d) => (
                    <div key={d} className="text-muted-foreground p-2 text-center text-xs font-medium">
                      {d}
                    </div>
                  ))}
                </div>
                <div className="grid grid-cols-7 gap-1">
                  {allDays.map((d, idx) => {
                    if (!d) return <div key={idx} className="p-2" />;
                    const isCur = isSameMonth(d, currentMonth);
                    const isSel = date ? isSameDay(d, date) : false;
                    const isT = isTodayFn(d);
                    return (
                      <Button
                        key={d.toISOString()}
                        variant="ghost"
                        size="sm"
                        className={cn(
                          "h-8 w-8 p-0 text-xs",
                          !isCur && "text-muted-foreground opacity-50",
                          isSel && "bg-primary text-primary-foreground hover:bg-primary",
                          isT && !isSel && "border-primary border",
                        )}
                        onClick={() => handleDateClick(d)}
                        disabled={!isCur}
                      >
                        {format(d, "d")}
                      </Button>
                    );
                  })}
                </div>
              </>
            )}
          </div>
        </PopoverContent>
      </Popover>
    );
  },
);
SingleDatePicker.displayName = "SingleDatePicker";

/**
 * 날짜 범위 선택 컴포넌트
 */
/**
 * 범위 날짜 팝오버 내부 캘린더 (drill-down 지원)
 */
const RangeCalendarPopover: React.FC<{
  open: boolean;
  onOpenChange: (open: boolean) => void;
  selectedDate?: Date;
  onSelect: (date: Date) => void;
  label: string;
  disabled?: boolean;
  readonly?: boolean;
  displayValue?: string;
}> = ({ open, onOpenChange, selectedDate, onSelect, label, disabled, readonly, displayValue }) => {
  const [currentMonth, setCurrentMonth] = useState(new Date());
  const [viewMode, setViewMode] = useState<"calendar" | "year" | "month">("calendar");
  const [yearRangeStart, setYearRangeStart] = useState(() => Math.floor(new Date().getFullYear() / 12) * 12);
  const [isTyping, setIsTyping] = useState(false);
  const [typingValue, setTypingValue] = useState("");

  useEffect(() => {
    if (open) {
      setViewMode("calendar");
      if (selectedDate && isValid(selectedDate)) {
        setCurrentMonth(new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 1));
        setYearRangeStart(Math.floor(selectedDate.getFullYear() / 12) * 12);
      } else {
        setCurrentMonth(new Date());
        setYearRangeStart(Math.floor(new Date().getFullYear() / 12) * 12);
      }
    } else {
      setIsTyping(false);
      setTypingValue("");
    }
  }, [open]);

  const handleTriggerInput = (raw: string) => {
    setIsTyping(true);
    setTypingValue(raw);
    const digitsOnly = raw.replace(/\D/g, "");
    if (digitsOnly.length === 8) {
      const parsed = parseManualDateInput(digitsOnly);
      if (parsed) {
        setIsTyping(false);
        onSelect(parsed);
      }
    }
  };

  const mStart = startOfMonth(currentMonth);
  const mEnd = endOfMonth(currentMonth);
  const days = eachDayOfInterval({ start: mStart, end: mEnd });
  const dow = mStart.getDay();
  const padding = dow === 0 ? 6 : dow - 1;
  const allDays = [...Array(padding).fill(null), ...days];

  return (
    <Popover
      open={open}
      onOpenChange={(v) => {
        if (!v) {
          setIsTyping(false);
        }
        onOpenChange(v);
      }}
    >
      <PopoverTrigger asChild>
        <div
          className={cn(
            "border-input bg-background flex h-full flex-1 cursor-pointer items-center rounded-md border px-3",
            (disabled || readonly) && "cursor-not-allowed opacity-50",
            !displayValue && !isTyping && "text-muted-foreground",
          )}
          onClick={() => {
            if (!disabled && !readonly) onOpenChange(true);
          }}
        >
          <CalendarIcon className="text-muted-foreground mr-2 h-4 w-4 shrink-0" />
          <input
            type="text"
            inputMode="numeric"
            value={isTyping ? typingValue : displayValue || ""}
            placeholder={label}
            disabled={disabled || readonly}
            onChange={(e) => handleTriggerInput(e.target.value)}
            onClick={(e) => e.stopPropagation()}
            onFocus={() => {
              if (!disabled && !readonly && !open) onOpenChange(true);
            }}
            onBlur={() => {
              if (!open) setIsTyping(false);
            }}
            className="placeholder:text-muted-foreground h-full w-full bg-transparent text-sm font-normal outline-none disabled:cursor-not-allowed"
          />
        </div>
      </PopoverTrigger>
      <PopoverContent className="w-auto p-0" align="start" onOpenAutoFocus={(e) => e.preventDefault()}>
        <div className="p-4">
          {viewMode === "year" ? (
            <>
              <div className="mb-4 flex items-center justify-between">
                <Button
                  variant="ghost"
                  size="sm"
                  className="h-8 w-8 p-0"
                  onClick={() => setYearRangeStart(yearRangeStart - 12)}
                >
                  <ChevronLeft className="h-4 w-4" />
                </Button>
                <div className="text-sm font-medium">
                  {yearRangeStart} - {yearRangeStart + 11}
                </div>
                <Button
                  variant="ghost"
                  size="sm"
                  className="h-8 w-8 p-0"
                  onClick={() => setYearRangeStart(yearRangeStart + 12)}
                >
                  <ChevronRight className="h-4 w-4" />
                </Button>
              </div>
              <div className="grid grid-cols-4 gap-2">
                {Array.from({ length: 12 }, (_, i) => yearRangeStart + i).map((year) => (
                  <Button
                    key={year}
                    variant="ghost"
                    size="sm"
                    className={cn(
                      "h-9 text-xs",
                      year === currentMonth.getFullYear() && "bg-primary text-primary-foreground hover:bg-primary",
                      year === new Date().getFullYear() &&
                        year !== currentMonth.getFullYear() &&
                        "border-primary border",
                    )}
                    onClick={() => {
                      setCurrentMonth(new Date(year, currentMonth.getMonth(), 1));
                      setViewMode("month");
                    }}
                  >
                    {year}
                  </Button>
                ))}
              </div>
            </>
          ) : viewMode === "month" ? (
            <>
              <div className="mb-4 flex items-center justify-between">
                <Button
                  variant="ghost"
                  size="sm"
                  className="h-8 w-8 p-0"
                  onClick={() => setCurrentMonth(new Date(currentMonth.getFullYear() - 1, currentMonth.getMonth(), 1))}
                >
                  <ChevronLeft className="h-4 w-4" />
                </Button>
                <button
                  type="button"
                  className="hover:bg-accent rounded-md px-2 py-1 text-sm font-medium transition-colors"
                  onClick={() => {
                    setYearRangeStart(Math.floor(currentMonth.getFullYear() / 12) * 12);
                    setViewMode("year");
                  }}
                >
                  {currentMonth.getFullYear()}년
                </button>
                <Button
                  variant="ghost"
                  size="sm"
                  className="h-8 w-8 p-0"
                  onClick={() => setCurrentMonth(new Date(currentMonth.getFullYear() + 1, currentMonth.getMonth(), 1))}
                >
                  <ChevronRight className="h-4 w-4" />
                </Button>
              </div>
              <div className="grid grid-cols-4 gap-2">
                {Array.from({ length: 12 }, (_, i) => i).map((month) => (
                  <Button
                    key={month}
                    variant="ghost"
                    size="sm"
                    className={cn(
                      "h-9 text-xs",
                      month === currentMonth.getMonth() && "bg-primary text-primary-foreground hover:bg-primary",
                      month === new Date().getMonth() &&
                        currentMonth.getFullYear() === new Date().getFullYear() &&
                        month !== currentMonth.getMonth() &&
                        "border-primary border",
                    )}
                    onClick={() => {
                      setCurrentMonth(new Date(currentMonth.getFullYear(), month, 1));
                      setViewMode("calendar");
                    }}
                  >
                    {month + 1}월
                  </Button>
                ))}
              </div>
            </>
          ) : (
            <>
              <div className="mb-4 flex items-center justify-between">
                <Button
                  variant="ghost"
                  size="sm"
                  className="h-8 w-8 p-0"
                  onClick={() => setCurrentMonth(subMonths(currentMonth, 1))}
                >
                  <ChevronLeft className="h-4 w-4" />
                </Button>
                <button
                  type="button"
                  className="hover:bg-accent rounded-md px-2 py-1 text-sm font-medium transition-colors"
                  onClick={() => {
                    setYearRangeStart(Math.floor(currentMonth.getFullYear() / 12) * 12);
                    setViewMode("year");
                  }}
                >
                  {format(currentMonth, "yyyy년 MM월", { locale: ko })}
                </button>
                <Button
                  variant="ghost"
                  size="sm"
                  className="h-8 w-8 p-0"
                  onClick={() => setCurrentMonth(addMonths(currentMonth, 1))}
                >
                  <ChevronRight className="h-4 w-4" />
                </Button>
              </div>
              <div className="mb-2 grid grid-cols-7 gap-1">
                {["월", "화", "수", "목", "금", "토", "일"].map((d) => (
                  <div key={d} className="text-muted-foreground p-2 text-center text-xs font-medium">
                    {d}
                  </div>
                ))}
              </div>
              <div className="grid grid-cols-7 gap-1">
                {allDays.map((d, idx) => {
                  if (!d) return <div key={idx} className="p-2" />;
                  const isCur = isSameMonth(d, currentMonth);
                  const isSel = selectedDate ? isSameDay(d, selectedDate) : false;
                  const isT = isTodayFn(d);
                  return (
                    <Button
                      key={d.toISOString()}
                      variant="ghost"
                      size="sm"
                      className={cn(
                        "h-8 w-8 p-0 text-xs",
                        !isCur && "text-muted-foreground opacity-50",
                        isSel && "bg-primary text-primary-foreground hover:bg-primary",
                        isT && !isSel && "border-primary border",
                      )}
                      onClick={() => onSelect(d)}
                      disabled={!isCur}
                    >
                      {format(d, "d")}
                    </Button>
                  );
                })}
              </div>
            </>
          )}
        </div>
      </PopoverContent>
    </Popover>
  );
};

const RangeDatePicker = forwardRef<
  HTMLDivElement,
  {
    value?: [string, string];
    onChange?: (value: [string, string]) => void;
    dateFormat: string;
    minDate?: string;
    maxDate?: string;
    disabled?: boolean;
    readonly?: boolean;
    className?: string;
  }
>(({ value = ["", ""], onChange, dateFormat = "YYYY-MM-DD", minDate, maxDate, disabled, readonly, className }, ref) => {
  const [openStart, setOpenStart] = useState(false);
  const [openEnd, setOpenEnd] = useState(false);

  const startDate = useMemo(() => parseDate(value[0], dateFormat), [value, dateFormat]);
  const endDate = useMemo(() => parseDate(value[1], dateFormat), [value, dateFormat]);

  const handleStartSelect = useCallback(
    (date: Date) => {
      const newStart = formatDate(date, dateFormat);
      if (endDate && date > endDate) {
        onChange?.([newStart, newStart]);
      } else {
        onChange?.([newStart, value[1]]);
      }
      setOpenStart(false);
    },
    [value, dateFormat, endDate, onChange],
  );

  const handleEndSelect = useCallback(
    (date: Date) => {
      const newEnd = formatDate(date, dateFormat);
      if (startDate && date < startDate) {
        onChange?.([newEnd, newEnd]);
      } else {
        onChange?.([value[0], newEnd]);
      }
      setOpenEnd(false);
    },
    [value, dateFormat, startDate, onChange],
  );

  return (
    <div ref={ref} className={cn("flex h-full items-center gap-2", className)}>
      <RangeCalendarPopover
        open={openStart}
        onOpenChange={setOpenStart}
        selectedDate={startDate}
        onSelect={handleStartSelect}
        label="시작일"
        disabled={disabled}
        readonly={readonly}
        displayValue={value[0]}
      />
      <span className="text-muted-foreground">~</span>
      <RangeCalendarPopover
        open={openEnd}
        onOpenChange={setOpenEnd}
        selectedDate={endDate}
        onSelect={handleEndSelect}
        label="종료일"
        disabled={disabled}
        readonly={readonly}
        displayValue={value[1]}
      />
    </div>
  );
});
RangeDatePicker.displayName = "RangeDatePicker";

/**
 * 시간 선택 컴포넌트
 */
const TimePicker = forwardRef<
  HTMLInputElement,
  {
    value?: string;
    onChange?: (value: string) => void;
    disabled?: boolean;
    readonly?: boolean;
    className?: string;
  }
>(({ value, onChange, disabled, readonly, className }, ref) => {
  return (
    <div className={cn("relative h-full", className)}>
      <Clock className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
      <Input
        ref={ref}
        type="time"
        value={value || ""}
        onChange={(e) => onChange?.(e.target.value)}
        disabled={disabled}
        readOnly={readonly}
        className="h-full pl-10"
      />
    </div>
  );
});
TimePicker.displayName = "TimePicker";

/**
 * 날짜+시간 선택 컴포넌트
 */
const DateTimePicker = forwardRef<
  HTMLDivElement,
  {
    value?: string;
    onChange?: (value: string) => void;
    dateFormat: string;
    minDate?: string;
    maxDate?: string;
    disabled?: boolean;
    readonly?: boolean;
    className?: string;
  }
>(({ value, onChange, dateFormat = "YYYY-MM-DD HH:mm", minDate, maxDate, disabled, readonly, className }, ref) => {
  // 날짜와 시간 분리
  const [datePart, timePart] = useMemo(() => {
    if (!value) return ["", ""];
    const parts = value.split(" ");
    return [parts[0] || "", parts[1] || ""];
  }, [value]);

  const handleDateChange = useCallback(
    (newDate: string) => {
      const newValue = `${newDate} ${timePart || "00:00"}`;
      onChange?.(newValue.trim());
    },
    [timePart, onChange],
  );

  const handleTimeChange = useCallback(
    (newTime: string) => {
      const newValue = `${datePart || format(new Date(), "yyyy-MM-dd")} ${newTime}`;
      onChange?.(newValue.trim());
    },
    [datePart, onChange],
  );

  return (
    <div ref={ref} className={cn("flex h-full gap-2", className)}>
      <div className="h-full flex-1">
        <SingleDatePicker
          value={datePart}
          onChange={handleDateChange}
          dateFormat="YYYY-MM-DD"
          minDate={minDate}
          maxDate={maxDate}
          disabled={disabled}
          readonly={readonly}
        />
      </div>
      <div className="h-full w-1/3 min-w-[100px]">
        <TimePicker value={timePart} onChange={handleTimeChange} disabled={disabled} readonly={readonly} />
      </div>
    </div>
  );
});
DateTimePicker.displayName = "DateTimePicker";

/**
 * 메인 V2Date 컴포넌트
 */
export const V2Date = forwardRef<HTMLDivElement, V2DateProps>((props, ref) => {
  const { id, label, required, readonly, disabled, style, size, config: configProp, value, onChange } = props;

  // config가 없으면 기본값 사용
  const config = configProp || { type: "date" as const };

  const dateFormat = config.format || "YYYY-MM-DD";

  // 타입별 컴포넌트 렌더링
  const renderDatePicker = () => {
    const isDisabled = disabled || readonly;

    // 범위 선택
    if (config.range) {
      return (
        <RangeDatePicker
          value={Array.isArray(value) ? (value as [string, string]) : ["", ""]}
          onChange={onChange as (value: [string, string]) => void}
          dateFormat={dateFormat}
          minDate={config.minDate}
          maxDate={config.maxDate}
          disabled={isDisabled}
          readonly={readonly}
        />
      );
    }

    // 타입별 렌더링
    switch (config.type) {
      case "date":
        return (
          <SingleDatePicker
            value={typeof value === "string" ? value : ""}
            onChange={(v) => onChange?.(v)}
            dateFormat={dateFormat}
            showToday={config.showToday}
            minDate={config.minDate}
            maxDate={config.maxDate}
            disabled={isDisabled}
            readonly={readonly}
            placeholder={config.placeholder}
          />
        );

      case "time":
        return (
          <TimePicker
            value={typeof value === "string" ? value : ""}
            onChange={(v) => onChange?.(v)}
            disabled={isDisabled}
            readonly={readonly}
          />
        );

      case "datetime":
        return (
          <DateTimePicker
            value={typeof value === "string" ? value : ""}
            onChange={(v) => onChange?.(v)}
            dateFormat={dateFormat}
            minDate={config.minDate}
            maxDate={config.maxDate}
            disabled={isDisabled}
            readonly={readonly}
          />
        );

      default:
        return (
          <SingleDatePicker
            value={typeof value === "string" ? value : ""}
            onChange={(v) => onChange?.(v)}
            dateFormat={dateFormat}
            showToday={config.showToday}
            disabled={isDisabled}
            readonly={readonly}
            placeholder={config.placeholder}
          />
        );
    }
  };

  const showLabel = label && style?.labelDisplay !== false;
  const componentWidth = size?.width || style?.width;
  const componentHeight = size?.height || style?.height;

  // 라벨 위치 및 높이 계산
  const labelPos = style?.labelPosition || "top";
  const isHorizLabel = labelPos === "left" || labelPos === "right";
  const labelFontSize = style?.labelFontSize ? parseInt(String(style.labelFontSize)) : 14;
  const labelMarginBottom = style?.labelMarginBottom ? parseInt(String(style.labelMarginBottom)) : 4;
  const estimatedLabelHeight = labelFontSize + labelMarginBottom + 2;
  const labelGapValue = style?.labelGap || "8px";

  const labelElement = showLabel ? (
    <Label
      htmlFor={id}
      style={{
        ...(labelPos === "top" ? { position: "absolute" as const, top: `-${estimatedLabelHeight}px`, left: 0 } : {}),
        ...(labelPos === "bottom"
          ? { position: "absolute" as const, bottom: `-${estimatedLabelHeight}px`, left: 0 }
          : {}),
        fontSize: style?.labelFontSize || "14px",
        color: getAdaptiveLabelColor(style?.labelColor),
        fontWeight: style?.labelFontWeight || "500",
      }}
      className="text-sm font-medium whitespace-nowrap"
    >
      {label}
      {required && <span className="ml-0.5 text-amber-500">*</span>}
    </Label>
  ) : null;

  const dateContent = (
    <div
      className={isHorizLabel ? "min-w-0 flex-1" : "h-full w-full"}
      style={isHorizLabel ? { height: "100%" } : undefined}
    >
      {renderDatePicker()}
    </div>
  );

  if (isHorizLabel && showLabel) {
    return (
      <div
        ref={ref}
        id={id}
        className={cn(
          "flex flex-col gap-1",
          labelPos === "left" ? "sm:flex-row sm:items-center" : "sm:flex-row-reverse sm:items-center",
        )}
        style={{
          width: componentWidth,
          height: componentHeight,
          gap: labelGapValue,
        }}
      >
        <Label
          htmlFor={id}
          style={{
            fontSize: style?.labelFontSize || "14px",
            color: getAdaptiveLabelColor(style?.labelColor),
            fontWeight: style?.labelFontWeight || "500",
          }}
          className="w-full text-sm font-medium whitespace-nowrap sm:w-[120px] sm:shrink-0"
        >
          {label}
          {required && <span className="ml-0.5 text-amber-500">*</span>}
        </Label>
        <div className="w-full min-w-0 flex-1">{renderDatePicker()}</div>
      </div>
    );
  }

  return (
    <div
      ref={ref}
      id={id}
      className="relative"
      style={{
        width: componentWidth,
        height: componentHeight,
      }}
    >
      {labelElement}
      {dateContent}
    </div>
  );
});

V2Date.displayName = "V2Date";

export default V2Date;
