import React, { useState, useRef, useEffect, useCallback, createRef, RefObject } from 'react';
import { ReactSortable } from 'react-sortablejs';
import classames from 'classnames';
import { LeftOutlined, RightOutlined } from '@easyv/react-icons';

export interface DataSourceType {
  id: string;
  name: string;
  rank: number;
}

export interface SortableTabsProp {
  dataSource: DataSourceType[];
  selectKey?: string;
  onTabChange?: (key: string) => void;
  onDragChange?: (dragKey: string, rank: number, changeDataSource: DataSourceType[]) => void;
}

export default function SortableTabs({
  dataSource,
  selectKey,
  onTabChange,
  onDragChange,
}: SortableTabsProp) {
  const scrollRef = useRef<HTMLDivElement>(null);
  const [listRef, setListRef] = useState<RefObject<HTMLDivElement>[]>([]);
  const [innerDataSource, setInnerDataSource] = useState<DataSourceType[]>([]);
  const [, setAddScrollLen] = useState<number>(0);

  const handleScroll = useCallback(
    (addScrollLen: number = 0) => {
      if (!scrollRef.current) return;
      const selectindex = dataSource.findIndex((i) => i.id === selectKey);

      if (selectindex > -1) {
        const itemRef = listRef[selectindex];
        if (!itemRef?.current) return;

        const scrollRefRect = scrollRef.current.getBoundingClientRect();
        const itemRefRect = itemRef.current.getBoundingClientRect();

        scrollRef.current.scrollTo({
          left:
            itemRef.current.offsetLeft -
            scrollRef.current.offsetLeft -
            (scrollRefRect.width - itemRefRect.width) / 2 +
            addScrollLen,
          behavior: 'smooth',
        });
      } else {
        scrollRef.current.scrollTo({
          left: 0,
          behavior: 'smooth',
        });
      }
    },
    [dataSource, listRef, selectKey],
  );

  useEffect(() => {
    setAddScrollLen(0);
    handleScroll(0);
  }, [handleScroll]);

  useEffect(() => {
    setInnerDataSource(JSON.parse(JSON.stringify(dataSource)));
    setListRef(dataSource.map(() => createRef<HTMLDivElement>()));
  }, [dataSource]);

  useEffect(() => {
    for (let index = 0; index < innerDataSource.length; index++) {
      const item = innerDataSource[index];
      const { id: key } = item;
      if (key !== dataSource[index]?.id) {
        const oldIndex = dataSource.findIndex(({ id }) => id === key);

        const oldPrev = dataSource[oldIndex - 1];
        const newPrev = innerDataSource[index - 1];

        const oldNext = dataSource[oldIndex + 1];
        const newNext = innerDataSource[index + 1];

        if (oldPrev?.id !== newPrev?.id && oldNext?.id !== newNext?.id) {
          let newOrder;
          if (newPrev === undefined) {
            newOrder = dataSource[0].rank - 1;
          } else if (newNext === undefined) {
            newOrder = dataSource[dataSource.length - 1].rank + 1;
          } else {
            newOrder = dataSource[dataSource.length - 1].rank + 1;
          }

          onDragChange?.(key, newOrder, innerDataSource);
          return;
        }
      }
    }
  }, [innerDataSource, dataSource, onDragChange]);

  return (
    <div className="flex rounded-sm">
      <span
        className="px-2 cursor-pointer flex justify-center items-center hover:bg-bgColorHover"
        onClick={() =>
          setAddScrollLen((state) => {
            handleScroll(state - 100);
            return state - 100;
          })
        }>
        <LeftOutlined className="anticon text-xs" />
      </span>
      <div ref={scrollRef} className="flex-auto overflow-y-auto">
        <ReactSortable list={innerDataSource} setList={setInnerDataSource} className="flex">
          {innerDataSource.map((item, index) => (
            <div
              key={item.id}
              ref={listRef[index]}
              className={classames(
                'h-6 px-4 cursor-pointer bg-bgColorSecondary whitespace-pre hover:bg-bgColorHover flex justify-center items-center',
                item.id === selectKey ? 'text-primary border-b border-b-1 border-b-primary ' : '',
              )}
              onClick={() => onTabChange?.(item.id)}>
              {item.name}
            </div>
          ))}
        </ReactSortable>
      </div>
      <span
        className="px-2 cursor-pointer flex justify-center items-center hover:bg-bgColorHover"
        onClick={() =>
          setAddScrollLen((state) => {
            handleScroll(state + 100);
            return state + 100;
          })
        }>
        <RightOutlined className="anticon text-xs" />
      </span>
    </div>
  );
}
