// File: src/components/UIX/DatePicker/DatePicker.jsx
// Enhanced DatePicker with custom calendar dropdown - Performance Optimized

import React, {
  useState,
  useRef,
  useEffect,
  useMemo,
  useCallback,
  memo,
} from "react";
import { createPortal } from "react-dom";
import {
  CalendarDaysIcon,
  ChevronLeftIcon,
  ChevronRightIcon,
  ExclamationTriangleIcon,
} from "@heroicons/react/24/outline";
import { useUIXTheme } from "../themes/useUIXTheme.jsx";

// Move all constants outside component to prevent recreation
const SIZE_CLASSES = {
  sm: "px-3 py-2 text-sm",
  md: "px-4 py-3 text-base",
  lg: "px-5 py-4 text-base sm:text-lg",
};

const LABEL_SIZE_CLASSES = {
  sm: "text-sm",
  md: "text-base",
  lg: "text-base sm:text-lg",
};

const MONTH_NAMES = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December",
];

const DAY_HEADERS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];

// Static helper functions outside component
const formatDisplayDate = (date) => {
  if (!date) return "";
  return date.toLocaleDateString("en-US", {
    year: "numeric",
    month: "long",
    day: "numeric",
  });
};

const formatInputDate = (date) => {
  if (!date) return "";
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
};

const isToday = (date) => {
  if (!date) return false;
  const today = new Date();
  return date.toDateString() === today.toDateString();
};

const isSameDate = (date1, date2) => {
  if (!date1 || !date2) return false;
  return date1.toDateString() === date2.toDateString();
};

const getCalendarDays = (currentMonth) => {
  const year = currentMonth.getFullYear();
  const month = currentMonth.getMonth();

  const firstDay = new Date(year, month, 1);
  const lastDay = new Date(year, month + 1, 0);
  const daysInMonth = lastDay.getDate();
  const startingDayOfWeek = firstDay.getDay();

  const days = [];

  // Add empty cells for days before the first day of the month
  for (let i = 0; i < startingDayOfWeek; i++) {
    days.push(null);
  }

  // Add days of the month
  for (let day = 1; day <= daysInMonth; day++) {
    days.push(new Date(year, month, day));
  }

  return days;
};

/**
 * Enhanced DatePicker Component with Custom Calendar Dropdown
 * Provides a beautiful, customizable date picker that matches our UIX design system
 */
