import React, { useEffect, useRef, useState } from "react";
import moment from "jalali-moment";
import {
  bgInputPrimaryColor,
  mobileBorders,
  textColor,
} from "../../data/getColorBasedOnMode";
import { getSizeStyles } from "../../data/getInputSizes";
import { checkIsMobile } from "../../utils/checkIsMobile";

interface DatePickerProps {
  value?: string;
  placeholderColor?: string;
  onChange: (value: string) => void;
  label?: string;
  disabled?: boolean;
  isTable?: boolean;
  fullWidth?: boolean;
  className?: string;
  minYear?: number;
  maxYear?: number;
  size?: "small" | "medium" | "large";
}

const persianMonths = [
  "فروردین",
  "اردیبهشت",
  "خرداد",
  "تیر",
  "مرداد",
  "شهریور",
  "مهر",
  "آبان",
  "آذر",
  "دی",
  "بهمن",
  "اسفند",
];

const persianWeekDays = ["ش", "ی", "د", "س", "چ", "پ", "ج"];

const DatePicker: React.FC<DatePickerProps> = ({
  onChange,
  label = "تاریخ",
  disabled = false,
  isTable = false,
  className = "",
  value = "",
  placeholderColor = "",
  minYear = 1390,
  maxYear = 1410,
  size = "medium",
}) => {
  const pickerRef = useRef<HTMLDivElement | null>(null);
  const [isOpen, setIsOpen] = useState(false);

  const today = moment().locale("fa");

  const [selectedYear, setSelectedYear] = useState<number>(
    parseInt(today.format("jYYYY"))
  );
  const [selectedMonthIndex, setSelectedMonthIndex] = useState<number>(
    parseInt(today.format("jM")) - 1
  );
  const [selectedDay, setSelectedDay] = useState<number>(
    parseInt(today.format("jD"))
  );

  const dayRef = useRef<HTMLDivElement>(null);
  const monthRef = useRef<HTMLDivElement>(null);
  const yearRef = useRef<HTMLDivElement>(null);

  const daysInMonth = moment(
    `${selectedYear}/${selectedMonthIndex + 1}/1`,
    "jYYYY/jM/jD"
  ).jDaysInMonth();

  useEffect(() => {
    if (value) {
      const jDate = moment(value, "YYYY-MM-DD").locale("fa");
      const jYear = parseInt(jDate.format("jYYYY"));
      const jMonth = parseInt(jDate.format("jM")) - 1;
      const jDay = parseInt(jDate.format("jD"));

      setSelectedYear(jYear);
      setSelectedMonthIndex(jMonth);
      setSelectedDay(jDay);
    }
  }, [value]);

  useEffect(() => {
    const daysInNewMonth = moment(
      `${selectedYear}/${selectedMonthIndex + 1}/1`,
      "jYYYY/jM/jD"
    ).jDaysInMonth();
    if (selectedDay > daysInNewMonth) {
      setSelectedDay(daysInNewMonth);
    }
  }, [selectedYear, selectedMonthIndex]);

  useEffect(() => {
    if (isOpen) {
      const scrollToSelected = (
        ref: React.RefObject<HTMLDivElement>,
        selector: string
      ) => {
        const el = ref.current?.querySelector(selector);
        el?.scrollIntoView({ behavior: "auto", block: "nearest" });
      };

      scrollToSelected(
        dayRef as React.RefObject<HTMLDivElement>,
        ".selected-day"
      );
      scrollToSelected(
        monthRef as React.RefObject<HTMLDivElement>,
        ".selected-month"
      );
      scrollToSelected(
        yearRef as React.RefObject<HTMLDivElement>,
        ".selected-year"
      );
    }
  }, [isOpen]);

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        pickerRef.current &&
        !pickerRef.current.contains(event.target as Node)
      ) {
        setIsOpen(false);
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
  }, []);

  useEffect(() => {
    const jDate = moment(
      `${selectedYear}/${selectedMonthIndex + 1}/${selectedDay}`,
      "jYYYY/jM/jD"
    );
    const gDate = jDate.locale("en").format("YYYY-MM-DD");

    if (value !== gDate) {
      onChange(gDate);
    }
  }, [selectedYear, selectedMonthIndex, selectedDay, value]);

  const getDayOfWeek = (day: number) => {
    const date = moment(
      `${selectedYear}/${selectedMonthIndex + 1}/${day}`,
      "jYYYY/jM/jD"
    );
    return persianWeekDays[date.day()];
  };

  return (
    <div className={`relative w-full ${className}`} ref={pickerRef}>
      <div className="flex items-center gap-2 ">
        <label
          onClick={() => setIsOpen(!isOpen)}
          className={`text-sm text-nowrap select-none  ${
            disabled ? "text-gray-400" : textColor
          }`}
        >
          {label}
        </label>
        <input
          readOnly
          value={`${selectedDay} / ${persianMonths[selectedMonthIndex]} / ${selectedYear} `}
          onClick={() => setIsOpen(!isOpen)}
          className={`${
            isTable ? "w-full md:w-30 text-xs" : "w-full min-w-40 text-sm"
          } border-1  focus:ring-dark-400 rounded-lg text-center  text-dark-800 dark:text-gray-100 ${
            disabled && "opacity-80"
          } ${disabled ? "text-gray-400" : textColor} ${
            placeholderColor
              ? placeholderColor
              : checkIsMobile()
              ? "bg-gray-50 border-gray-300"
              : "bg-white border-black-100"
          } ${checkIsMobile() && mobileBorders} ${
            getSizeStyles(size).padding
          } ${bgInputPrimaryColor} ${disabled ? "text-gray-400" : textColor}`}
          disabled={disabled}
        />
      </div>

      {isOpen && (
        <div
          className={`absolute z-50 mt-2 flex rounded-lg shadow-lg text-white text-sm w-56 bg-white dark:bg-dark-500 `}
        >
          {[
            {
              label: "روز",
              options: Array.from({ length: daysInMonth }, (_, i) => i + 1),
              selected: selectedDay,
              setSelected: setSelectedDay,
              ref: dayRef,
              selectedClass: "selected-day",
            },
            {
              label: "ماه",
              options: persianMonths,
              selected: selectedMonthIndex,
              setSelected: (v: number) => setSelectedMonthIndex(v),
              ref: monthRef,
              selectedClass: "selected-month",
            },
            {
              label: "سال",
              options: Array.from(
                { length: maxYear - minYear + 1 },
                (_, i) => minYear + i
              ),
              selected: selectedYear,
              setSelected: setSelectedYear,
              ref: yearRef,
              selectedClass: "selected-year",
            },
          ].map(
            (
              { label, options, selected, setSelected, ref, selectedClass },
              colIndex
            ) => (
              <div
                key={label}
                ref={ref}
                className="flex-1 h-48 overflow-y-auto snap-y snap-mandatory text-center space-y-1 scrollbar-hide relative"
              >
                <ul className="relative z-20">
                  <li className="h-6" aria-hidden />
                  {options.map((opt, idx) => {
                    const isString = typeof opt === "string";
                    const isSelected =
                      (colIndex === 0 && opt === selected) ||
                      (colIndex === 1 && idx === selected) ||
                      (colIndex === 2 && opt === selected);
                    const itemClass = isSelected ? selectedClass : "";

                    return (
                      <li
                        key={isString ? opt : String(opt)}
                        className={`py-2 cursor-pointer transition ${itemClass} ${
                          isSelected
                            ? "text-amber-900 dark:text-amber-200 font-bold scale-105"
                            : textColor
                        } ${
                          (opt === parseInt(today.format("jD")) ||
                            opt ===
                              persianMonths[parseInt(today.format("jM")) - 1] ||
                            opt === parseInt(today.format("jYYYY"))) &&
                          " decoration-cyan-200 rounded-4xl"
                        }`}
                        onClick={() =>
                          setSelected(colIndex === 1 ? idx : (opt as number))
                        }
                      >
                        {colIndex === 0 ? (
                          <span className="flex items-center justify-between mx-5">
                            <span className={`text-[10px]`}>
                              {getDayOfWeek((opt as number) + 1)}
                            </span>
                            <span
                              className={`${
                                opt === parseInt(today.format("jD")) &&
                                " underline underline-offset-4 decoration-cyan-200 rounded-4xl"
                              }`}
                            >
                              {opt}{" "}
                            </span>
                          </span>
                        ) : (
                          opt
                        )}
                      </li>
                    );
                  })}

                  <li className="h-6" aria-hidden />
                </ul>
              </div>
            )
          )}
        </div>
      )}
    </div>
  );
};

export default DatePicker;
