import React, { useState, useEffect } from 'react';
import { Tree } from 'antd';
import {YIcon} from '@/icon';
// import { CaretDownOutlined } from '@ant-design/icons';
import { TreeProps } from 'antd/lib/tree';
import {
  YGoodsCategoriesProps,
  GoodsCategoriesTreeNodeProps,
} from './goodsCategories.interface';
import { markReturnDataStructure } from './goodsCategories.utils';
import {
  DEF_ALL_TYPE_NUM,
  DEF_ALL_TYPE_TEXT,
  DEF_PARENTNO,
} from './goodsCategories.config';
import { useModel } from './useModel';

// 类目缓存数组
const categoriesDataCache: any = {};

export const GoodsCategoriesTree: React.FC<YGoodsCategoriesProps<any>> = (
  props,
) => {
  const { config, onChange, originalProps } = props;
  const { getCategoryList } = useModel();
  const parentNo = config.parentNo ? config.parentNo : DEF_PARENTNO;
  const [treeItemsList, setTreeItemsList] = useState([]);

  /* update Tree Data */
  const updateTreeData = (
    list: GoodsCategoriesTreeNodeProps[],
    key: React.Key,
    children: GoodsCategoriesTreeNodeProps[],
  ): GoodsCategoriesTreeNodeProps[] => {
    return list.map((node) => {
      if (node.key === key) {
        return {
          ...node,
          children,
        };
      } else if (node.children) {
        return {
          ...node,
          children: updateTreeData(node.children, key, children),
        };
      }
      return node;
    });
  };

  /* dynamic load Category data */
  const loadCategoryData: any = (item: { key: string }, children: any) => {
    let curKey = item.key;
    return new Promise((resolve) => {
      if (children) {
        resolve();
        return;
      }
      getCategoryData(curKey, (resData: any) => {
        if (resData) {
          setTreeItemsList(
            (origin): never[] =>
              updateTreeData(origin, curKey, resData) as never[],
          );
        }
        resolve();
      });
    });
  };

  /* get Category List Data */
  const getCategoryData = async (
    parentNo: string,
    callback: { (data: any): void; (arg0: any): any },
  ) => {
    let res: any = await getCategoryList({
      parentNo: parentNo,
    });
    let tRes: GoodsCategoriesTreeNodeProps[] = [];
    res.map(
      (item: {
        categoryName: any;
        categoryNo: any;
        hasChild: any;
        categoryNoPath: any;
      }) => {
        let tData = {
          title: item.categoryName,
          key: item.categoryNo,
          isLeaf: item.hasChild ? false : true,
          categoryNoPath: item.categoryNoPath,
          orgData: JSON.stringify(item),
        };
        categoriesDataCache[item.categoryNo] = tData;
        tRes.push(tData);
      },
    );

    /* 添加“全部类目” */
    if (parentNo === '0' && config.isShowAll) {
      const allCats = {
        title: config.selectAllText ? config.selectAllText : DEF_ALL_TYPE_TEXT,
        key: DEF_ALL_TYPE_NUM,
        categoryNoPath: '',
        categoryName: config.selectAllText
          ? config.selectAllText
          : DEF_ALL_TYPE_TEXT,
        level: 1,
        isLeaf: true,
      };
      tRes.unshift({ ...allCats, orgData: JSON.stringify(allCats) });
    }
    callback && callback(tRes as []);
  };

  /* Actions */
  /* selected Item Callback */
  const onSelectedItem = (selectedKeys: any, info: any) => {
    let retData: any = null;
    // multiple
    if (config.multiple) {
      retData = [];
      selectedKeys.map((item: string | number) => {
        retData.push(
          markReturnDataStructure(
            JSON.parse(categoriesDataCache[item].orgData),
          ),
        );
      });
    } else {
      retData = markReturnDataStructure(JSON.parse(info.node.orgData));
    }
    onChange(retData);
  };

  useEffect(() => {
    getCategoryData(parentNo, (data: React.SetStateAction<never[]>) => {
      setTreeItemsList(data);
    });
  }, []);

  return (
    <>
      <Tree
        {...(originalProps as TreeProps)}
        switcherIcon={<YIcon name="CaretDownOutlined" />}
        showLine={{ showLeafIcon: false }}
        showIcon={false}
        loadData={loadCategoryData}
        onSelect={onSelectedItem}
        treeData={treeItemsList}
        virtual={true}
        multiple={config.multiple}
      />
    </>
  );
};
