import React, { useEffect, useState, useRef, useMemo, useCallback, forwardRef, useImperativeHandle } from "react";
import dayjs from "dayjs";
import moment from "moment";
import localeData from "dayjs/plugin/localeData";
import "dayjs/locale/zh-cn";
import zhCN from './zh_CN';
import 'moment/locale/zh-cn';
import lunarjs from './calendar.min.js';
import { DatePicker } from "antd";
import weekOfYear from 'dayjs/plugin/weekOfYear';
import {
  DoubleLeftOutlined,
  DoubleRightOutlined,
  UpOutlined,
  DownOutlined,
  LeftOutlined,
  RightOutlined,
} from "@ant-design/icons";
import "./datePicker.scss";

// 国际化，设置周一为第一天
dayjs.extend(localeData);
dayjs.extend(weekOfYear);
dayjs.locale("zh-cn");
const throttle = (fun: (val: any) => void, time: number) => {
  let delay = 0;
  return (...params: any) => {
    const now = +new Date();
    if (now - delay > time) {
      fun.apply(this, params);
      delay = now;
    }
  };
};

type weekType = {
  id: number;
  name: string;
};
type touchType = { x: number; y: number };

type dayjsType = Array<dayjs.Dayjs>;

type generateWeekDataType = {
  currenWeekFirstDay: dayjs.Dayjs;
  generateWeekDateList: Array<dayjsType>;
};

type generateMonthDataType = {
  currentMonthFirstDay: dayjs.Dayjs;
  generateMonthDateList: Array<dayjsType>;
};
interface IProps {
  onDateSelected: (date: string, isInit?: boolean) => void;
  events: any[];
  /** 初始化日期 */
  initDate?: string;
  /** 是否展示日历, 仅展示切换功能， true： 切换操作有切换 周/月， false: 仅切换月 */
  showCalendar?: boolean;
  /** 视图类型 */
  viewType: string;
  /** 当不显示所有日历，手动点击前后切换后，触发fullcalendar组件切换的回调 */
  onToggleCalendar?: (dateType: string, toggleType: string, date: dayjs.Dayjs) => void;
  /** 当不显示所有日历，手动点击切换年月，触发fullcalendar组件gotoDate回调 */
  onSelectMonth?: (date: string) => void;
  /** 当面板选择的时候，触发年月视图的切换 */
  onPanelToggle?: (val, mode: string) => void;
  /** 是否周视图 */
  isWeekView?: boolean;
  /** 是否移动端 */
  isMobile?: boolean;

