/** @jsxRuntime classic */
/** @jsx jsx */

import { FC, useEffect, useMemo, useState } from 'react';
import { useTheme, jsx } from '@emotion/react';
import dayjs from 'dayjs';
import isoWeek from 'dayjs/plugin/isoWeek';
import { Droppable } from '../Droppable';
import { IWeekToDropProps, ISlot, ECalendarView } from '../../types';
import { useMiddlewareContext } from '../../hooks/useMiddlewareContext';
import {
  moreItemsButton,
  moreModal,
  spaceWidth,
  weekDayContainer,
  weekDayEventContainer,
  weekdayHeight,
  weekDayToDropContainer,
  weekDayToDropHorizontalContainer,
} from '../styles';
import { WeeklyDraggable } from './WeeklyDraggable';
import { BnClose } from '../../../icons/BnClose';
import { calculateModalPosition } from '../../utils';

dayjs.extend(isoWeek);

export const WeekToDrop: FC<IWeekToDropProps> = ({ id, EventComponent }) => {
  const colors = useTheme();
  const { options, eventsToSpaces } = useMiddlewareContext();
  const { view = ECalendarView.VERTICAL, date, isSundayFirstDay } =
    options || {};
  const dayShift = isSundayFirstDay ? 1 : 0;
  const horizontal = view === ECalendarView.HORIZONTAL;
  const today = dayjs.utc(date);

  const dates = useMemo(() => {
    let result = [] as dayjs.Dayjs[];
    for (let i = 1; i < 8; i++) {
      result.push(today.isoWeekday(i - dayShift).utc());
    }
    return result;
  }, [date, dayShift]);

  // Grouping events by date
  const weekDaysWithEvents = useMemo(() => {
    let result = [] as { date: dayjs.Dayjs; events: ISlot[] }[];

    dates.forEach((date) =>
      result.push({
        date,
        events:
          eventsToSpaces[Number(id)]
            ?.filter((event: ISlot) =>
              date.isSame(dayjs.utc(event.startDate), 'date')
            )
            .sort(
              (a: ISlot, b: ISlot) =>
                dayjs.utc(a.startDate).toDate().getTime() -
                dayjs.utc(b.startDate).toDate().getTime()
            ) || [],
      })
    );

    return result;
  }, [dates, eventsToSpaces, id]);

  const [modals, setModals] = useState<boolean[]>([]);

  useEffect(() => {
    setModals(Array(dates.length).fill(false));
  }, [dates]);

  const handleToggleModal = (index: number) => {
    let newModals = modals.slice();
    newModals[index] = !newModals[index];
    setModals(newModals);
  };

  let maxVisibleSlotsPerDay = 1;
  const todayContainer = document.getElementById(`week_container_${id}`);
  if (todayContainer) {
    const height = todayContainer.clientHeight - 20;
    maxVisibleSlotsPerDay = Math.floor(height / 20) + 1;
  }

  return (
    <div
      css={
        horizontal
          ? weekDayToDropHorizontalContainer(colors)
          : weekDayToDropContainer(colors)
      }
    >
      {weekDaysWithEvents.map((weekDay, index) => {
        const droppableId = `${id}_${weekDay.date.toISOString()}`;

        const withModal = weekDay.events.length > maxVisibleSlotsPerDay;
        const items = withModal
          ? weekDay.events.slice(0, maxVisibleSlotsPerDay - 1)
          : weekDay.events;

        const element = document.querySelector(
          `#draggable-${weekDay.events[0]?.id}`
        );
        const box = element?.parentElement?.parentElement;
        const boxW = box?.parentElement?.parentElement;
        const container = box?.parentElement;
        const containerW = container?.parentElement?.parentElement;
        const modalPosition = horizontal
          ? calculateModalPosition(boxW, containerW, box, container)
          : calculateModalPosition(box, container, boxW, containerW);

        return (
          <Droppable
            weekly
            maxWidth={
              horizontal ? `max(100% / 7, ${spaceWidth - 1}px)` : undefined
            }
            height={
              !horizontal ? `max(100% / 7, ${weekdayHeight}px)` : undefined
            }
            dragging={false}
            id={droppableId}
            key={droppableId}
          >
            <div
              id={index === 0 ? `week_container_${id}` : undefined}
              css={weekDayContainer(colors, horizontal)}
            >
              {items.map((event) => (
                <WeeklyDraggable
                  parentId={droppableId}
                  state={event}
                  key={event.id}
                  id={event.id}
                >
                  <div css={weekDayEventContainer} key={event.id}>
                    <EventComponent event={event} />
                  </div>
                </WeeklyDraggable>
              ))}
              {withModal && (
                <button
                  css={moreItemsButton(colors, true)}
                  onClick={() => handleToggleModal(index)}
                >
                  <div>
                    +{weekDay.events.length - (maxVisibleSlotsPerDay - 1)}
                  </div>
                  <div>{'more'}</div>
                </button>
              )}
              {withModal && modals[index] && (
                <div css={moreModal(colors, modalPosition)}>
                  <div className="more-modal-header">
                    <div onClick={() => handleToggleModal(index)}>
                      <BnClose />
                    </div>
                  </div>
                  <div className="events-list">
                    {weekDay.events.map((event) => (
                      <div key={event.id} css={{ margin: 2, height: '50px' }}>
                        <EventComponent event={event} />
                      </div>
                    ))}
                  </div>
                </div>
              )}
            </div>
          </Droppable>
        );
      })}
    </div>
  );
};
