import PropTypes from 'prop-types';

import { Input, Layout, Spin, Tree, ConfigProvider } from 'antd';
// import { SearchOutlined } from '@ant-design/icons';
import React, { useCallback, useEffect, useMemo, useRef, useState, useContext } from 'react';
import PandaEmpty from '@wisdom-components/empty';
import classNames from 'classnames';
import _ from 'lodash';
import { getEquipmentInfo } from './apis';
import './index.less';
import classnames from 'classnames';

// 生成树的数据格式
const treeDataGenerator = (origin, currentType, ref) => {
  if (!origin || !Array.isArray(origin)) return [];
  return origin.map((item) => {
    const { shortName, deviceName, code, deviceType, children: originChildren } = item;
    const title = shortName || deviceName;
    const children = treeDataGenerator(originChildren, currentType);
    const _width = (ref?.current?.getBoundingClientRect().width || 180) - 24 - 8 - 28; // 24为tree的左侧空白,8为右侧滚动条位置,28是左侧复选框和边距等
    return {
      ...item,
      title: (
        <div
          title={title}
          style={{
            // width: _width,
            overflow: 'hidden',
            whiteSpace: 'nowrap',
            textOverflow: 'ellipsis',
          }}
        >
          {title}
        </div>
      ),
      key: code,
      children,
      disabled: currentType ? !(currentType === deviceType) : false,
    };
  });
};

// 树结构展开平铺
const flattenTreeData = (treeData) => {
  if (!treeData || !Array.isArray(treeData)) return {};
  const result = {};
  const deep = (treeData, target) => {
    treeData &&
      treeData.forEach((item) => {
        target[item.key] = item;
        if (item.children && item.children.length > 0) {
          deep(item.children, target);
        }
      });
  };
  deep(treeData, result);
  return result;
};

// 图层树处理
const convertToTree = (data, name) => {
  let obj = {};
  let newData = [];
  data.forEach((item, index) => {
    const state = item[name] || '未知';
    if (obj[state]) {
      obj[state] = [...obj[state], item];
    } else {
      obj[state] = [item];
    }
  });
  for (let k in obj) {
    newData.push({
      title: k,
      children: [...obj[k]],
      key: k,
      selectable: false,
      disableCheckbox: true,
      checkable: false,
    });
    expandedKeys.push(k);
  }
  return newData;
};

let dataList = [];
let expandedKeys = [];

