/* eslint-disable @typescript-eslint/ban-types */
import React, { useEffect, useRef, useState } from 'react';
import Gantt, { EnrichedTask } from 'frappe-gantt';
import cn from 'classnames';

import { useTheme } from '../Theme';
import { StyledPopover } from '../Popover/styled-component';
import Task from './task';
import './styles.scss';
import { GanttTask, GanttChartProps } from './types.d';

export const GanttChart = <T extends object>(props: GanttChartProps<T>): React.ReactElement => {
  const {
    popover,
    dateFormat,
    language = 'en',
    marginBottom = 0,
    onClick = () => {},
    onDateChange = () => {},
    onProgressChange = () => {},
    onTasksChange = () => {},
    onViewChange = () => {},
    tasks,
    viewMode,
  } = props;
  const theme = useTheme();
  const svg = useRef<SVGSVGElement>(null);
  const container = useRef<HTMLDivElement>(null);
  const gantt = useRef<Gantt>();

  const [data, setData] = useState<GanttTask<T>[]>([]);
  const [anchorEl, setAnchorEl] = useState<SVGGElement | null>(null);
  const [currentTask, setCurrentTask] = useState<GanttTask<T>>();

  useEffect(() => {
    setData(tasks.map((t) => new Task(t)));
  }, [tasks]);

  useEffect(() => {
    if (gantt.current) {
      gantt.current.refresh(tasks);
      gantt.current.change_view_mode(viewMode);
    }
  }, [viewMode, tasks]);

  useEffect(() => {
    const options: Gantt.Options = {
      on_click: handleClick,
      on_view_change: onViewChange,
      on_progress_change: (task, progress) => {
        onProgressChange(task, progress);
        onTasksChange(data);
      },
      on_date_change: (task, start, end) => {
        onDateChange(task as unknown as GanttTask<T>, start, end);
        onTasksChange(data);
      },
      language,
      date_format: dateFormat,
      custom_popup_html: '',
      margin_bottom: marginBottom,
      disable_popup: true,
    };

    gantt.current = new Gantt(svg.current as SVGElement, tasks, options);

    if (gantt.current?.change_view_mode) {
      gantt.current.change_view_mode(viewMode);
    }

    const midOfSvg = (svg.current?.clientWidth ?? 1) * 0.5;
    if (container.current?.scrollLeft) container.current.scrollLeft = midOfSvg;
  }, []);

  const className = cn({
    'gantt-chart-container': true,
    [theme.type]: true,
  });

  const handleClick = (task: EnrichedTask, event: PointerEvent) => {
    event.stopPropagation();
    if (popover) setAnchorEl(event.currentTarget as SVGGElement);
    setCurrentTask(task as unknown as GanttTask<T>);
    onClick(task, event);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  return (
    <>
      <div ref={container} className={className}>
        <svg ref={svg} xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" />
      </div>
      <StyledPopover
        anchorEl={anchorEl}
        open={Boolean(anchorEl)}
        onClose={handleClose}
        className={popover?.className}
        $theme={theme}
        style={popover?.style}
        anchorOrigin={{
          vertical: 'bottom',
          horizontal: 'center',
          ...(popover?.anchorOrigin ?? {}),
        }}
        transformOrigin={{
          vertical: 'top',
          horizontal: 'center',
          ...(popover?.transformOrigin ?? {}),
        }}
      >
        {popover?.content(currentTask)}
      </StyledPopover>
    </>
  );
};
