import React, {
  useEffect,
  useState,
  useRef,
  useMemo,
  useLayoutEffect,
} from "react";

import { monthsNumber } from "./constant";
import ChevronLeftOutlinedIcon from "@mui/icons-material/ChevronLeftOutlined";
import ChevronRightOutlinedIcon from "@mui/icons-material/ChevronRightOutlined";
import "./MonthPicker.styles.scss";
import { Select } from "../Select";
import { Button } from "../Button";
import { IconButton } from "@mui/material";
import { ReactComponent as CloseIcon } from "../../assets/close.svg";
import Portal from "../Portal";

export const MonthPicker = ({
  customYears,
  locale = "en-US",
  isMandatory = false,
  displayFormat = "MM/YYYY",
  focusedInput = null,
  onApply = () => {},
  selectedMonth: initialSelectedMonth = null,
  isOutsideRange = () => false,
  disabled = false,
  showYearSelect = false,
  isError = false,
  customWidth = "282px",
  withPortal = false,
  portalContainer = document.body,
  portalClassName = "",
  onMonthChange = () => {},
}) => {
  const today = new Date();
  const currentYear = today.getFullYear();
  const yrs = Array.from({ length: 10 }, (_, index) => {
    const year = (currentYear - 5 + index).toString();
    return { label: year, value: year };
  });

  const years = customYears && customYears.length > 0 ? customYears : yrs;

  const [openCalendar, setOpenCalendar] = useState(false);
  const [selectedMonth, setSelectedMonth] = useState(initialSelectedMonth);
  const [yearOffset, setYearOffset] = useState(0);
  const [open, setOpen] = useState(false);
  const [currentOptions, setCurrentOptions] = useState(years);
  const [selectedOptions, setSelectedOptions] = useState({
    label: today.getFullYear().toString(),
    value: today.getFullYear().toString(),
  });
  const inputContainerRef = useRef(null);
  const dropDownContainerRef = useRef(null);
  const dropDownRef = useRef(null);
  const monthInputRef = useRef(null);
  const monthPickerMainContainerRef = useRef(null);
  const [isSelectOpen, setIsSelectOpen] = useState(false);
  const [focusInput, setFocusInput] = useState(focusedInput);
  const [dummySelectedMonth, setDummySelectedMonth] =
    useState(initialSelectedMonth);
  const isResetClicked = useRef(false);
  const [prevIconDisabled, setPrevIconDisabled] = useState(false);
  const [nextIconDisabled, setNextIconDisabled] = useState(false);
  const [position, setPosition] = useState({
    x: 0,
    y: 0,
    offsetHeight: 0,
    offsetWidth: 0,
  });
  const [focusedMonthIndex, setFocusedMonthIndex] = useState(null);
  const monthButtonRefs = useRef([]);
  const keyboardOpenRef = useRef(false);
  const pendingFocusRef = useRef(null);
  // const isLastYear = currentYear + yearOffset + 1 > currentYear;

  const handleMonthClick = (month) => {
    setSelectedMonth(month);
    onMonthChange(month);
  };

  const formatDate = (date) => {
    if (!date) return "";

    const month = new Intl.DateTimeFormat("en-US", { month: "2-digit" }).format(
      date
    );
    const year = new Intl.DateTimeFormat("en-US", { year: "numeric" }).format(
      date
    );

    if (displayFormat === "YYYY/MM") {
      return `${year}/${month}`;
    }
    // Default to MM/YYYY format
    return `${month}/${year}`;
  };

  const isMonthSelected = (month) => {
    if (!selectedMonth || !month) return false;
    return (
      selectedMonth.getMonth() === month.getMonth() &&
      selectedMonth.getFullYear() === month.getFullYear()
    );
  };

  const renderMonth = (year, type, month) => {
    const monthStart = new Date(year, month, 1);
    const isSelected = isMonthSelected(monthStart);
    const isDisabled = isOutsideRange(monthStart);
    const isCurrentMonth =
      monthStart.getFullYear() === today.getFullYear() &&
      monthStart.getMonth() === today.getMonth();

    const getVariants = () => {
      if (isSelected) return "selected";
      if (isDisabled) return "disabled";
      if (isCurrentMonth) return "current-month";
      return "";
    };

    return (
      <button
        key={month}
        type="button"
        className={`mp-month month${month + 1} ${getVariants()}`}
        tabIndex={focusedMonthIndex === month ? 0 : -1}
        ref={(el) => (monthButtonRefs.current[month] = el)}
        disabled={isDisabled}
        onClick={() => handleMonthClick(monthStart, type)}
        onFocus={() => setFocusedMonthIndex(month)}
        aria-label={new Intl.DateTimeFormat(locale, {
          month: "long",
          year: "numeric",
        }).format(monthStart)}
        aria-pressed={isSelected}
      >
        <span className="mp-calendar-month">
          {new Intl.DateTimeFormat(locale, { month: "short" }).format(
            monthStart
          )}
        </span>
      </button>
    );
  };

  const renderYear = (year, type) => (
    <div className="mp-render-month">
      {monthsNumber.map((month) => renderMonth(year, type, month))}
    </div>
  );

  const handlePrevYear = () => {
    const offset = yearOffset - 1;

    setYearOffset(offset);
    setSelectedOptions((prevState) => {
      const newValue = parseInt(prevState.value) - 1;
      if (newValue == currentOptions[0].value) {
        setPrevIconDisabled(true);
      }
      return { label: newValue.toString(), value: newValue.toString() };
    });
  };

  const handleNextYear = () => {
    const offset = yearOffset + 1;

    setYearOffset(offset);
    setSelectedOptions((prevState) => {
      const newValue = parseInt(prevState.value) + 1;
      return { label: newValue.toString(), value: newValue.toString() };
    });
  };

  const hanldeInputClick = (inputType) => {
    setOpenCalendar(true);
    setFocusInput(inputType);
  };

  const handleInputKeyDown = (e) => {
    if (e.key === "Enter" && !openCalendar) {
      keyboardOpenRef.current = true;
      hanldeInputClick("selected month");
      setFocusedMonthIndex(selectedMonth?.getMonth() ?? 0);
    }
  };

  const handleCalendarKeyDown = (e) => {
    if (e.key === "Escape") {
      handleCancel();
      monthInputRef.current?.focus();
      return;
    }
    const moves = { ArrowRight: 1, ArrowLeft: -1, ArrowDown: 4, ArrowUp: -4 };
    if (moves[e.key] !== undefined && focusedMonthIndex !== null) {
      e.preventDefault();
      const next = focusedMonthIndex + moves[e.key];
      if (next > 11) {
        if (!nextIconDisabled) {
          pendingFocusRef.current = next - 12;
          handleNextYear();
        }
      } else if (next < 0) {
        if (!prevIconDisabled) {
          pendingFocusRef.current = next + 12;
          handlePrevYear();
        }
      } else {
        setFocusedMonthIndex(next);
        monthButtonRefs.current[next]?.focus();
      }
    }
  };

  useEffect(() => {
    if (focusInput === "selected month") {
      monthInputRef.current.focus();
    }
  }, [focusInput]);

  useEffect(() => {
    if (openCalendar && keyboardOpenRef.current && focusedMonthIndex !== null) {
      const timer = setTimeout(() => {
        monthButtonRefs.current[focusedMonthIndex]?.focus();
      }, 0);
      keyboardOpenRef.current = false;
      return () => clearTimeout(timer);
    }
  }, [openCalendar]);

  useEffect(() => {
    if (pendingFocusRef.current !== null) {
      const idx = pendingFocusRef.current;
      pendingFocusRef.current = null;
      setFocusedMonthIndex(idx);
      setTimeout(() => {
        monthButtonRefs.current[idx]?.focus();
      }, 0);
    }
  }, [selectedOptions]);
  const handleClickOutside = (event) => {
    if (
      inputContainerRef.current &&
      !inputContainerRef.current.contains(event.target) &&
      dropDownContainerRef.current &&
      !dropDownContainerRef.current.contains(event.target) &&
      !event.target.closest(".mp-close-icon") &&
      !event.target.closest(".month-picker-year-select-dropdown") &&
      !isSelectOpen
    ) {
      setOpenCalendar(false);
      if (isResetClicked.current) {
        setSelectedMonth(null);
        setDummySelectedMonth(null);
        isResetClicked.current = false;
      } else {
        setSelectedMonth(dummySelectedMonth);
      }
    }
  };

  useEffect(() => {
    document.addEventListener("click", handleClickOutside);

    return () => {
      document.removeEventListener("click", handleClickOutside);
    };
  }, [openCalendar]);

  const handleClear = () => {
    setSelectedMonth(null);
    setDummySelectedMonth(null);
    isResetClicked.current = true;
  };

  const handleCancel = () => {
    setOpenCalendar(false);
    setSelectedMonth(dummySelectedMonth);
  };

  const handleApply = () => {
    setOpenCalendar(false);
    setDummySelectedMonth(selectedMonth);
    onApply?.(selectedMonth);
  };

  // Calculate position for portal
  useLayoutEffect(() => {
    if (withPortal && monthPickerMainContainerRef.current) {
      const scrollY = window.scrollY || document.documentElement.scrollTop;
      const {
        x,
        y,
        height: offsetHeight,
        width: offsetWidth,
      } = monthPickerMainContainerRef.current.getBoundingClientRect();
      setPosition({ x, y: y + scrollY, offsetHeight, offsetWidth });
    }
  }, [openCalendar, withPortal]);

  useEffect(() => {
    if (selectedOptions.value == currentOptions[0].value) {
      setPrevIconDisabled(true);
    } else {
      setPrevIconDisabled(false);
    }
    if (
      selectedOptions.value == currentOptions[currentOptions.length - 1].value
    ) {
      setNextIconDisabled(true);
    } else {
      setNextIconDisabled(false);
    }
  }, [selectedOptions]);

  const computedIsError = useMemo(
    () =>
      Boolean(isError || (selectedMonth && isOutsideRange?.(selectedMonth))),
    [isError, selectedMonth]
  );

  const renderCalendarContent = () => (
    <div
      className="mp-single-month-picker-container"
      ref={dropDownContainerRef}
      onKeyDown={handleCalendarKeyDown}
      role="dialog"
      aria-label="Month picker"
    >
      <div className="mp-header">
        <IconButton
          onClick={handlePrevYear}
          disableRipple
          disabled={prevIconDisabled}
          sx={{padding: 0}}
        >
          <ChevronLeftOutlinedIcon className="mp-left-icon" />
        </IconButton>
        {showYearSelect ? (
          <div className="month-picker-year-select-container">
            <Select
              name="year-select"
              isWithSearch
              withPortal
              dropDownPortalClassName={"month-picker-year-select-dropdown"}
              isOpen={isSelectOpen}
              setIsOpen={setIsSelectOpen}
              currentOptions={currentOptions}
              setCurrentOptions={setCurrentOptions}
              initialOptions={years}
              selectedOptions={selectedOptions}
              setSelectedOptions={setSelectedOptions}
              ref={dropDownRef}
              minWidth={62}
            />
          </div>
        ) : (
          <div className="mp-selected-year">{selectedOptions.value}</div>
        )}
        <IconButton
          onClick={handleNextYear}
          disableRipple
          disabled={nextIconDisabled}
          sx={{padding: 0}}
        >
          <ChevronRightOutlinedIcon className="mp-right-icon"/>
        </IconButton>
      </div>
      <div className="mp-render-month-container">
        {renderYear(parseInt(selectedOptions.value), "start")}
      </div>
      <hr className="mp-vertical-line" />
      <div className="mp-calendar-button">
        <Button variant="tertiary" onClick={handleCancel}>
          Cancel
        </Button>
        <Button onClick={handleApply}>Apply</Button>
      </div>
    </div>
  );

  return (
    <div
      className={`impact-singleMonthPicker-main-container single-month-label-flex-column ${
        disabled ? "disabled" : ""
      }`}
    >
      <div className="singleMonthPicker-label">
        Select Month & Year
        {isMandatory && <span style={{ color: "red" }}>*</span>}
      </div>

      <div
        className="singleMonthPicker-container"
        style={{ width: customWidth }}
        ref={monthPickerMainContainerRef}
      >
        <div
          className="singleMonthPicker-input-container"
          ref={inputContainerRef}
        >
          <input
            type="text"
            placeholder={`Select ${displayFormat}`}
            readOnly
            className={`singleMonthPicker-input-field ${
              selectedMonth ? "active" : ""
            } ${computedIsError ? "error" : ""}`}
            value={selectedMonth ? `${formatDate(selectedMonth)}` : ""}
            ref={monthInputRef}
            onClick={() => hanldeInputClick("selected month")}
            onFocus={() => setFocusInput("selected month")}
            onBlur={() => setFocusInput(null)}
            onKeyDown={handleInputKeyDown}
            aria-label="Selected month"
            aria-haspopup="dialog"
            aria-expanded={openCalendar}
          />
          {selectedMonth && (
            <CloseIcon 
              className="mp-close-icon" 
              onClick={handleClear} 
              tabIndex={0} 
              onKeyDown={(e) => {
                if (e.key === "Enter" || e.key === " ") {
                  e.preventDefault();
                  handleClear();
                }
              }}
              aria-label="Close month picker"
            />
          )}
        </div>
        {openCalendar &&
          (withPortal ? (
            <Portal container={portalContainer}>
              <div
                className={`impact-portal-container ${portalClassName}`}
                style={{
                  top: position.y || position.top,
                  left: position.x || position.left,
                  bottom: position.bottom,
                  right: position.right,
                  width: position.offsetWidth || 0 + "px",
                }}
              >
                {renderCalendarContent()}
              </div>
              <div
                className="ia-select-container-v3-blanket"
                onClick={() => setOpenCalendar(false)}
              />
            </Portal>
          ) : (
            renderCalendarContent()
          ))}
      </div>
    </div>
  );
};
