import React, { FC, useEffect, useMemo, useState } from 'react';
import { observer } from 'mobx-react-lite';
import moment from 'moment';

import { Alert, Button, Checkbox, Collapse, Input, notification } from 'antd';
import { CheckboxChangeEvent } from 'antd/es/checkbox';

import styles from '../Schedule.module.scss';

import StudyRoom from './StudyRoom';
import CalendarDate from './CalendarDate';
import Patient from './Patient';
import Services from './Services';
import { LoadingStatus } from '../../../store/types';
import useStore from '../../../hooks/useStore';
import { SearchData } from '../types';
import { dateFormat } from '../consts';
import ScheduleTable from './ScheduleTable';
import { IScheduleItem } from '../../../store/schedule';
import { timeToDate } from '../../../utils/commonHelpers';
import useScheduleTable from '../../../hooks/useScheduleTable';

const { Panel } = Collapse;

interface CreateNewOrderProps {
  onCreated: () => void;
}

const CreateNewOrder: FC<CreateNewOrderProps> = ({ onCreated }) => {
  const { scheduleStore } = useStore();

  const [searchData, setSearchData] = useState<SearchData>({
    studyRoomUUID: '',
    date: moment().format(dateFormat),
    time: '',
    notes: '',
    autoChangeDuration: false,
  });
  const [error, setError] = useState('');
  const {
    scheduleItems,
    loading: scheduleItemsLoading,
    setIsPoll,
  } = useScheduleTable(searchData.studyRoomUUID, searchData.date);

  useEffect(() => {
    if (scheduleStore.orderLoadingStatus === LoadingStatus.SUCCESS) {
      notification.success({
        message: 'Запис додано',
      });
      scheduleStore.setOrderLoadingStatus(LoadingStatus.NEVER);
      onCreated();
      setIsPoll(true);
    } else if (scheduleStore.orderLoadingStatus === LoadingStatus.ERROR) {
      notification.error({
        message: scheduleStore.orderError || 'Виникла помилка',
      });
      setSearchData((prev) => ({ ...prev, time: '' }));
      scheduleStore.setOrderLoadingStatus(LoadingStatus.NEVER);
      setIsPoll(true);
    }
  }, [scheduleStore.orderLoadingStatus, scheduleStore.studyRooms]);

  const servicesDuration = useMemo(() => {
    return (
      searchData.services?.reduce(
        (sum, service) => sum + service.duration,
        0
      ) || 0
    );
  }, [searchData.services]);

  useEffect(() => {
    const start = timeToDate(searchData.time);
    const end = moment(timeToDate(searchData.time))
      .add(servicesDuration, 'minutes')
      .toDate();

    if (
      scheduleItems.some(
        (item) => item.status && item.time === searchData.time
      ) ||
      (!searchData.autoChangeDuration &&
        scheduleItems.some(
          (item) =>
            timeToDate(item.time) > start &&
            timeToDate(item.time) < end &&
            item.status
        ))
    ) {
      durationErrorNotification();
      setSearchData((prev) => ({
        ...prev,
        time: '',
      }));
    }
  }, [
    servicesDuration,
    searchData.time,
    searchData.autoChangeDuration,
    scheduleItems,
  ]);

  const durationErrorNotification = () => {
    notification.error({
      message:
        'Вільного інтервалу часу між обстеженнями недостатньо. Обереіть інший час або скористайтеся прапорцем автоматичного зменшення тривалості обраних послуг',
    });
  };

  const handleAutoDurationCheck = (e: CheckboxChangeEvent) => {
    setSearchData((prev) => ({
      ...prev,
      autoChangeDuration: e.target.checked,
    }));
  };

  const handleTimeChange = (scheduleItem: IScheduleItem) => {
    if (!scheduleItem.status) {
      if (servicesDuration) {
        const start = timeToDate(scheduleItem.time);
        const end = moment(timeToDate(scheduleItem.time))
          .add(servicesDuration, 'minutes')
          .toDate();

        if (
          !searchData.autoChangeDuration &&
          scheduleItems.some(
            (item) =>
              timeToDate(item.time) > start &&
              timeToDate(item.time) < end &&
              item.status
          )
        ) {
          durationErrorNotification();
          setSearchData((prev) => ({
            ...prev,
            time: '',
          }));
          return;
        }
      }
      setIsPoll(false);
      setSearchData((prev) => ({
        ...prev,
        time: scheduleItem.time,
      }));
    }
  };

  const handleStudyRoomChange = (studyRoomUUID: string) =>
    setSearchData((prev) => {
      const newData = { ...prev, time: '', studyRoomUUID };
      delete newData.services;
      return newData;
    });

  const handleCreate = () => {
    (async () => {
      if (!searchData.studyRoomUUID) {
        setError('Кабінет не обраний');
      } else if (!searchData.date) {
        setError('Дата не обрана');
      } else if (!searchData.time) {
        setError('Час не обрано');
      } else {
        setError('');
        await scheduleStore.order(searchData);
      }
    })();
  };

  const isTimeRowActive = (scheduleItem: IScheduleItem) => {
    if (searchData.autoChangeDuration || !servicesDuration) {
      return scheduleItem.time === searchData.time;
    }
    return (
      timeToDate(scheduleItem.time) >= timeToDate(searchData.time) &&
      moment(timeToDate(searchData.time))
        .add(servicesDuration, 'minutes')
        .toDate() > timeToDate(scheduleItem.time)
    );
  };

  return (
    <div>
      <Collapse
        defaultActiveKey={[
          'patient',
          'time',
          'services',
          'notes',
          'studyRoom',
          'date',
        ]}
      >
        <Panel header="Обрати пацієнта" key="patient">
          <Patient searchData={searchData} setSearchData={setSearchData} />
        </Panel>
        <Panel header="Дата" key="date">
          <CalendarDate
            setDate={(date) => setSearchData((prev) => ({ ...prev, date }))}
          />
        </Panel>
        <Panel header="Кабінет" key="studyRoom">
          <StudyRoom setStudyRoom={handleStudyRoomChange} />
        </Panel>
        <Panel header="Обрати обстеження" key="services">
          <Services searchData={searchData} setSearchData={setSearchData} />
        </Panel>
        <Panel header="Обрати час" key="time">
          <Checkbox
            style={{ marginBottom: 34 }}
            onChange={handleAutoDurationCheck}
          >
            Автоматично зменшити тривалість
          </Checkbox>
          <ScheduleTable
            scheduleItems={scheduleItems}
            loading={scheduleItemsLoading}
            onRowClick={handleTimeChange}
            rowClassName={(row) =>
              isTimeRowActive(row) ? styles.chosenRow : ''
            }
          />
        </Panel>
        <Panel header="Примітка" key="notes">
          <Input
            placeholder="Примітка"
            onBlur={(e) =>
              setSearchData((prev) => ({ ...prev, notes: e.target.value }))
            }
          />
        </Panel>
      </Collapse>
      {!!error && (
        <Alert className={styles.errorMessage} message={error} type="error" />
      )}
      <Button
        style={{ margin: '20px 0' }}
        type="primary"
        loading={scheduleStore.orderLoadingStatus === LoadingStatus.LOADING}
        onClick={handleCreate}
      >
        Створити запис
      </Button>
    </div>
  );
};

export default observer(CreateNewOrder);
