"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { useLocale, useTranslations } from "next-intl";

import { Typography } from "@/components/ui";
import { SelectInput } from "@/components/ui/SelectInput/SelectInput";

import styles from "./DatePicker.module.scss";

const isValidDate = (year: number, month: number, day: number) => {
  if (!year || !month || !day) return false;
  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 };
};

// Упрощенное определение порядка полей даты на основе локали.
// В реальном приложении здесь лучше использовать данные из next-intl.
const getDateInputLocaleFormat = (locale: string): ("d" | "m" | "y")[] => {
  const format = new Intl.DateTimeFormat(locale).format(new Date(2001, 1, 3)); // Используем 3/Feb/2001
  if (/^3.*2/.test(format)) return ["d", "m", "y"]; // 3/2/2001 -> d/m/y
  if (/^2.*3/.test(format)) return ["m", "d", "y"]; // 2/3/2001 -> m/d/y
  return ["y", "m", "d"]; // 2001/2/3 -> y/m/d
};

interface DatePickerProps {
  label?: string;
  value: string | null;
  onChange: (value: string | null) => void;
  error?: string;
  maxYear?: number;
  yearsRange?: number;
  onBlur?: () => void;
}

export default function DatePicker({
  label,
  value,
  onChange,
  error,
  maxYear = new Date().getFullYear() - 11,
  yearsRange = 100,
  onBlur,
}: DatePickerProps) {
  const t = useTranslations("DatePicker");
  const locale = useLocale();

  const [year, setYear] = useState("");
  const [month, setMonth] = useState("");
  const [day, setDay] = useState("");

  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 !== value) {
        onChange(newValue);
      }
    },
    [onChange, value]
  );

  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(
    () =>
      Array.from({ length: 12 }, (_, i) => ({
        value: String(i + 1).padStart(2, "0"),
        label: String(i + 1),
      })),
    []
  );

  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(locale),
    [locale]
  );

  const handleYearChange = useCallback(
    (e: React.ChangeEvent<HTMLSelectElement>) => {
      setYear(e.target.value);
    },
    []
  );

  const handleMonthChange = useCallback(
    (e: React.ChangeEvent<HTMLSelectElement>) => {
      setMonth(e.target.value);
    },
    []
  );

  const handleDayChange = useCallback(
    (e: React.ChangeEvent<HTMLSelectElement>) => {
      setDay(e.target.value);
    },
    []
  );

  const inputs = {
    d: (
      <SelectInput
        key="d"
        value={day}
        onChange={handleDayChange}
        options={dayOptions}
        placeholder={t("day")}
      />
    ),
    m: (
      <SelectInput
        key="m"
        value={month}
        onChange={handleMonthChange}
        options={monthOptions}
        placeholder={t("month")}
      />
    ),
    y: (
      <SelectInput
        key="y"
        value={year}
        onChange={handleYearChange}
        options={yearOptions}
        placeholder={t("year")}
      />
    ),
  };

  return (
    <div className={styles.container} onBlur={onBlur}>
      {label && (
        <Typography as="p" size="sm" align="left" className={styles.mainLabel}>
          {label}
        </Typography>
      )}
      <div className={styles.inputsWrapper}>
        {localeFormat.map(format => inputs[format])}
      </div>
      {error && (
        <Typography
          as="p"
          size="xs"
          color="danger"
          align="left"
          className={styles.errorText}
        >
          {error}
        </Typography>
      )}
    </div>
  );
}
