/*
 * @Description: 个人版数据
 * @Author: taosu
 * @Date: 2022-01-11 14:16:01
 * @LastEditTime: 2022-04-27 18:17:08
 * @LastEditors: Nian Yi
 */
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import ImportCsvDataModal from './ImportCsvdata';
import EasyvButton from 'components/EasyvButton';
import { Menu, Dropdown, Form } from '@easyv/antd';
import styles from './index.less';
import {
  ExpandAltOutlined,
  FileTextOutlined,
  SyncOutlined,
  QuestionCircleOutlined,
} from '@easyv/react-icons';
import isEqual from 'lodash/isEqual';
import message from 'components/message';
import {
  excelDataToJson,
  fetchAndDecode,
  initDataToExcelData,
} from 'components/EasyvCsvExcel/util';
import EasyvModal, { useActionModalRef, useConfirmRef } from 'components/EasyvModal';
import { getSource } from 'models/source';
import CsvExcelContent from './csvExcelContent';
import EasyvCsvExcel, { EasyvCsvExcelRef } from 'components/EasyvCsvExcel';
import { Course } from 'models/course.types';
import { connect, useSelector } from 'react-redux';
import { RootState } from 'models';
import { updateVersion } from 'models/updateVersion';
import { useDispatch } from 'react-redux';
import EasyvTooltip from 'components/EasyvTooltip';
import { getAssetsUrl } from 'utils/utils';
import { addSource } from 'models/source';
import { AddSource } from '@/models/source.types';
import { getTopScreenId } from '@/utils/screen';
import { ComponentItem, DataFrom } from '@/models/component.types';
import { updateComponentDataConfig } from '@/models/component';

type PersonalCsvType = {
  componentBaseInfo: {
    module_name: string;
    version: string;
  };
  sources: any;
  addSource: AddSource;
  updateComponentDataConfig: (params: {
    id: number;
    useFilter?: boolean;
    autoUpdate?: ComponentItem['autoUpdate'];
    data?: any;
    fields?: any;
  }) => any;
  value: any;
  componentId: number;
};

const { useForm } = Form;

