import React, { useState, useRef, useEffect } from 'react';
import { useIntl, FormattedMessage, useAccess } from 'umi';
import type { ProColumns, ActionType } from '@ant-design/pro-table';
import ProTable from '@ant-design/pro-table';
import { FooterToolbar, PageContainer } from '@ant-design/pro-layout';
import { Button, message } from 'antd';
import { PlusOutlined, FileExcelOutlined } from '@ant-design/icons';
import { downloadImportExcelExample, graphql, importExcel, remove } from '@/services/mgr/api';
import CreateForm from './components/CreateForm';
import EditForm from './components/EditForm';
import type { ReconfirmProps } from '@/components/ReconfirmForm';
import ReconfirmForm, { EmptyReconfirmProps } from '@/components/ReconfirmForm';
import ImportForm from '@/components/excel/ImportForm';
import ExportForm from '@/components/excel/ExportForm';
import {
  getSingleTable,
  columnBuilderManager,
  specificationBuilderManager,
  requistFieldBuilderManager,
} from './utils/api';
import moment from 'moment';

const Main: React.FC<any> = (props) => {
  const intl = useIntl();

  const [singleTable, setSingleTable] = useState<Api.SingleTable>();
  const [columns, setColumns] = useState<ProColumns<any>[]>([]);

  const actionRef = useRef<ActionType>();
  const [createFormVisible, setCreateFormVisible] = useState(false);
  const [editFormVisible, setEditFormVisible] = useState(false);
  const [currentRow, setCurrentRow] = useState<any>();
  const [selectedRows, setSelectedRows] = useState<any[]>([]);
  const [reconfirmProps, setReconfirmProps] = useState<ReconfirmProps>(EmptyReconfirmProps);
  const [reconfirmFormVisible, setReconfirmFormVisible] = useState(false);
  const [criteria, setCriteria] = useState<any>();
  const [importFormVisible, setImportFormVisible] = useState(false);
  const [exportFormVisible, setExportFormVisible] = useState(false);

  const access = useAccess();

  const getOptionColumn = (st: Api.SingleTable | undefined) => {
    const option: ProColumns<any>[] = [];
    if (
      (st?.canEdit && access.grantAccess(st?.editAccess)) ||
      (st?.canRemove && access.grantAccess(st?.removeAccess))
    ) {
      option.push({
        title: '操作',
        valueType: 'option',
        width: 90,
        fixed: 'right',
        render: (_, record) => {
          return [
            st?.canEdit && access.grantAccess(st?.editAccess) && (
              <a
                key="edit"
                onClick={async () => {
                  setCurrentRow(record);
                  setEditFormVisible(true);
                }}
              >
                <FormattedMessage id="component.option.edit" defaultMessage="编辑" />
              </a>
            ),
            st?.canRemove && access.grantAccess(st?.removeAccess) && (
              <a
                key="remove"
                onClick={() => {
                  setReconfirmProps({
                    title: intl.formatMessage({
                      id: 'component.option.remove.reconfirm.title',
                      defaultMessage: '确定删除？',
                    }),
                    message: intl.formatMessage({
                      id: 'component.option.remove.reconfirm.message',
                      defaultMessage: '删除后，信息将无法找回。',
                    }),
                    comfirmHandler: async () => {
                      await remove(singleTable?.entityMetadata.code as string, record);
                    },
                    onSubmitting: async () => {
                      const hide = message.loading(
                        intl.formatMessage({
                          id: 'component.option.remove.loading',
                          defaultMessage: '正在删除...',
                        }),
                      );
                      return {
                        hide,
                      };
                    },
                    onSuccess: async (params) => {
                      params.hide();
                      setReconfirmFormVisible(false);
                      actionRef.current?.reload();
                    },
                    onError: async (params) => {
                      params.hide();
                    },
                  });
                  setReconfirmFormVisible(true);
                }}
              >
                <FormattedMessage id="component.option.remove" defaultMessage="删除" />
              </a>
            ),
          ];
        },
      });
    }
    return option;
  };

  useEffect(() => {
    const routeName = props?.route?.name as string;
    getSingleTable(routeName)
      .then((result) => {
        const singleTableLocal = result.data.singleTable.slice().pop() as
          | Api.SingleTable
          | undefined;
        singleTableLocal?.fields.sort((a, b) => a.ordinal - b.ordinal);
        setSingleTable(singleTableLocal);
      })
      .catch(() => {
        message.error('获取数据失败。');
      })
      .finally(() => {});
  }, [props?.route?.name]);

  useEffect(() => {
    if (!!!singleTable) {
      return;
    }
    setColumns(columnBuilderManager.build(singleTable));
    //actionRef.current?.reload();
  }, [actionRef, singleTable]);

  const getData = async (params: any) => {
    if (!!!singleTable) {
      return {
        data: [],
        total: 0,
      };
    }
    const queryOption = `${singleTable.entityMetadata.code}Page`;
    const specification = specificationBuilderManager.build(params, singleTable);
    const requistField = requistFieldBuilderManager.build(singleTable);
    let sort = '';
    if (singleTable.orders && singleTable.orders.length > 0) {
      sort = `sort:{orders:${singleTable.orders}}`;
    }
    const gqlString = `query{
      ${queryOption}(pageable:{
        page: ${params.current - 1},
        size: ${params.pageSize},
        ${sort}
      },${specification}){
        totalPages,
        totalElements,
        ${requistField}
      }
    }`;
    const graphqlParams = {
      operationName: null,
      variables: {},
      query: gqlString,
    };
    const sr = await graphql(graphqlParams);
    return {
      data: sr.data[queryOption].content,
      total: sr.data[queryOption].totalElements,
    };
  };

  return (
    <PageContainer
      header={{
        title: null,
      }}
    >
      <ProTable<any, any>
        headerTitle={singleTable?.name}
        rowKey="id"
        actionRef={actionRef}
        search={{
          labelWidth: 120,
        }}
        scroll={
          singleTable?.scroll && singleTable.scroll.length > 0
            ? JSON.parse(singleTable.scroll)
            : undefined
        }
        toolBarRender={() => [
          singleTable?.canCreate && access.grantAccess(singleTable?.createAccess) && (
            <Button
              type="primary"
              key="create"
              onClick={() => {
                setCreateFormVisible(true);
              }}
            >
              <PlusOutlined />
              <FormattedMessage id="component.option.add" defaultMessage="新增" />
            </Button>
          ),
          singleTable?.canImport && access.grantAccess(singleTable?.importAccess) && (
            <Button
              type="default"
              key="import"
              onClick={() => {
                setImportFormVisible(true);
              }}
            >
              <FileExcelOutlined />
              <FormattedMessage id="component.option.import" defaultMessage="导入" />
            </Button>
          ),
          singleTable?.canExport && (
            <Button
              type="default"
              key="export"
              onClick={() => {
                setExportFormVisible(true);
              }}
            >
              <FileExcelOutlined />
              <FormattedMessage id="component.option.exprot" defaultMessage="导出" />
            </Button>
          ),
        ]}
        request={async (params) => {
          setCriteria(params);
          return await getData(params);
        }}
        columns={[...columns, ...getOptionColumn(singleTable)]}
        rowSelection={{
          onChange: (_, rows) => {
            setSelectedRows(rows);
          },
          preserveSelectedRowKeys: false,
        }}
        tableAlertRender={false}
        onLoad={(datasource) => {
          if (selectedRows?.length > 0) {
            setSelectedRows(selectedRows.filter((ele) => datasource.find((i) => i.id === ele.id)));
          }
        }}
      />
      {selectedRows?.length > 0 && (
        <FooterToolbar
          extra={
            <div>
              <FormattedMessage id="component.option.batch.label.1" defaultMessage="已选择" />
              {selectedRows?.length}
              <FormattedMessage id="component.option.batch.label.2" defaultMessage="项" />
            </div>
          }
        >
          {singleTable?.canRemove && access.grantAccess(singleTable?.removeAccess) && (
            <Button
              type="primary"
              danger
              onClick={() => {
                setReconfirmProps({
                  title: intl.formatMessage({
                    id: 'component.option.remove.reconfirm.title',
                    defaultMessage: '确定删除？',
                  }),
                  message: intl.formatMessage({
                    id: 'component.option.remove.reconfirm.message',
                    defaultMessage: '删除后，信息将无法找回。',
                  }),
                  comfirmHandler: async () => {
                    for (let i = 0; i < selectedRows.length; i++) {
                      const hide = message.loading(`
                    ${intl.formatMessage({
                      id: 'component.option.batch.loading.1',
                      defaultMessage: '正在执行第',
                    })}
                    ${i + 1}
                    ${intl.formatMessage({
                      id: 'component.option.batch.loading.2',
                      defaultMessage: '项...',
                    })}`);
                      try {
                        await remove(singleTable?.entityMetadata.code as string, {
                          id: selectedRows[i].id,
                        });
                        hide();
                      } catch {
                        hide();
                      }
                    }
                  },
                  onSubmitting: async () => {},
                  onSuccess: async () => {
                    setReconfirmFormVisible(false);
                    actionRef.current?.reload();
                  },
                  onError: async () => {},
                });
                setReconfirmFormVisible(true);
              }}
            >
              <FormattedMessage id="component.option.batch.delete" defaultMessage="批量删除" />
            </Button>
          )}
        </FooterToolbar>
      )}
      <CreateForm
        singleTable={singleTable}
        visible={createFormVisible}
        onVisibleChange={setCreateFormVisible}
        onSubmitting={async () => {
          const hide = message.loading(
            intl.formatMessage({
              id: 'component.option.add.loading',
              defaultMessage: '正在新增...',
            }),
          );
          return {
            hide,
          };
        }}
        onSuccess={async (params) => {
          params.hide();
          setCreateFormVisible(false);
          actionRef.current?.reload();
        }}
        onError={async (params) => {
          params.hide();
        }}
      />
      <EditForm
        singleTable={singleTable}
        values={currentRow || {}}
        visible={editFormVisible}
        onVisibleChange={setEditFormVisible}
        onSubmitting={async () => {
          const hide = message.loading(
            intl.formatMessage({
              id: 'component.option.edit.loading',
              defaultMessage: '正在更新...',
            }),
          );
          return {
            hide,
          };
        }}
        onSuccess={async (params) => {
          params.hide();
          setEditFormVisible(false);
          actionRef.current?.reload();
        }}
        onError={async (params) => {
          params.hide();
        }}
      />
      <ReconfirmForm
        visible={reconfirmFormVisible}
        onVisibleChange={setReconfirmFormVisible}
        reconfirmProps={reconfirmProps}
      />
      <ImportForm
        importHandler={async (formdata) => {
          if (singleTable?.entityMetadata.code)
            await importExcel(singleTable.entityMetadata.code, formdata);
        }}
        visible={importFormVisible}
        onVisibleChange={setImportFormVisible}
        onSubmitting={async () => {
          const hide = message.loading(
            intl.formatMessage({
              id: 'component.option.import.loading',
              defaultMessage: '正在导入...',
            }),
          );
          return {
            hide,
          };
        }}
        onSuccess={async (params) => {
          params.hide();
          setImportFormVisible(false);
          actionRef.current?.reload();
        }}
        onError={async (params) => {
          params.hide();
        }}
        excelExample={{
          download: async () => {
            if (singleTable?.entityMetadata.code)
              return await downloadImportExcelExample(singleTable.entityMetadata.code);
            return null;
          },
          fileNameProvider: async () => {
            if (singleTable?.entityMetadata.name) return singleTable?.entityMetadata.name;
            return null;
          },
        }}
      />
      <ExportForm
        dataGetter={async (pageParams) => {
          return (
            await getData({
              ...criteria,
              current: pageParams.current,
              pageSize: pageParams.pageSize,
            })
          ).data;
        }}
        columnsGetter={async () => {
          if (singleTable?.fields) {
            return singleTable.fields
              .filter((item) => !!!item.hideInTable)
              .map((item) => ({
                code: item.code,
                name: item.name,
              }));
          } else {
            return [];
          }
        }}
        fileNameProvider={async () => {
          if (singleTable?.name) {
            const data = moment().format('-YYYYMMDDHHmmss');
            return singleTable.name + data + '.xlsx';
          }
          return 'Data';
        }}
        param={criteria || {}}
        visible={exportFormVisible}
        onVisibleChange={setExportFormVisible}
        onSubmitting={async () => {
          const hide = message.loading(
            intl.formatMessage({
              id: 'component.option.exprot.loading',
              defaultMessage: '正在导出...',
            }),
          );
          return {
            hide,
          };
        }}
        onSuccess={async (params) => {
          params.hide();
          setExportFormVisible(false);
        }}
        onError={async (params) => {
          params.hide();
        }}
      />
    </PageContainer>
  );
};

export default Main;