const DatePicker = memo(
  ({
    label,
    value,
    onChange,
    error,
    disabled = false,
    required = false,
    min,
    max,
    helperText,
    className = "",
    placeholder = "Select a date",
    size = "lg",
  }) => {
    const { getThemeClasses } = useUIXTheme();
    const [isOpen, setIsOpen] = useState(false);
    const [currentMonth, setCurrentMonth] = useState(() => {
      if (value) {
        const date = new Date(value);
        return new Date(date.getFullYear(), date.getMonth(), 1);
      }
      return new Date();
    });

    const dropdownRef = useRef(null);
    const inputRef = useRef(null);
    const portalContainerRef = useRef(null);

    // Parse the selected date from value prop
    const selectedDate = useMemo(() => {
      return value ? new Date(value) : null;
    }, [value]);

    // Create portal container on mount, cleanup on unmount
    useEffect(() => {
      if (!portalContainerRef.current) {
        portalContainerRef.current = document.createElement("div");
        portalContainerRef.current.style.position = "absolute";
        portalContainerRef.current.style.zIndex = "9999";
        document.body.appendChild(portalContainerRef.current);
      }

      return () => {
        if (
          portalContainerRef.current &&
          document.body.contains(portalContainerRef.current)
        ) {
          document.body.removeChild(portalContainerRef.current);
          portalContainerRef.current = null;
        }
      };
    }, []);

    // Update dropdown position when opened
    const updateDropdownPosition = useCallback(() => {
      if (inputRef.current && portalContainerRef.current) {
        const rect = inputRef.current.getBoundingClientRect();
        const scrollTop =
          window.pageYOffset || document.documentElement.scrollTop;
        const scrollLeft =
          window.pageXOffset || document.documentElement.scrollLeft;

        portalContainerRef.current.style.top = `${rect.bottom + scrollTop + 8}px`;
        portalContainerRef.current.style.left = `${rect.left + scrollLeft}px`;
      }
    }, []);

    // Handle click outside
    useEffect(() => {
      if (!isOpen) return;

      const handleClickOutside = (event) => {
        if (
          dropdownRef.current &&
          !dropdownRef.current.contains(event.target) &&
          inputRef.current &&
          !inputRef.current.contains(event.target)
        ) {
          setIsOpen(false);
        }
      };

      // Add small delay to prevent immediate closing
      const timeoutId = setTimeout(() => {
        document.addEventListener("mousedown", handleClickOutside);
      }, 0);

      return () => {
        clearTimeout(timeoutId);
        document.removeEventListener("mousedown", handleClickOutside);
      };
    }, [isOpen]);

    // Update position on scroll or resize when dropdown is open
    useEffect(() => {
      if (!isOpen) return;

      updateDropdownPosition();

      const handleScroll = () => updateDropdownPosition();
      const handleResize = () => updateDropdownPosition();

      window.addEventListener("scroll", handleScroll, true);
      window.addEventListener("resize", handleResize);

      return () => {
        window.removeEventListener("scroll", handleScroll, true);
        window.removeEventListener("resize", handleResize);
      };
    }, [isOpen, updateDropdownPosition]);

    // Update current month when value changes
    useEffect(() => {
      if (value) {
        const date = new Date(value);
        setCurrentMonth(new Date(date.getFullYear(), date.getMonth(), 1));
      }
    }, [value]);

    // Memoized event handlers
    const handleDateSelect = useCallback(
      (date) => {
        const formattedDate = formatInputDate(date);
        onChange(formattedDate);
        setIsOpen(false);
      },
      [onChange],
    );

    const handleToggleOpen = useCallback(() => {
      if (!disabled) {
        setIsOpen((prev) => !prev);
      }
    }, [disabled]);

    const navigateMonth = useCallback((direction) => {
      setCurrentMonth((prev) => {
        const newMonth = new Date(prev);
        newMonth.setMonth(prev.getMonth() + direction);
        return newMonth;
      });
    }, []);

    const handleToday = useCallback(() => {
      handleDateSelect(new Date());
    }, [handleDateSelect]);

    const handleClear = useCallback(() => {
      onChange("");
      setIsOpen(false);
    }, [onChange]);

    // Memoize date checking functions
    const isDateDisabled = useCallback(
      (date) => {
        if (!date) return false;
        if (min && date < new Date(min)) return true;
        if (max && date > new Date(max)) return true;
        return false;
      },
      [min, max],
    );

    const isSelected = useCallback(
      (date) => {
        return isSameDate(date, selectedDate);
      },
      [selectedDate],
    );

    // Memoize calendar days
    const days = useMemo(() => getCalendarDays(currentMonth), [currentMonth]);

    // Memoize formatted display value
    const displayValue = useMemo(() => {
      return selectedDate ? formatDisplayDate(selectedDate) : placeholder;
    }, [selectedDate, placeholder]);

    // Memoize classes
    const sizeClass = SIZE_CLASSES[size];
    const labelSizeClass = LABEL_SIZE_CLASSES[size];

    const inputClasses = useMemo(
      () =>
        `
    w-full
    ${sizeClass}
    pl-10 pr-5
    border-2 border-gray-200 rounded-xl shadow-sm
    transition-all duration-200
    cursor-pointer
    flex items-center justify-between
    ${error ? `${getThemeClasses("input-border-error")}` : isOpen ? getThemeClasses("datepicker-focus") : "border-gray-300 hover:border-gray-400"}
    ${disabled ? "bg-gray-50 cursor-not-allowed" : "bg-white"}
  `
          .replace(/\s+/g, " ")
          .trim(),
      [sizeClass, error, isOpen, disabled, getThemeClasses],
    );

    const labelClasses = useMemo(
      () =>
        `block ${labelSizeClass} font-semibold text-gray-700 mb-3 flex items-center`,
      [labelSizeClass],
    );

    return (
      <div className={`${className} relative`}>
        {label && (
          <label className={labelClasses}>
            {label}
            {required && <span className={`${getThemeClasses("text-danger")} ml-1`}>*</span>}
          </label>
        )}

        <div className="relative">
          <div
            ref={inputRef}
            onClick={handleToggleOpen}
            className={inputClasses}
          >
            <CalendarDaysIcon className="absolute left-3 h-5 w-5 text-gray-400" />
            <span className={selectedDate ? "text-gray-900" : "text-gray-400"}>
              {displayValue}
            </span>
            <CalendarDaysIcon className="h-4 w-4 text-gray-400" />
          </div>
        </div>

        {/* Custom Calendar Dropdown - Rendered as Portal */}
        {isOpen &&
          !disabled &&
          portalContainerRef.current &&
          createPortal(
            <div
              ref={dropdownRef}
              className="w-80 bg-white border border-gray-200 rounded-xl shadow-2xl p-4"
              style={{ maxHeight: "400px" }}
            >
              {/* Month Navigation */}
              <div className="flex items-center justify-between mb-4">
                <button
                  type="button"
                  onClick={() => navigateMonth(-1)}
                  className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
                >
                  <ChevronLeftIcon className="h-5 w-5 text-gray-600" />
                </button>
                <h3 className="text-lg font-semibold text-gray-900">
                  {MONTH_NAMES[currentMonth.getMonth()]}{" "}
                  {currentMonth.getFullYear()}
                </h3>
                <button
                  type="button"
                  onClick={() => navigateMonth(1)}
                  className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
                >
                  <ChevronRightIcon className="h-5 w-5 text-gray-600" />
                </button>
              </div>

              {/* Day Headers */}
              <div className="grid grid-cols-7 gap-1 mb-2">
                {DAY_HEADERS.map((day) => (
                  <div
                    key={day}
                    className="text-center text-sm font-medium text-gray-500 py-2"
                  >
                    {day}
                  </div>
                ))}
              </div>

              {/* Calendar Days */}
              <div className="grid grid-cols-7 gap-1">
                {days.map((date, index) => {
                  const disabled = !date || isDateDisabled(date);
                  const selected = isSelected(date);
                  const today = isToday(date);

                  return (
                    <button
                      key={index}
                      type="button"
                      onClick={() =>
                        date && !disabled && handleDateSelect(date)
                      }
                      disabled={disabled}
                      className={`
                      h-10 w-10 rounded-lg text-sm font-medium transition-all duration-200
                      ${!date ? "invisible" : ""}
                      ${disabled ? "text-gray-300 cursor-not-allowed" : "hover:bg-gray-100 cursor-pointer"}
                      ${selected ? getThemeClasses("datepicker-selected") : today ? getThemeClasses("datepicker-today") : "text-gray-700"}
                    `
                        .replace(/\s+/g, " ")
                        .trim()}
                    >
                      {date?.getDate()}
                    </button>
                  );
                })}
              </div>

              {/* Quick Actions */}
              <div className="flex justify-between items-center mt-4 pt-4 border-t border-gray-200">
                <button
                  type="button"
                  onClick={handleToday}
                  className={`text-sm ${getThemeClasses("link-primary")} font-medium`}
                >
                  Today
                </button>
                {selectedDate && (
                  <button
                    type="button"
                    onClick={handleClear}
                    className="text-sm text-gray-500 hover:text-gray-700"
                  >
                    Clear
                  </button>
                )}
              </div>
            </div>,
            portalContainerRef.current,
          )}

        {helperText && !error && (
          <p className="mt-1 text-xs text-gray-500">{helperText}</p>
        )}
        {error && (
          <p className={`mt-1 text-sm ${getThemeClasses("text-error")} flex items-center`}>
            <ExclamationTriangleIcon className="h-4 w-4 mr-1 flex-shrink-0" />
            {error}
          </p>
        )}
      </div>
    );
  },
);

// Add display name for better debugging
DatePicker.displayName = "DatePicker";

export default DatePicker;