const PersonalCSV = (props: PersonalCsvType) => {
  const { componentBaseInfo, sources, addSource, value, componentId, updateComponentDataConfig } =
    props;

  const onUpdate = useCallback(
    (value) => {
      updateComponentDataConfig({ ...value, id: componentId });
    },
    [props.componentId],
  );

  const [csvBoxHeight, setCsvBoxHeight] = useState<string | number>('calc(100vh - 430px)'); // csv 编辑器高度 - 动态计算
  const [current, setCurrent] = useState<'dataSource' | 'import'>('dataSource'); // 上传数据的menukey
  const [form] = useForm();
  const csvExcelRef = useRef<EasyvCsvExcelRef>(null);
  const modalCsvExcelRef = useRef<EasyvCsvExcelRef>(null);
  const personalRef = useRef<HTMLDivElement>(null);
  const confirmRef = useConfirmRef();
  const modalRef = useActionModalRef();
  const dataImportModalRef = useActionModalRef();
  const [confirmModalType, setConfirmModalType] = useState<'restoreDefault' | 'saveWarning'>(
    'restoreDefault',
  );
  const dispatch = useDispatch();

  const course = useSelector<RootState>((state) => state.course) as RootState['course'];

  useEffect(() => {
    const element: any = personalRef.current;
    const resizeObserver = new ResizeObserver(() => {
      const height = personalRef.current?.offsetHeight;
      const oStyle = element.currentStyle
        ? element.currentStyle
        : window.getComputedStyle(element, null);
      const top = oStyle.getPropertyValue('padding-top');
      const bottom = oStyle.getPropertyValue('padding-bottom');
      if (height) {
        const csvH = height - parseInt(top) - parseInt(bottom) - 40 - 20;
        if (typeof csvH && csvH > 0) {
          resizeObserver.unobserve(element);
          setCsvBoxHeight(csvH);
        }
      }
    });
    resizeObserver.observe(element);
    return () => {
      resizeObserver.unobserve(element);
    };
  }, []);

  // 打开上传数据弹框
  const openModal = (e) => {
    form.resetFields();
    setCurrent(e.key);
    if (e.key === 'dataList') {
      versionUpdate();
      return;
    }
    dataImportModalRef.current?.show();
  };

  // 获取csv数据
  const onComplateCsv = (dataId) => {
    getSource(dataId)().then(async (dataBaseInfo: any) => {
      if (!dataBaseInfo) {
        return;
      }
      const res: any = await fetchAndDecode(getAssetsUrl(`${dataBaseInfo.filePath}`));
      if (res.success) {
        handleUpdate(excelDataToJson(res.data));
        dataImportModalRef.current?.close();
      } else {
        message.error(res.message);
      }
    });
  };

  // csv本地上传
  const onImport = useCallback((value) => {
    value = {
      ...value,
      type: 'csv',
      desc: '',
      encode: 'auto',
    };
    addSource(value).then((res) => {
      onComplateCsv(res.data_id);
    });
  }, []);

  // 提示升级版本获取更多数据（高级版本）
  const versionUpdate = () => {
    dispatch(updateVersion({ show: true, targetVersion: 'saas_advanced' }));
  };

  // 上传数据dropmenu
  const csvdataList = (
    <Menu onClick={openModal} className={styles.dropdownMenu}>
      <Menu.Item key="dataSource">
        <p>数据导入</p>
      </Menu.Item>
      <Menu.Item key="import">
        <p>本地上传</p>
      </Menu.Item>
      <Menu.Item key="dataList">
        <span className={styles.moreDate}>更多数据</span>
        <EasyvTooltip
          title={
            <>
              支持接入API、MySQL、Oracle、SQL<br></br>
              Server、PostgreSQL、ClickHouse、<br></br>
              阿里云API网关、数栈API等动态数据
            </>
          }>
          <QuestionCircleOutlined className={styles.sustainDate} />
        </EasyvTooltip>
      </Menu.Item>
    </Menu>
  );

  const handleUpdate = (data) => {
    if (data) {
      try {
        if (!isEqual(data, value)) {
          onUpdate({ data });
        }
      } catch (error) {
        message.error('数据格式有误，请检查');
      }
    }
  };

  const handleSubmit = () => {
    form.validateFields().then((values) => {
      if (current === 'dataSource') {
        onComplateCsv(values.dataSource);
      } else {
        onImport(values);
      }
    });
  };

  const handleClose = () => {
    dataImportModalRef.current?.close();
  };

  const handleFileChange = (file) => {
    form.setFieldsValue({
      name: form.getFieldValue('name') || file.name,
      filePath: file,
      encode: 'auto',
      desc: '',
      type: 'csv',
    });
  };

  const data = useMemo(() => {
    return initDataToExcelData(JSON.parse(value || {}));
  }, [value]);

  // 教程
  const _course = course[Course.EDIT_CSV_TABLE];

  const EditModelTitle = () => {
    return (
      <div style={{ display: 'flex' }}>
        <span>修改数据</span>
        {_course && (
          <a className={styles.course} target="_blank" href={_course.courseUrl}>
            <FileTextOutlined style={{ lineHeight: '10px' }} />
            <span> 查看教程</span>
          </a>
        )}
      </div>
    );
  };

  return (
    <>
      <div className={styles.personalData} ref={personalRef}>
        <div className={styles.btnGroup}>
          <div>
            <Dropdown overlay={csvdataList} trigger={['click']}>
              <EasyvButton theme="default">上传数据</EasyvButton>
            </Dropdown>
            <EasyvButton
              onClick={() => {
                setConfirmModalType('saveWarning');
                modalRef.current?.show();
              }}
              theme="primary"
              style={{ marginLeft: 8 }}>
              编辑数据
            </EasyvButton>
          </div>
          <p
            className={styles.recover}
            onClick={() => {
              setConfirmModalType('restoreDefault');
              confirmRef.current?.show();
            }}>
            <SyncOutlined className={styles.reloadIcon} />
            <span className={styles.recoverText}>恢复默认数据</span>
          </p>
        </div>
        <div className={styles.csvContent}>
          <div
            onDoubleClick={() => {
              setConfirmModalType('saveWarning');
              modalRef.current?.show();
            }}>
            <EasyvCsvExcel
              containerId="readContainerIdReadOnly"
              contentId="readContentIdReadOnly"
              readonly={true}
              ref={csvExcelRef}
              width={310}
              height={csvBoxHeight}
              style={{ height: csvBoxHeight, overflowY: 'hidden' }}
              data={data}
            />
          </div>
          <p
            onClick={() => {
              setConfirmModalType('saveWarning');
              modalRef.current?.show();
            }}
            className={styles.fullScreen}>
            <ExpandAltOutlined style={{ fontSize: 16 }} className="icon" />
          </p>
        </div>
      </div>
      <ImportCsvDataModal
        form={form}
        ref={dataImportModalRef}
        handleSubmit={handleSubmit}
        handleClose={handleClose}
        changeCurrent={(e) => setCurrent(e.key)}
        current={current}
        sources={sources}
        handleFileChange={(e) => handleFileChange(e)}
      />

      <EasyvModal.ActionModal
        width={1000}
        ref={modalRef}
        title={<EditModelTitle />}
        maxHeight="none"
        onCancel={() => {
          if (modalCsvExcelRef.current?.getChangedStatus()) {
            confirmRef.current?.show();
            return;
          }
          modalRef.current?.close();
        }}
        footer={
          <div style={{ textAlign: 'center' }}>
            <EasyvButton
              theme="primary"
              onClick={() => {
                onUpdate({ data: excelDataToJson(modalCsvExcelRef.current?.getData()) });
                modalRef.current?.close();
              }}>
              完成
            </EasyvButton>
          </div>
        }
        content={<CsvExcelContent modalCsvExcelRef={modalCsvExcelRef} value={value} />}
      />

      <EasyvModal.Confirm
        onOk={() => {
          if (confirmModalType === 'saveWarning') {
            onUpdate({ data: excelDataToJson(modalCsvExcelRef.current?.getData()) });
            modalRef.current?.close();
          } else {
            onUpdate(
              window.component[
                `${componentBaseInfo.module_name}@${componentBaseInfo.version}`
              ]?.getDefaultData(),
            );
            confirmRef.current?.close();
          }
        }}
        onCancel={() => {
          confirmRef.current?.close();
          modalRef.current?.close();
        }}
        onOkBtnType="primary"
        okText={confirmModalType === 'saveWarning' ? '保存' : '确定'}
        content={
          confirmModalType === 'saveWarning'
            ? '是否保存对当前数据的修改?'
            : '是否恢复该组件的初始默认数据?'
        }
        title={confirmModalType === 'saveWarning' ? '未保存' : '恢复默认数据'}
        iconType="warning"
        ref={confirmRef}
      />
    </>
  );
};

