import React, { useCallback, useState, useEffect, useContext } from 'react';
import { connect } from 'react-redux';
import { Switch, Button } from '@easyv/antd';
import AceEditor from '@easyv/react-ace';
import { SortableContainer } from 'react-sortable-hoc';
import FilterItem from './Item';
import FilterAdd from './Add';
import {
  updateComponentDataConfig,
  removeComponentFilter,
  addComponentFilter,
  triggerComponentFilter,
  sortComponentFilter,
} from 'models/component';
import { getFilterScreenId } from '@/models/create-app';
import {isAppPage} from 'utils/utils'
import { updateContainerFilter } from 'models/data-container';
import { updateFilter, addFilter } from 'models/filter';
import { filterData } from 'utils/convert';
import styles from '../../RightZoneBar/index.less';
import { getFiltersWithUsedComponents } from 'utils/filter';
import { getTopScreenId } from 'utils/screen';
import { Drawer, Select } from '@easyv/react-gui';
import message from 'components/message';
import { DataContext } from '../../RightZoneBar/DataBox/Context/index';
const Option = Select.Option;
import PreviewContent from './PreviewContent';
import { CloseOutlined } from '@easyv/react-icons';

const MySortableContainer = SortableContainer(({ children }) => {
  return (
    <ul style={{ background: '#181B24', padding: '18px 16px', overflow: 'auto' }}>{children}</ul>
  );
});

const Title = ({ onClose }) => (
  <div className={styles.title}>
    <span>数据响应结果</span>
    <CloseOutlined
      onClick={() => {
        onClose?.();
      }}
      className={styles.icon}
    />
  </div>
);