  render?: any;
  /** 提示文案 */
  alertText?: string;

}
const ScheduleList = (props: IProps, ref: any) => {
  const {
    onDateSelected,
    events = [],
    initDate,
    showCalendar = true,
    onToggleCalendar,
    onSelectMonth,
    onPanelToggle,
    viewType,
    isWeekView: defaultWeek = true,
    isMobile,
    render,
    alertText
  } = props;
  // const CalendarComp = () => {
  const { current } = useRef({
    currentDate: initDate ?? dayjs().format("YYYY-MM-DD"),
    // currentDate: initDate,
    isTouch: false,
    touchStartX: 0,
    touchStartY: 0,
    calendarRef: { offsetWidth: 0 },
  });

  const dayjsDate = dayjs(current.currentDate);
  const generateMonthData = (
    dayjsDate: dayjs.Dayjs
  ): generateMonthDataType => {
    //返回当前月份的第一天
    const currentMonthFirstDay = dayjsDate.startOf("month");

    // 返回当月的第一周第一天
    const currentMonthStartDay = currentMonthFirstDay.startOf("week");
    //上一个月
    const prevMonthFirstDay = currentMonthFirstDay.subtract(1, "month");
    const prevMonthStartDay = prevMonthFirstDay.startOf("week");
    //下一个月
    const nextMonthFirstDay = currentMonthFirstDay.add(1, "month");
    const nextMonthStartDay = nextMonthFirstDay.startOf("week");

    return {
      currentMonthFirstDay,
      generateMonthDateList: [
        new Array(42)
          .fill("")
          .map((_, index) => prevMonthStartDay.add(index, "day")),
        new Array(42)
          .fill("")
          .map((_, index) => currentMonthStartDay.add(index, "day")),
        new Array(42)
          .fill("")
          .map((_, index) => nextMonthStartDay.add(index, "day")),
      ],
    };
  };

  /**
   *
   * @param {*} dayjsDate dayjs对象
   */
  const generateWeekData = (dayjsDate: dayjs.Dayjs): generateWeekDataType => {
    const currenWeekStartDay = dayjsDate.startOf("week");
    const prevWeekStartDay = currenWeekStartDay.subtract(1, "week");
    const nextWeekStartDay = currenWeekStartDay.add(1, "week");
    return {
      currenWeekFirstDay: currenWeekStartDay,
      generateWeekDateList: [
        new Array(7) .fill("") .map((_, index) => prevWeekStartDay.add(index, "day")),
        new Array(7) .fill("") .map((_, index) => currenWeekStartDay.add(index, "day")),
        new Array(7) .fill("") .map((_, index) => nextWeekStartDay.add(index, "day")),
      ],
    };
  };
  const { currentMonthFirstDay, generateMonthDateList = [] } =
    generateMonthData(dayjsDate);
  const { currenWeekFirstDay, generateWeekDateList = [] } =
    generateWeekData(dayjsDate);

  const [monthFirstDay, setMonthFirstDay] =
    useState<dayjs.Dayjs>(currentMonthFirstDay);
  const [mountDateList, setMonthDateList] = useState<Array<dayjsType>>(
    generateMonthDateList
  ); // 月日历需要展示的日期 包括前一月 当月 下一月
  const [weekFirstDay, setWeekFirstDay] =
    useState<dayjs.Dayjs>(currenWeekFirstDay); // 周日历需要展示的日期  包括前一周 当周 下一周
  const [weekDateList, setWeekDateList] =
    useState<Array<dayjsType>>(generateWeekDateList);
  const [selectDate, setSelectDate] = useState<string>(current.currentDate);
  const [moveIndex, setMoveIndex] = useState<number>(0);
  const [touch, setTouch] = useState<touchType>({ x: 0, y: 0 }); //Y轴
  const [isWeekView, setIsWeekView] = useState<boolean>((defaultWeek) as boolean); //true/周日历 false/月日历
  const [weekInd, selectWeekInd] = useState<number>(0); //记录周日历选中的index

  const weekList: Array<weekType> = [ { id: 1, name: "一", }, { id: 2, name: "二", }, { id: 3, name: "三", }, { id: 4, name: "四", }, { id: 5, name: "五", }, { id: 6, name: "六", }, { id: 7, name: "日", }, ];

  const handleTouchStart = (e: any) => {
    current.isTouch = true;
    e.stopPropagation();
    const touches = e.touches[0];
    current.touchStartX = touches.clientX;
    current.touchStartY = touches.clientY;
  };

  const handleTouchMove = throttle((e: any) => {
    e.stopPropagation();
    const touches = e.touches[0];
    const moveX = touches.clientX - current.touchStartX;
    const moveY = touches.clientY - current.touchStartY;
    const calendarWidth = current.calendarRef.offsetWidth;
    if (Math.abs(moveX) > Math.abs(moveY)) {
      // 左右滑动
      setTouch({ x: moveX / calendarWidth, y: 0 });
    }
  }, 25);
  const handleTouchEnd = (
    e?: any,
    touchInfo?: { x: number; y: number },
    type?: "month" | "week"
  ) => {
    current.isTouch = false;
    e?.stopPropagation();
    const touchSource = touchInfo ?? touch;
    const touchX = Math.abs(touchSource.x);
    const touchY = Math.abs(touchSource.y);
    const newTranslateIndex =
      touchSource.x > 0 ? moveIndex + 1 : moveIndex - 1;
    const toggleType = type ?? (isWeekView ? "week" : "month");
    let toggleDate = selectDate;
    if (touchX > touchY && touchX > 0.15) {
      // 如果是周视图
      if (isWeekView) {
        const firstDayMap = {
          week: weekFirstDay,
          month: monthFirstDay,
        };
        const nextWeekFirstDay = firstDayMap[toggleType ?? "week"][
          touchSource.x > 0 ? "subtract" : "add"
        ](1, toggleType);
        const { currenWeekFirstDay = null, generateWeekDateList = [] } =
          generateWeekData(nextWeekFirstDay);
        updateWeekView(
          newTranslateIndex,
          currenWeekFirstDay,
          generateWeekDateList
        );

        if (toggleType === "week") {
          //周日历滚动默认选中
          const currentWeekDays = generateWeekDateList[1];
          const selectWeekDay = currentWeekDays[weekInd];
          const formSelectWeekDay = handleFormDate(
            selectWeekDay,
            "YYYY-MM-DD"
          );
          // 周模式，获取当月第一天
          const selectedDateFirstDay = dayjs(selectWeekDay).date(1);

          toggleDate = dayjs(formSelectWeekDay).format("YYYY-MM-DD");
          setMonthFirstDay(selectedDateFirstDay);
          setSelectDate(formSelectWeekDay);
        } else if (toggleType === "month") {
          //周日历滚动默认选中
          const formSelectWeekDay = handleFormDate(
            nextWeekFirstDay,
            "YYYY-MM-DD"
          );

          toggleDate = dayjs(formSelectWeekDay).format("YYYY-MM-DD");
          // 周模式，获取当月第一天
          setMonthFirstDay(nextWeekFirstDay);
          setSelectDate(formSelectWeekDay);
        }
      } else {
        // 如果是月视图
        if (toggleType === "month") {
          //月日历
          const nextMonthFirstDay = monthFirstDay[
            touchSource.x > 0 ? "subtract" : "add"
          ](1, "month");
          const { currentMonthFirstDay = null, generateMonthDateList = [] } =
            generateMonthData(nextMonthFirstDay);

          toggleDate = dayjs(currentMonthFirstDay).format("YYYY-MM-DD");
          updateMonthView(
            newTranslateIndex,
            currentMonthFirstDay,
            generateMonthDateList
          );
        }
      }
    }
    setTouch({ x: 0, y: 0 });
    onDateSelected(toggleDate, true);
  };

  /** 下一页 */
  const handleNext = (e, type) => {
    if (showCalendar) {
      handleTouchEnd(e, { x: -0.5, y: 0 }, type);
    } else {
      setSelectDate((date) => {
        let newDate = dayjs(date);
        if (type === 'month') {
          const currentMonth = dayjs(date).month();
          newDate = dayjs(date).month(currentMonth + 1).date(1);
        } else if (type === 'week') {
          const currentWeek = dayjs(date).week();
          newDate = dayjs(date).week(currentWeek + 1)
        }
        onToggleCalendar?.(type, "next", newDate);
        return newDate;
      });
    }
  };
  /** 上一页 */
  const handlePrev = (e, type) => {
    if (showCalendar) {
      handleTouchEnd(e, { x: 0.5, y: 0 }, type);
    } else {
      setSelectDate((date) => {
        let newDate = dayjs(date);
        if (type === 'month') {
          const currentMonth = dayjs(date).month();
          newDate = dayjs(date).month(currentMonth - 1).date(1);
        } else if (type === 'week') {
          const currentWeek = dayjs(date).week();
          newDate = dayjs(date).week(currentWeek - 1)
        }
        onToggleCalendar?.(type, "prev", newDate);
        return newDate;
      });
    }
  };
  //更新月日历视图
  const updateMonthView = (
    index: number,
    currentFirstDay: any,
    dateList: Array<dayjsType>
  ): void => {
    setMoveIndex(index);
    setMonthFirstDay(currentFirstDay);
    setMonthDateList(dateList);
  };

  //更新周日历视图
  const updateWeekView = (
    index: number,
    currentFirstDay: any,
    dateList: Array<dayjsType>
  ): void => {
    setMoveIndex(index);
    setWeekFirstDay(currentFirstDay);
    setWeekDateList(dateList);
  };

  const handleFormDate = (
    date: dayjs.Dayjs | string,
    exp: string
  ): string => {
    return dayjs(date).format(exp);
  };

  //日历选中逻辑
  const handleSelectDate = (
    formDate: string,
    isOtherMonthDay: boolean,
    index: number
  ) => {
    let selectM = handleFormDate(formDate, "YYYYMM");
    let currentM = handleFormDate(monthFirstDay, "YYYYMM");
    if (!isOtherMonthDay) {
      //在当月点击上一个月或者下一个月
      const { generateMonthDateList = [] } = generateMonthData(
        dayjs(formDate)
      );
      const newTranslateIndex =
        selectM < currentM ? moveIndex + 1 : moveIndex - 1;
      updateMonthView(
        newTranslateIndex,
        dayjs(formDate),
        generateMonthDateList
      );
    }

    if (isWeekView) {
      //周日历 记录选中的位置
      // selectWeekInd(index);
    }
    setSelectDate(formDate);
    //更新日历选中样式
    onDateSelected(formDate, true);
  };
  const today = dayjs().format('YYYY-MM-DD');
  //渲染选中样式
  const renderClassName = (formDate: string): string => {
    if (selectDate === formDate) return "selectDay";
    if (formDate === today) return "currentDay";
    const matchEvent = events.find((item) => dayjs(item.start).format('YYYY-MM-DD') === formDate);
    if (matchEvent) {
      if (matchEvent.bgColor) return matchEvent.bgColor;
    }
    return "";
  };

  //月日历/周日历切换
  const handleIsMonthView = () => {
    const dayjsDate = dayjs(selectDate);
    const { generateWeekDateList = [], generateMonthDateList = [] } = {
      ...generateMonthData(dayjsDate),
      ...generateWeekData(dayjsDate),
    };

    const flag = !isWeekView;
    if (flag) {
      //更新周日历
      setWeekFirstDay(dayjsDate);
      setWeekDateList(generateWeekDateList);
      handleSetWeekIndex(selectDate, generateWeekDateList);
    } else {
      //更新月日历
      setMonthFirstDay(dayjsDate);
      setMonthDateList(generateMonthDateList);
    }
    setIsWeekView(flag);
  };

  //设置周日历选中的位置
  const handleSetWeekIndex = (
    selectDate: string | dayjs.Dayjs,
    generateWeekDateList: Array<{ [key: string]: any }>
  ): void => {
    const currentWeekDateList = generateWeekDateList[1];
    let weekIndex = 0;
    currentWeekDateList.forEach((v: any, index: number) => {
      if (handleFormDate(v, "YYYY-MM-DD") === selectDate) weekIndex = index;
    });
    selectWeekInd(weekIndex);
  };
  // 当从面板切换年月
  const handleYearMonthChange = (val, valStr, stopPropagation?: boolean) => {
    // const nextFirstDay = valStr + "-01";
    // 如果是手动重置，则按指定的日期来初始化
    const nextFirstDay = stopPropagation ? dayjs(valStr).startOf('week').format('YYYY-MM-DD') : dayjs(valStr).startOf('M').format('YYYY-MM-DD');

    const parsedDay = dayjs(nextFirstDay);
    if (showCalendar && isWeekView) {
      setMonthFirstDay(parsedDay);
      if (isWeekView) {
        setSelectDate(nextFirstDay);

        const { currenWeekFirstDay = null, generateWeekDateList = [] } =
          generateWeekData(parsedDay);
        updateWeekView(0, currenWeekFirstDay, generateWeekDateList);
      }

      // 更新日期
      !stopPropagation && onDateSelected(nextFirstDay);
    } else if (!isWeekView && !showCalendar) {

      onSelectMonth?.(nextFirstDay);
    } else if (!isWeekView && showCalendar) {
      // 更新某月视图
      const { currentMonthFirstDay = null, generateMonthDateList = [] } =
        generateMonthData(dayjs(nextFirstDay));
      setMonthFirstDay(dayjs(nextFirstDay))
      // toggleDate = dayjs(currentMonthFirstDay).format("YYYY-MM-DD");
      updateMonthView(
        0,
        currentMonthFirstDay,
        generateMonthDateList
      );
    }
  };
  const handleGetTerm = (date) => {
    const Y = Number(dayjs(date).get('y'));
    const M = Number(dayjs(date).get('M')) + 1;
    const D = Number(dayjs(date).get('D'));
    const { term, festival, lDayZH } = lunarjs.getDateBySolar(Y, M, D) ?? {};

    return term || festival || lDayZH;
  }
  const renderDotClassName = (date) => {
    const parsedDay = dayjs(date).format('YYYY-MM-DD').valueOf();
    const dotColor = events.find((item) => {
      let isMatch = false;
      const startDay = dayjs(item.startTime).startOf('d').format('YYYY-MM-DD').valueOf();
      const endDay = dayjs(item.endTime).endOf('d').format('YYYY-MM-DD').valueOf();
      isMatch = parsedDay >= startDay && parsedDay <= endDay;

      return isMatch;
    })?.['color'] ?? '';
    return dotColor;
  };

  useEffect(() => {
    if (!isWeekView) {
      //月日历, 如果是当月则默认选中当天
      // const mOfToday = dayjs().get('M');
      // const currentMNum = dayjs(monthFirstDay).get('M');
      // const isSame = mOfToday === currentMNum;
      const currentM = dayjs(monthFirstDay).format("YYYY-MM-DD");
      setSelectDate(currentM);
      onDateSelected(currentM);
    }
  }, [monthFirstDay, isWeekView]);

  useEffect(() => {
    if (showCalendar) {
      const formatDate = dayjs(initDate).format('YYYY-MM-DD');
      handleSetWeekIndex(current.currentDate, weekDateList);
      setSelectDate(formatDate);
    }
  }, []);
  // useEffect(() => {
  //   console.log('debug-initDate??', initDate);

  //   if (initDate) {
  //     handleYearMonthChange('', dayjs(initDate).format('YYYY-MM'), true);
  //   }
  // }, [initDate]);
  const handleViewTypeChange = (val, mode) => {
    if (mode === 'month') {
      const newDate = dayjs(val).date(1).format('YYYY-MM-DD');
      setSelectDate(newDate);
      onPanelToggle?.(newDate, mode);
    }
  }
  const currentMonth = useMemo(() => {
    return dayjs(selectDate).format("YYYY年MM月");
  }, [selectDate]);
  const showWeekToggler = useCallback(() => {
    return ['timeGridDay', 'timeGridWeek'].includes(viewType) && isWeekView;
  }, [viewType, isWeekView]);

  useImperativeHandle(ref, () => ({
    handleYearMonthChange
  }));

  return (
    <div className={`schedule-view-wrap ${isMobile ? 'mobile' : ''} showFold`}>
      <div className="schedule-list-section">
        <div className="calendar-comp">
          <div className="calendar-header">
            <div className="icon" onClick={(e) => handlePrev(e, "month")}>
              <DoubleLeftOutlined style={{ fontSize: 18 }} />
            </div>
            {showWeekToggler() ? (
              <div className="icon" onClick={(e) => handlePrev(e, "week")}>
                <LeftOutlined style={{ fontSize: 18 }} />
              </div>
            ) : null}

            <div className="date-time">
              <div className="picker-box">
                <div className="picker">
                  <DatePicker
                    style={{ width: 240, cursor: 'pointer' }}
                    picker="month"
                    onChange={handleYearMonthChange}
                    onPanelChange={handleViewTypeChange}
                    value={moment(selectDate)}
                    inputReadOnly
                    locale={zhCN}
                    allowClear={false}
                  ></DatePicker>
                </div>
              </div>
              <div className="date-text">{currentMonth}</div>
            </div>
            {showWeekToggler() ? (
              <div className="icon" onClick={(e) => handleNext(e, "week")}>
                <RightOutlined style={{ fontSize: 18 }} />
              </div>
            ) : null}
            <div className="icon" onClick={(e) => handleNext(e, "month")}>
              <DoubleRightOutlined style={{ fontSize: 18 }} />
            </div>
          </div>

          {showCalendar ? (
            <>
              <div className="week-list">
                {weekList.map((item) => {
                  return (
                    <span className="week-item" key={item.id}>
                      {item.name}
                    </span>
                  );
                })}
              </div>
              <div
                className={`calendar-comp-wrap pullHeight ${isWeekView ? 'weekView' : 'monthView'}`}
                ref={(e: any) => (current.calendarRef = e)}
                onTouchStart={handleTouchStart}
                onTouchMove={handleTouchMove}
                onTouchEnd={handleTouchEnd}
              >
                <div
                  className="calendar-comp-section"
                  style={{
                    transform: `translateX(${-moveIndex * 100}%)`,
                  }}
                >
                  {(isWeekView ? weekDateList : mountDateList).map(
                    (item, index) => {
                      return (
                        <div
                          key={index}
                          className="calendar-list-day"
                          style={{
                            transform: `translateX(${(index - 1 + moveIndex + (current.isTouch ? touch.x : 0)) * 100}%)`,
                            transitionDuration: `${current.isTouch ? 0.1 : 0.3}s`,
                          }}
                        >
                          {item.map((date, ind) => {
                            const isOtherMonthDay = date.isSame(
                              monthFirstDay,
                              "month"
                            );
                            const formDate = handleFormDate(date, "YYYY-MM-DD");

                            return (
                              <div
                                key={ind}
                                onClick={() => {
                                  handleSelectDate(formDate, isOtherMonthDay, ind);
                                }}
                                className={`item ${isOtherMonthDay ? "current" : "other"}`}
                              >
                                <div className={`dayItem ${renderClassName(formDate)}`} >
                                  {date.format("DD")}
                                  <div className="lunar-date">
                                    {handleGetTerm(formDate)}
                                  </div>
                                  <div className={`event-dot ${renderDotClassName(date)}`} ></div>
                                </div>

                              </div>
                            );
                          })}
                        </div>
                      );
                    }
                  )}

                </div>
                {
                  <div className="calendar-fold" onClick={() => { handleIsMonthView() }} >
                    <div>
                      {alertText ? render?.('tpl', { type: 'tpl', tpl: alertText }) : null}
                    </div>
                    {isWeekView ? <DownOutlined /> : <UpOutlined />}
                  </div>
                }
              </div>
              {/* <p className="current-day">
              {handleFormDate(selectDate, "MM月DD日")}{" "}
              {`周${getWeekDate(selectDate)?.name}`}{" "}
              </p> */}
            </>
          ) : null}

        </div>
      </div>
    </div>
  );
  // };
  // return (
  //   <>
  //     <div className="schedule-view-wrap">
  //       <div className="schedule-list-section">
  //         {/* 日历组件 */}
  //         <CalendarComp />
  //       </div>
  //     </div>
  //   </>
  // );
};
export default forwardRef(ScheduleList);