const mapStateToProps = ({ sources, componentsById, createApp, dataContainers }) => {
  const { componentsChildSelected, layersSelected } = createApp;
  const screenId = getTopScreenId();

  const componentId = componentsChildSelected || layersSelected[0];
  const current = componentsById[componentId] as ComponentItem;
  if (current.dataFrom === DataFrom.DATA_CONTAINER) {
    let containersFilterResult = {};
    let dataContainerList = [];
    dataContainerList = dataContainers.list.filter((d) => d.screenId === screenId);
    current.dataContainers.map((d) => {
      containersFilterResult[d.id] = dataContainers.filterResult[d.id];
    });
  }

  return {
    sources: sources.list || [],
    value: JSON.stringify(current.dataConfigs['static'].data, null, '\t'),
    componentId,
    componentBaseInfo: current.base,
  };
};

const mapDispatchToProps = {
  addSource,
  updateComponentDataConfig,
};

function areEqual(props, nextProps) {
  return (
    isEqual(props.value, nextProps.value) &&
    isEqual(props.sources, nextProps.sources) &&
    isEqual(props.componentId, nextProps.componentId) &&
    isEqual(props.componentBaseInfo, nextProps.componentBaseInfo)
  );
}
export default connect(mapStateToProps, mapDispatchToProps)(memo(PersonalCSV, areEqual));