function Filter(props: {
  id: number;
  zIndex: number;
  visible: boolean;
  filters: any;
  useFilter: boolean;
  childrenDrawer?: React.ReactNode;
  usedFilters: any;
  originData: any;
  onClose: () => any;
  createCode?: boolean | number; //是否自动新建功能 true 自动创建，如果是number就是打开指定类目过滤器
  dispatch: any;
}) {
  const {
    id,
    visible,
    zIndex,
    filters = [],
    useFilter,
    usedFilters = [],
    childrenDrawer,
    originData = [],
    onClose,
    dispatch,
    createCode,
  } = props;
  const [adding, setAdding] = useState(false);
  const topScreenId = getTopScreenId();
  const [previewContent, setPreviewContent] = useState({});
  const { editItem, useContainer } = useContext(DataContext);

  const isAppEdit = isAppPage();
    const leaveFilterOptions = filters
    .filter((d) => !usedFilters.find((o) => o.id === d.id))
    .filter((d) => d && d.screenId === (isAppEdit ? getFilterScreenId() : topScreenId));

  useEffect(() => {
    if (visible) {
      // 首先判断本地是否存在当前组件当前过滤器list未保存的代码，若存在，->
      // 不允许新建 （之前业务规则不允许存在未保存过滤器的前提下去创建新的过滤器）
      const usedFiltersLocal = usedFilters.filter((e) => {
        return window.sessionStorage.getItem(`${id}-${e.id}`);
      });
      const isAddLocal = window.sessionStorage.getItem(`${id}`);
      if (isAddLocal) {
        // 如果本地存在新增过滤器代码。
        setAdding(true);
      } else if (!usedFiltersLocal || !usedFiltersLocal.length) {
        // drawer 打开有个过程，动画结束后，再自动新建
        createCode === true && setAdding(true);
      } else {
        setAdding(false);
      }
    } else {
      setPreviewContent({});
    }
  }, [visible]);

  const handleDelete = useCallback(
    (filterId) => {
      if (useContainer) {
        dispatch(
          updateContainerFilter({
            containerId: editItem.data?.id,
            id,
            filterId,
            type: 'delete',
          }),
        );
      } else {
        dispatch(removeComponentFilter({ id, filterId }));
      }
      window.sessionStorage.removeItem(`${id}-${filterId}`);
    },
    [dispatch, id, editItem, useContainer],
  );

  const handleUpdate = useCallback(
    async (value) => {
      const result = await dispatch(updateFilter(value));
      return result;
    },
    [dispatch],
  );

  const handleRemove = useCallback(() => {
    window.sessionStorage.removeItem(id.toString());
    setAdding(false);
  }, []);

  const handleAdd = useCallback(
    async (value) => {
      const result = await dispatch(addFilter(value));
      if (result) {
        let addResult = null;
        // 用来区分数据容器的添加还是
        if (useContainer) {
          addResult = await dispatch(
            updateContainerFilter({
              containerId: editItem.data?.id,
              type: 'bind',
              id,
              filterId: result.id,
            }),
          );
        } else {
          addResult = await dispatch(addComponentFilter({ id, filterId: result.id }));
        }
        if (addResult) {
          setAdding(false);
          window.sessionStorage.removeItem(id.toString());
        }
      }
    },
    [dispatch, id, editItem],
  );

  const handleTrigger = useCallback(
    async (filterId, enable) => {
      let result = null;
      if (useContainer) {
        result = await dispatch(
          updateContainerFilter({
            containerId: editItem.data?.id,
            type: 'enable',
            id,
            filterId,
            enable,
          }),
        );
      } else {
        result = await dispatch(triggerComponentFilter({ id, filterId, enable }));
      }
      return result;
    },
    [dispatch, id, editItem],
  );

  const handleSort = useCallback(
    ({ oldIndex, newIndex }) => {
      if (useContainer) {
        const filter = usedFilters[oldIndex];
        filter &&
          dispatch(
            updateContainerFilter({
              containerId: editItem.data?.id,
              type: 'sort',
              id,
              filterId: filter.id,
              rankIndex: newIndex,
            }),
          );
      }
      dispatch(sortComponentFilter({ id, oldIndex, newIndex }));
    },
    [dispatch, id, editItem],
  );

  const currentFilters = usedFilters
    .filter((d) => d.enable)
    .map((d) => filters.find((o) => o.id === d.id));
  let resultData = '';
  if (visible) {
    resultData = useFilter
      ? filterData({
          data: originData,
          filters: currentFilters,
        })
      : originData;
  }
  const onPreviewContent = (value) => {
    setPreviewContent(value);
  };

  return (
    <Drawer
      className={`${styles.drawer} ${styles.filter} ${styles.drawerTitle}`}
      visible={visible}
      onClose={onClose}
      closable={false}
      zIndex={zIndex}
      destroyOnClose={true}
      title={<Title onClose={onClose} />}
      placement="right"
      mask={false}
      width={520}>
      {previewContent && (
        <PreviewContent
          previewContent={previewContent}
          onChange={(v) => {
            setPreviewContent(v);
          }}
        />
      )}

      <div style={{ padding: '0 16px 16px', maxHeight: 'calc(100vh - 114px)', overflow: 'auto' }}>
        <div style={{ margin: '8px 0 20px 0' }}>
          <label>开启过滤器：</label>
          <Switch
            checked={useFilter}
            onChange={async (value) => {
              const hide = message.loading((value ? '开启' : '关闭') + '中...', 0);
              useContainer
                ? await dispatch(
                    updateContainerFilter({
                      id,
                      useFilter: value,
                      containerId: editItem.data?.id,
                      type: 'useFilter',
                    }),
                  )
                : await dispatch(updateComponentDataConfig({ id, useFilter: value }));
              hide();
            }}
          />
        </div>

        {useFilter ? (
          <div style={{ display: 'flex', alignItems: 'center', marginBottom: 20 }}>
            <label>选择过滤器：</label>
            <Select
              value="请选择过滤器"
              showSearch
              optionFilterProp="title"
              style={{ flex: 1, marginRight: 12 }}
              placeholder="请选择过滤器"
              onChange={(value) => dispatch(addComponentFilter({ id, filterId: value }))}>
              {leaveFilterOptions.map((d) => (
                <Option key={d.id} value={d.id} title={d.name}>
                  <div className="flex-between">
                    <span>{d.name}</span>
                    <span
                      className="click"
                      onClick={(e) => {
                        e.stopPropagation();
                        let i = 1;
                        let name = `${d.name} ${i}`;
                        while (filters.some((o) => o.name === name)) {
                          i++;
                          name = `${d.name} ${i}`;
                        }
                        handleAdd({
                          name: name,
                          content: d.content,
                          callbackKeys: d.callbackKeys,
                        });
                      }}>
                      复制
                    </span>
                  </div>
                </Option>
              ))}
            </Select>
            <Button
              className="dark"
              type="primary"
              ghost
              disabled={adding}
              onClick={() => setAdding(true)}>
              + 新建过滤器
            </Button>
          </div>
        ) : null}

        {(usedFilters.length > 0 || adding) && (
          <MySortableContainer onSortEnd={handleSort} useDragHandle>
            {usedFilters.map((d, i) => {
              const filter = filters.find((o) => o.id === d.id);
              const prevFilters = usedFilters
                .filter((o, j) => j < i && o.enable)
                .map((o) => filters.find((a) => a.id === o.id));
              const data = filterData({
                data: originData,
                filters: prevFilters,
              });

              if (filter) {
                return (
                  <FilterItem
                    key={d.id}
                    id={d.id}
                    index={i}
                    componentId={id}
                    drawerStates={visible}
                    collapsedCode={createCode === d.id}
                    enable={d.enable}
                    onPreviewContent={onPreviewContent}
                    name={filter.name}
                    content={filter.content}
                    callbackKeys={filter.callbackKeys}
                    usedComponents={filter.usedComponents}
                    originData={data}
                    onDelete={handleDelete}
                    onSubmit={handleUpdate}
                    onTrigger={handleTrigger}
                  />
                );
              } else {
                return null;
              }
            })}

            {adding && (
              <FilterAdd
                onRemove={handleRemove}
                componentId={id}
                drawerStates={visible}
                onSubmit={handleAdd}
                originData={resultData}
              />
            )}
          </MySortableContainer>
        )}

        <div style={{ marginTop: 32, marginBottom: 16 }}>
          数据响应结果
          <span style={{ color: '#999999', fontSize: '12px' }}>（只读）</span>
        </div>

        <AceEditor
          className="dark"
          mode="json"
          theme="twilight"
          width="488px"
          height="326px"
          readOnly={true}
          name="responseData"
          tabSize={2}
          value={JSON.stringify(resultData, null, 2)}
          showGutter={true}
          editorProps={{ $blockScrolling: true }}
          setOptions={{ wrap: true }}
        />
      </div>
      {childrenDrawer}
    </Drawer>
  );
}

const mapStateToProps = ({ filters, componentsById }) => {
  return {
    filters: getFiltersWithUsedComponents({ filters: filters.list, componentsById }),
  };
};

export default connect(mapStateToProps)(Filter);