const DeviceTree = (props) => {
  const {
    deviceTypes = '二供泵房,二供机组',
    userAccessor = false,
    getChild = true,
    sortFields = '',
    direction = '',
    classField = '',
    customerName = '',
  } = props;

  const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
  const prefixCls = getPrefixCls('ec-device-tree-group');

  const cusProps = _.pick(props, ['onSelect', 'onCheck', 'selectable', 'checkable']);
  const { onSelect, onCheck, keepChecked, singleType = false, selectable, checkable } = props;

  const [data, setData] = useState([]);
  const [{ pageIndex, pageSize }, setPagination] = useState({
    pageIndex: 1,
    pageSize: props.pageSize || 500,
  });
  const [searchs, setSearchs] = useState('');
  const [loading, setLoading] = useState(true);
  const [hasMore, setHasMore] = useState(true);
  const ref = useRef();

  const dataRef = useRef({
    currentType: '',
    preCheckedData: [],
    preCheckedKeys: [],
    preSelectedData: [],
    flatData: {},
  });
  const { currentType, flatData } = dataRef.current;
  const [checkedKeys, setCheckedKeys] = useState([]);
  const [selectedKeys, setSelectedKeys] = useState([]);
  const [first, setFirst] = useState(true);

  const requestQuery = useMemo(() => {
    return {
      deviceTypes,
      pageIndex,
      pageSize,
      queryInfo: searchs,
      getChild,
      userID: userAccessor ? window?.globalConfig?.userInfo?.OID : void 0,
      userAccess: userAccessor,
      sortFields,
      classField,
      direction,
      customerName,
    };
  }, [
    customerName,
    deviceTypes,
    direction,
    getChild,
    pageIndex,
    pageSize,
    searchs,
    sortFields,
    classField,
  ]);

  useEffect(() => {
    setLoading(true);
    getEquipmentInfo(requestQuery)
      .then((res) => {
        setLoading(false);
        const { list, pageIndex, totalCount } = res.data || {};
        const newData = pageIndex === 1 ? list : [...dataList, ...list]; // 非第一页时合并

        // 是否需要默认选中
        if (pageIndex === 1 && (!keepChecked || (keepChecked && !checkedKeys.length))) {
          setCheckedKeys(newData.length > 0 ? [newData[0].code] : []);
          onCheck?.(newData.length > 0 ? [newData[0]] : []);

          // 仅单选时使用select相关数据
          !checkable && onSelect?.(newData.length > 0 ? [newData[0]] : []);
          !checkable && setSelectedKeys(newData.length > 0 ? [newData[0].code] : []);

          singleType && (dataRef.current.currentType = newData[0].deviceType);
        }
        setData(() => {
          dataList = [...newData];
          return newData;
        });
        props.setDeviceList(newData);
        props.setSearchStr(searchs);
        setHasMore(newData.length < totalCount);
      })
      .catch((err) => {
        setLoading(false);
      });
  }, [requestQuery]);

  const onScroll = useCallback(() => {
    if (loading || !hasMore) return;
    const { clientHeight, scrollHeight, scrollTop } = ref.current;
    if (clientHeight + scrollTop + 10 >= scrollHeight) {
      // 加载更多
      setPagination({
        pageSize,
        pageIndex: pageIndex + 1,
      });
    }
  }, [loading, pageIndex, pageSize, hasMore]);

  const onSearch = useCallback(
    (value) => {
      setSearchs(value);
      setPagination({
        pageIndex: 1,
        pageSize,
      });
    },
    [pageSize],
  );

  useEffect(() => {
    ref.current?.addEventListener('scroll', onScroll, true);
    return () => {
      // eslint-disable-next-line react-hooks/exhaustive-deps
      ref.current?.removeEventListener('scroll', onScroll, true);
    };
  }, [onScroll]);

  const treeData = useMemo(() => {
    const treeData = treeDataGenerator(data, singleType && currentType, ref);
    const flatData = flattenTreeData(treeData);
    dataRef.current.flatData = Object.assign(dataRef.current.flatData || {}, flatData);
    return convertToTree(treeData, requestQuery.classField ? 'deviceClass' : 'deviceType');
  }, [data, singleType, currentType]);

  const handleCheck = (keys, info) => {
    // keys中会保留多余的key
    const { checked } = keys;
    setCheckedKeys(checked);
    const data = checked.map((key) => flatData[key]);
    onCheck?.(data);
    singleType && data.length === 0 && (dataRef.current.currentType = '');
    singleType && data.length === 1 && (dataRef.current.currentType = data[0].deviceType);
  };

  const handleSelect = (keys, info) => {
    if (checkable) {
      setCheckedKeys(keys);
      const data = keys.map((key) => flatData[key]);
      onCheck?.(data);
      singleType && data.length === 0 && (dataRef.current.currentType = '');
      singleType && data.length === 1 && (dataRef.current.currentType = data[0].deviceType);
    } else {
      setSelectedKeys(keys);
      const data = keys.map((key) => flatData[key]);
      onSelect?.(data);
    }
  };

  return (
    <div className={classNames(prefixCls, 'wkt-scroll-light')}>
      <Input.Search placeholder="搜索设备名称" onSearch={onSearch} allowClear />
      <div className={classnames(`${prefixCls}-tree-wrap`, 'wkt-scroll-light-plus')} ref={ref}>
        <Spin spinning={loading}>
          {data && data.length ? (
            <Tree
              checkStrictly
              checkedKeys={checkedKeys}
              selectedKeys={selectedKeys}
              autoExpandParent
              treeData={treeData}
              defaultExpandParent
              defaultExpandedKeys={expandedKeys}
              {...cusProps}
              onCheck={handleCheck}
              onSelect={handleSelect}
            />
          ) : (
            <PandaEmpty />
          )}
        </Spin>
      </div>
    </div>
  );
};

DeviceTree.defaultProps = {
  deviceTypes: '二供泵房',
  userAccessor: false,
  getChild: false,
  sortFields: '',
  direction: '',
  customerName: '',
  classField: '',
  selectable: false,
  checkable: false,
  keepChecked: false,
  onSelect: () => {},
  onCheck: () => {},
  setDeviceList: () => {},
  setSearchStr: () => {},
};

DeviceTree.propTypes = {
  deviceTypes: PropTypes.string,
  userAccessor: PropTypes.bool,
  getChild: PropTypes.bool,
  sortFields: PropTypes.string,
  direction: PropTypes.string,
  customerName: PropTypes.string,
  classField: PropTypes.string,
  selectable: PropTypes.bool,
  checkable: PropTypes.bool,
  keepChecked: PropTypes.bool,
  onSelect: PropTypes.func,
  onCheck: PropTypes.func,
  setDeviceList: PropTypes.func,
  setSearchStr: PropTypes.func,
};

export default DeviceTree;