import { SelectInputProps } from "@/components/ui/SelectInput/SelectInput";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";

// Валидация даты без зависимости от часовых зон
// Проверяет что дата существует (например, 31 февраля - невалидна)
const isValidDate = (year: number, month: number, day: number) => {
  if (!year || !month || !day) return false;
  // Используем Date в локальной зоне только для валидации
  // Это безопасно, т.к. мы не сохраняем результат, только проверяем корректность
  const date = new Date(year, month - 1, day);
  return (
    date.getFullYear() === year &&
    date.getMonth() === month - 1 &&
    date.getDate() === day
  );
};

const parseDateValue = (
  value?: string | null
): { year: string; month: string; day: string } | null => {
  if (!value) return null;

  // Поддерживаем форматы: "2003-04-09" и "2003-04-09 12:00"
  const dateMatch = value.match(/^(\d{4})-(\d{2})-(\d{2})(?:\s+\d{2}:\d{2})?$/);

  if (!dateMatch) return null;

  const [, year, month, day] = dateMatch;
  return { year, month, day };
};

// Порядок полей даты: месяц-день-год (американский формат)
// Этот формат используется для всех локалей чтобы обеспечить единообразие
const getDateInputLocaleFormat = (): ("d" | "m" | "y")[] => {
  // Всегда используем американский формат: месяц, день, год
  return ["m", "d", "y"];
};

interface UseDateInputProps {
  value?: string | null;
  onChange?: (value: string | null) => void;
  maxYear?: number;
  yearsRange?: number;
}

export const useDateInput = ({
  value,
  onChange,
  maxYear = new Date().getFullYear() - 11,
  yearsRange = 100,
}: UseDateInputProps) => {
  const [year, setYear] = useState("");
  const [month, setMonth] = useState("");
  const [day, setDay] = useState("");

  const lastEmittedValue = useRef<string | null>(null);

  useEffect(() => {
    const parsedDate = parseDateValue(value);

    if (parsedDate) {
      setYear(parsedDate.year);
      setMonth(parsedDate.month);
      setDay(parsedDate.day);
    } else {
      setYear("");
      setMonth("");
      setDay("");
    }
  }, [value]);

  const updateValue = useCallback(
    (newValue: string | null) => {
      if (newValue !== lastEmittedValue.current) {
        lastEmittedValue.current = newValue;
        onChange?.(newValue);
      }
    },
    [onChange]
  );

  useEffect(() => {
    const numericYear = Number(year);
    const numericMonth = Number(month);
    const numericDay = Number(day);

    if (isValidDate(numericYear, numericMonth, numericDay)) {
      const formattedDate = `${year}-${month}-${day}`;
      updateValue(formattedDate);
    } else {
      if (year || month || day) {
        updateValue(null);
      }
    }
  }, [year, month, day, updateValue]);

  const yearOptions = useMemo(
    () =>
      Array.from({ length: yearsRange }, (_, i) => ({
        value: maxYear - i,
        label: String(maxYear - i),
      })),
    [maxYear, yearsRange]
  );

  const monthOptions = useMemo(() => {
    const monthNames = [
      "January", "February", "March", "April", "May", "June",
      "July", "August", "September", "October", "November", "December"
    ];
    
    return Array.from({ length: 12 }, (_, i) => ({
      value: String(i + 1).padStart(2, "0"),
      label: monthNames[i],
    }));
  }, []);

  const dayOptions = useMemo(() => {
    const daysInMonth =
      year && month ? new Date(Number(year), Number(month), 0).getDate() : 31;
    return Array.from({ length: daysInMonth }, (_, i) => ({
      value: String(i + 1).padStart(2, "0"),
      label: String(i + 1),
    }));
  }, [year, month]);

  const localeFormat = useMemo(
    () => getDateInputLocaleFormat(),
    []
  );

  const handleYearChange: SelectInputProps["onValueChange"] = useCallback(
    (value: string) => {
      setYear(value);
    },
    []
  );

  const handleMonthChange: SelectInputProps["onValueChange"] = useCallback(
    (value: string) => {
      setMonth(value);
    },
    []
  );

  const handleDayChange: SelectInputProps["onValueChange"] = useCallback(
    (value: string) => {
      setDay(value);
    },
    []
  );

  return {
    year,
    month,
    day,
    yearOptions,
    monthOptions,
    dayOptions,
    localeFormat,
    handleYearChange,
    handleMonthChange,
    handleDayChange,
  };
};
