import useDidUpdateEffect from "@/hooks/useDidUpdateEffect";
import { doFetch } from "@/utils/doFetch";
import {
  CloseOutlined,
  DownOutlined,
  PlusOutlined,
  RedoOutlined,
} from "@ant-design/icons";
import {
  ProForm,
  ProFormCascader,
  ProFormCheckbox,
  ProFormDatePicker,
  ProFormDateRangePicker,
  ProFormDateTimePicker,
  ProFormDateTimeRangePicker,
  ProFormDependency,
  ProFormDigit,
  ProFormDigitRange,
  ProFormList,
  ProFormMoney,
  ProFormRadio,
  ProFormRate,
  ProFormSelect,
  ProFormSlider,
  ProFormSwitch,
  ProFormText,
  ProFormTextArea,
  ProFormTimePicker,
  ProFormTreeSelect,
  ProFormUploadButton,
  ProFormUploadDragger,
} from "@ant-design/pro-components";
import * as Antd from "antd";
import ImgCrop from "antd-img-crop";
import dayjs from "dayjs";
import { createElement, memo, useRef, useState } from "react";
import EditorItem from "./EditorItem";
import EditTable from "./EditTable";

const { Image, Form, Upload, Col, Dropdown, Menu, Tabs } = Antd;

function upperCase(str) {
  const newStr = str.slice(0, 1).toUpperCase() + str.slice(1);
  return newStr;
}
// tree遍历
function treeForeach(tree, func) {
  tree.forEach((data) => {
    func(data);
    data.children && treeForeach(data.children, func); // 遍历子树
  });
}

// colProps 默认删格
function Input({ item, colProps }) {
  let keys = item.key ?? item.dataIndex ?? "";
  keys = keys ?? "";
  const defaultrule =
    keys.indexOf("phone") != -1
      ? {
          pattern: /^(((\d{3,4}-)?[0-9]{7,8})|(1(3|4|5|6|7|8|9)\d{9}))$/,
          message: item.title + "格式不正确",
        }
      : keys.indexOf("mail") != -1
      ? {
          pattern:
            /^[a-z0-9A-Z]+[- | a-z0-9A-Z . _]+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-z]{2,}$/,
          message: "邮箱格式不正确",
        }
      : {};

  return (
    <>
      <ProFormText
        fieldProps={item?.fieldProps}
        formItemProps={{
          ...item.formItemProps,
          rules: [defaultrule, ...(item?.formItemProps?.rules ?? [])],
        }} //手机号邮箱自带验证
        name={keys}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请输入${item.title}`}
      />
    </>
  );
}
//pwd
function Password({ item, colProps }) {
  return (
    <>
      <ProFormText.Password
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请输入${item.title}`}
      />
    </>
  );
}
//money
function Money({ item, colProps }) {
  return (
    <>
      <ProFormMoney
        locale="zh-CN"
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请输入${item.title}`}
        min={item.min}
        max={item.max}
      />
    </>
  );
}

//textarea
function Textarea({ item }) {
  return (
    <>
      <ProFormTextArea
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? { span: 24 }}
        label={item.title}
        placeholder={`请输入${item.title}`}
      />
    </>
  );
}

//digit
function Digit({ item, colProps }) {
  return (
    <>
      <ProFormDigit
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请输入${item.title}`}
        min={item.min}
        max={item.max}
        fieldProps={{
          precision: item.precision ?? 0,
          ...(item?.fieldProps ?? {}),
        }}
      />
    </>
  );
}

//digitrange
function DigitRange({ item, colProps }) {
  return (
    <>
      <ProFormDigitRange
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={["请输入最小值", "请输入最大值"]}
        min={item.min}
        max={item.max}
        fieldProps={{
          precision: item.precision ?? 0,
          ...(item?.fieldProps ?? {}),
        }}
      />
    </>
  );
}

//Date
function Date({ item, colProps }) {
  return (
    <>
      <ProFormDatePicker
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}

function DateWeek({ item, colProps }) {
  const weekFormat = "YYYY-MM-DD";
  const customWeekStartEndFormat = (value) =>
    `${dayjs(value).startOf("week").format(weekFormat)} ~ ${dayjs(value)
      .endOf("week")
      .format(weekFormat)}`;
  return (
    <>
      <ProFormDatePicker
        fieldProps={{
          ...item?.fieldProps,
          picker: "week",
          format: customWeekStartEndFormat,
        }}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}
//DateMonth
function DateMonth({ item, colProps }) {
  return (
    <>
      <ProFormDatePicker
        fieldProps={{ ...item?.fieldProps, picker: "month", format: "YYYY-MM" }}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}
//DateQuarter
function DateQuarter({ item, colProps }) {
  const quarterFormat = "YYYY-MM-DD";
  const customWeekStartEndFormat = (value) =>
    `${dayjs(value).startOf("quarter").format(quarterFormat)} ~ ${dayjs(value)
      .endOf("quarter")
      .format(quarterFormat)}`;
  return (
    <>
      <ProFormDatePicker
        fieldProps={{
          ...item?.fieldProps,
          picker: "quarter",
          format: customWeekStartEndFormat,
        }}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}
//DateYear
function DateYear({ item, colProps }) {
  return (
    <>
      <ProFormDatePicker
        fieldProps={{ ...item?.fieldProps, picker: "year", format: "YYYY" }}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}

//dateTime
function DateTime({ item, colProps }) {
  return (
    <>
      <ProFormDateTimePicker
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}
//DateRange
function DateRange({ item, colProps }) {
  return (
    <>
      <ProFormDateRangePicker
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={["请选择开始日期", "请选择结束日期"]}
        width="100%"
      />
    </>
  );
}
//dateTimeRange
function DateTimeRange({ item, colProps }) {
  return (
    <>
      <ProFormDateTimeRangePicker
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={["请选择开始时间", "请选择结束时间"]}
        width="100%"
      />
    </>
  );
}
//Time
function Time({ item, colProps }) {
  return (
    <>
      <ProFormTimePicker
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        width="100%"
      />
    </>
  );
}
//TimeRange
function TimeRange({ item, colProps }) {
  return (
    <>
      <ProFormTimePicker.RangePicker
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={["请选择开始时间", "请选择结束时间"]}
        width="100%"
      />
    </>
  );
}

function LinkSelect({ item, colProps, formRef, name, curindex }) {
  let curoption = item.options ?? null,
    curlinkparams = curoption?.linkParams ?? {}; //获取linkParams下声明的key
  return (
    <>
      <ProFormDependency name={Object.keys(curlinkparams)}>
        {(params) => {
          const curkey = item.key ?? item.dataIndex;
          return (
            <ProFormSelect
              convertValue={(value) => {
                return item?.fieldProps?.mode == "multiple"
                  ? !value
                    ? []
                    : null
                  : null;
              }}
              fieldProps={item?.fieldProps}
              formItemProps={item.formItemProps}
              name={curkey}
              colProps={item.colProps ?? colProps}
              label={item.title}
              placeholder={`请选择${item.title}`}
              params={params}
              mode={item?.mode}
              request={async (parse) => {
                let result = {};
                for (let key in curlinkparams) {
                  let reversekey = !curlinkparams[key]
                    ? key
                    : curlinkparams[key];
                  result[reversekey] = parse[key];
                }
                let res = await doFetch({
                  url: curoption?.path,
                  params: result,
                });
                if (name) {
                  let curvals = formRef?.current?.getFieldValue(name);
                  curvals = curvals.map((it, i) => {
                    if (i == curindex) {
                      it[curkey] = null;
                    }
                    return it;
                  });
                  formRef?.current?.setFieldsValue({ [name]: curvals });
                } else {
                  let curval = formRef?.current?.getFieldValue(curkey),
                    ifclean;
                  if (Array.isArray(curval)) {
                    ifclean = res?.data?.dataList
                      ?.map((it) => it.value)
                      .filter?.((it) => {
                        return curval?.includes(it);
                      });
                  } else {
                    ifclean = res?.data?.dataList.filter(
                      (it) => it.value == curval
                    )?.[0]?.value;
                  }
                  formRef?.current?.setFieldsValue({ [curkey]: ifclean });
                }
                return res?.data?.dataList ?? [];
              }}
              showSearch
            />
          );
        }}
      </ProFormDependency>
    </>
  );
}

function NolinkSelect({ item, colProps }) {
  let options = {
      options: [],
    },
    curoption = item.options ?? null;

  if (Array.isArray(curoption)) {
    options = {
      options: [...curoption],
    };
  } else if (curoption) {
    options = {
      request: async () => {
        let list = await doFetch({
          url: curoption?.path,
          params: curoption?.params,
        });
        return list.data.dataList;
      },
    };
  }

  return (
    <>
      <ProFormSelect
        fieldProps={{ ...item.fieldProps, dropdownMatchSelectWidth: 200 }}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        showSearch
        mode={item?.mode}
        {...options}
      />
    </>
  );
}

//Select 高阶组建
function Select(props) {
  let ifs = props?.item?.options?.linkParams;
  if (ifs) {
    return <LinkSelect {...props} />;
  } else {
    return <NolinkSelect {...props} />;
  }
}

function LinkTreeSelect({ item, colProps, formRef, name, curindex }) {
  let prevparse = useRef();
  let curoption = item.options ?? null,
    curlinkparams = curoption?.linkParams ?? {}; //获取linkParams下声明的key
  return (
    <>
      <ProFormDependency name={Object.keys(curlinkparams)}>
        {(params) => {
          const curkey = item.key ?? item.dataIndex;
          return (
            <ProFormTreeSelect
              fieldProps={{
                ...item?.fieldProps,
                fieldNames: {
                  label: "title",
                  value: "key",
                  children: "children",
                },
                showSearch: false,
                multiple: item?.mode === "multiple",
              }}
              formItemProps={item.formItemProps}
              name={curkey}
              colProps={item.colProps ?? colProps}
              label={item.title}
              placeholder={`请选择${item.title}`}
              params={params}
              request={async (parse) => {
                delete parse.keyWords;
                let result = {};
                for (let key in curlinkparams) {
                  let reversekey = !curlinkparams[key]
                    ? key
                    : curlinkparams[key];
                  result[reversekey] = parse[key];
                }
                let res = await doFetch({
                  url: curoption?.path,
                  params: result,
                });

                if (prevparse.current !== JSON.stringify(parse)) {
                  if (name) {
                    let curvals = formRef?.current?.getFieldValue(name);
                    curvals = curvals.map((it, i) => {
                      if (i == curindex) {
                        it[curkey] = null;
                      }
                      return it;
                    });
                    formRef?.current?.setFieldsValue({ [name]: curvals });
                  } else {
                    let curval = formRef?.current?.getFieldValue(curkey),
                      ifclean;
                    //树结构所有value提取到数组
                    let allvalue = [];
                    treeForeach(res?.data?.dataList, (node) => {
                      allvalue.push(node.key);
                    });

                    //过滤存在的value
                    if (Array.isArray(curval)) {
                      ifclean = allvalue?.filter?.((it) => {
                        return curval?.includes(it);
                      });
                    } else {
                      ifclean = allvalue?.filter?.((it) => it == curval)?.[0];
                    }

                    formRef?.current?.setFieldsValue({ [curkey]: ifclean });
                  }
                }
                prevparse.current = JSON.stringify(parse);
                return res?.data?.dataList ?? [];
              }}
            />
          );
        }}
      </ProFormDependency>
    </>
  );
}

function NolinkTreeSelect({ item, colProps }) {
  let options = {
      options: [],
    },
    curoption = item.options ?? null;

  if (Array.isArray(curoption)) {
    options = {
      options: [...curoption],
    };
  } else if (curoption) {
    options = {
      request: async () => {
        let list = await doFetch({
          url: curoption?.path,
          params: curoption?.params,
        });
        return list.data.dataList;
      },
    };
  }

  return (
    <>
      <ProFormTreeSelect
        fieldProps={{
          ...item?.fieldProps,
          fieldNames: { label: "title", value: "key", children: "children" },
          showSearch: true,
          multiple: item?.mode === "multiple",
        }}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        multiple
        {...options}
      />
    </>
  );
}

//TreeSelect 高阶组建
function TreeSelect(props) {
  let ifs = props?.item?.options?.linkParams;
  if (ifs) {
    return <LinkTreeSelect {...props} />;
  } else {
    return <NolinkTreeSelect {...props} />;
  }
}

function CheckboxItem({ item, colProps }) {
  return (
    <>
      <ProFormCheckbox
        fieldProps={item.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
      />
    </>
  );
}

function LinkCheckbox({ item, colProps, formRef, name, curindex }) {
  let curoption = item.options ?? null,
    curlinkparams = curoption?.linkParams ?? {}; //获取linkParams下声明的key
  return (
    <>
      <ProFormDependency name={Object.keys(curlinkparams)}>
        {(params) => {
          const curkey = item.key ?? item.dataIndex;
          return (
            <ProFormCheckbox.Group
              fieldProps={item?.fieldProps}
              formItemProps={item.formItemProps}
              name={curkey}
              colProps={item.colProps ?? colProps}
              label={item.title}
              placeholder={`请选择${item.title}`}
              params={params}
              request={async (parse) => {
                let result = {};
                for (let key in curlinkparams) {
                  let reversekey = !curlinkparams[key]
                    ? key
                    : curlinkparams[key];
                  result[reversekey] = parse[key];
                }
                let res = await doFetch({
                  url: curoption?.path,
                  params: result,
                });
                if (name) {
                  let curvals = formRef?.current?.getFieldValue(name);
                  curvals = curvals.map((it, i) => {
                    if (i == curindex) {
                      it[curkey] = null;
                    }
                    return it;
                  });
                  formRef?.current?.setFieldsValue({ [name]: curvals });
                } else {
                  let curval = formRef?.current?.getFieldValue(curkey),
                    ifclean;
                  if (Array.isArray(curval)) {
                    ifclean = res?.data?.dataList
                      ?.map((it) => it.value)
                      .filter?.((it) => {
                        return curval?.includes(it);
                      });
                  } else {
                    ifclean = res?.data?.dataList.filter(
                      (it) => it.value == curval
                    )?.[0]?.value;
                  }
                  formRef?.current?.setFieldsValue({ [curkey]: ifclean });
                }
                return res?.data?.dataList ?? [];
              }}
            />
          );
        }}
      </ProFormDependency>
    </>
  );
}

function NolinkCheckbox({ item, colProps }) {
  let options = {
      options: [],
    },
    curoption = item.options ?? null;

  if (Array.isArray(curoption)) {
    options = {
      options: [...curoption],
    };
  } else if (curoption) {
    options = {
      request: async () => {
        let list = await doFetch({
          url: curoption?.path,
          params: curoption?.params,
        });
        return list.data.dataList;
      },
    };
  }

  return (
    <>
      <ProFormCheckbox.Group
        fieldProps={item.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        {...options}
      />
    </>
  );
}

//Checkbox 高阶组建
function Checkbox(props) {
  let ifs = props?.item?.options?.linkParams;
  if (ifs) {
    return <LinkCheckbox {...props} />;
  } else {
    return <NolinkCheckbox {...props} />;
  }
}

function RadioItem({ item, colProps }) {
  return (
    <>
      <ProFormRadio
        fieldProps={item.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
      />
    </>
  );
}

function LinkRadio({ item, colProps, formRef, name, curindex }) {
  let curoption = item.options ?? null,
    curlinkparams = curoption?.linkParams ?? {}; //获取linkParams下声明的key
  return (
    <>
      <ProFormDependency name={Object.keys(curlinkparams)}>
        {(params) => {
          const curkey = item.key ?? item.dataIndex;
          return (
            <ProFormRadio.Group
              fieldProps={item?.fieldProps}
              formItemProps={item.formItemProps}
              name={curkey}
              colProps={item.colProps ?? colProps}
              label={item.title}
              placeholder={`请选择${item.title}`}
              params={params}
              request={async (parse) => {
                let result = {};
                for (let key in curlinkparams) {
                  let reversekey = !curlinkparams[key]
                    ? key
                    : curlinkparams[key];
                  result[reversekey] = parse[key];
                }
                let res = await doFetch({
                  url: curoption?.path,
                  params: result,
                });
                if (name) {
                  let curvals = formRef?.current?.getFieldValue(name);
                  curvals = curvals.map((it, i) => {
                    if (i == curindex) {
                      it[curkey] = null;
                    }
                    return it;
                  });
                  formRef?.current?.setFieldsValue({ [name]: curvals });
                } else {
                  let curval = formRef?.current?.getFieldValue(curkey),
                    ifclean;
                  if (Array.isArray(curval)) {
                    ifclean = res?.data?.dataList
                      ?.map((it) => it.value)
                      .filter?.((it) => {
                        return curval?.includes(it);
                      });
                  } else {
                    ifclean = res?.data?.dataList.filter(
                      (it) => it.value == curval
                    )?.[0]?.value;
                  }
                  formRef?.current?.setFieldsValue({ [curkey]: ifclean });
                }
                return res?.data?.dataList ?? [];
              }}
            />
          );
        }}
      </ProFormDependency>
    </>
  );
}

function NolinkRadio({ item, colProps }) {
  let options = {
      options: [],
    },
    curoption = item.options ?? null;

  if (Array.isArray(curoption)) {
    options = {
      options: [...curoption],
    };
  } else if (curoption) {
    options = {
      request: async () => {
        let list = await doFetch({
          url: curoption?.path,
          params: curoption?.params,
        });
        return list.data.dataList;
      },
    };
  }

  return (
    <>
      <ProFormRadio.Group
        fieldProps={item.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        {...options}
      />
    </>
  );
}

//Radio 高阶组建
function Radio(props) {
  let ifs = props?.item?.options?.linkParams;
  if (ifs) {
    return <LinkRadio {...props} />;
  } else {
    return <NolinkRadio {...props} />;
  }
}

function LinkCascader({ item, colProps, formRef, name, curindex }) {
  let prevparse = useRef();
  let curoption = item.options ?? null,
    curlinkparams = curoption?.linkParams ?? {}; //获取linkParams下声明的key
  return (
    <>
      <ProFormDependency name={Object.keys(curlinkparams)}>
        {(params) => {
          const curkey = item.key ?? item.dataIndex;
          return (
            <ProFormCascader
              fieldProps={{
                ...item?.fieldProps,
                fieldNames: {
                  label: "title",
                  value: "key",
                  children: "children",
                },
                showSearch: true,
                multiple: item?.mode === "multiple",
              }}
              formItemProps={item.formItemProps}
              name={curkey}
              colProps={item.colProps ?? colProps}
              label={item.title}
              placeholder={`请选择${item.title}`}
              params={params}
              request={async (parse) => {
                delete parse.keyWords;
                let result = {};
                for (let key in curlinkparams) {
                  let reversekey = !curlinkparams[key]
                    ? key
                    : curlinkparams[key];
                  result[reversekey] = parse[key];
                }
                let res = await doFetch({
                  url: curoption?.path,
                  params: result,
                });
                if (prevparse.current !== JSON.stringify(parse)) {
                  if (name) {
                    let curvals = formRef?.current?.getFieldValue(name);
                    curvals = curvals.map((it, i) => {
                      if (i == curindex) {
                        it[curkey] = null;
                      }
                      return it;
                    });
                    formRef?.current?.setFieldsValue({ [name]: curvals });
                  } else {
                    let curval = formRef?.current?.getFieldValue(curkey),
                      ifclean;
                    if (Array.isArray(curval)) {
                      ifclean = res?.data?.dataList
                        ?.map((it) => it.value)
                        .filter?.((it) => {
                          return curval?.includes(it);
                        });
                    } else {
                      ifclean = res?.data?.dataList.filter(
                        (it) => it.value == curval
                      )?.[0]?.value;
                    }
                    formRef?.current?.setFieldsValue({ [curkey]: ifclean });
                  }
                }
                prevparse.current = JSON.stringify(parse);
                return res?.data?.dataList ?? [];
              }}
            />
          );
        }}
      </ProFormDependency>
    </>
  );
}

function NolinkCascader({ item, colProps }) {
  let options = {
      options: [],
    },
    curoption = item.options ?? null;

  if (Array.isArray(curoption)) {
    options = {
      options: [...curoption],
    };
  } else if (curoption) {
    options = {
      request: async () => {
        let list = await doFetch({
          url: curoption?.path,
          params: curoption?.params,
        });
        return list.data.dataList;
      },
    };
  }

  return (
    <>
      <ProFormCascader
        fieldProps={{
          ...item?.fieldProps,
          fieldNames: { label: "title", value: "key", children: "children" },
          showSearch: true,
          multiple: item?.mode === "multiple",
        }}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请选择${item.title}`}
        {...options}
      />
    </>
  );
}

//Cascader 高阶组建
function Cascader(props) {
  let ifs = props?.item?.options?.linkParams;
  if (ifs) {
    return <LinkCascader {...props} />;
  } else {
    return <NolinkCascader {...props} />;
  }
}

//switch
function Switch({ item, colProps }) {
  return (
    <>
      <ProFormSwitch
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        placeholder={`请输入${item.title}`}
      />
    </>
  );
}

//Rate
function Rate({ item, colProps }) {
  return (
    <>
      <ProFormRate
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
      />
    </>
  );
}

//Slider
function Slider({ item, colProps }) {
  return (
    <>
      <ProFormSlider
        {...item?.fieldProps}
        fieldProps={item?.fieldProps}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
      />
    </>
  );
}

//uploadbtn
function UploadBtn({ item, colProps }) {
  return (
    <>
      <ProFormUploadButton
        fieldProps={{
          ...item?.fieldProps,
          action: REACT_APP_URL + "/file/upload",
          onPreview: (file) => {
            let url = "";
            if (file.response) {
              url = file.response.data.dataList[0].url;
            } else if (file.url) {
              url = file.url;
            } else {
              url = file.thumbUrl;
            }
            window.open(url);
          },
        }}
        transform={(value) => {
          const key = item.key ?? item.dataIndex;
          const transvalue = value?.map((it) => {
            if (it.response) {
              return it?.response?.data?.dataList[0];
            } else {
              return it;
            }
          });
          return {
            [key]: transvalue,
          };
        }}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
        title={`上传${item.title}`}
      />
    </>
  );
}

function UploadImg({ value, onChange, fieldProps }) {
  const [image, setImage] = useState({});
  let token = localStorage.getItem("TOKENES");

  function beforeUpload(file) {
    const isJpgOrPng =
      file.type === "image/jpg" ||
      file.type === "image/jpeg" ||
      file.type === "image/png";
    if (!isJpgOrPng) {
      message.error("只能上传.jpg/.jpeg/.png图片!");
      return;
    }
    return true;
  }

  // maxCount 最大数量
  const defaultconfig = {
    name: "file",
    action: REACT_APP_URL + "/file/upload",
    accept: ".jpg,.png,.jpeg",
    listType: "picture-card",
    beforeUpload: beforeUpload,
    fileList: value,
    headers: { token },
    onChange(info) {
      let {
        file: { status },
        fileList,
      } = info;
      onChange(fileList);
    },
    onRemove(file) {
      let uid = file?.response?.data?.dataList[0]?.uid ?? file?.uid;
      let newvalue = value.filter((it) => it.uid != uid);
      onChange(newvalue);
    },
    onPreview(file) {
      let url = "";
      if (file.response) {
        url = file.response.data.dataList[0].url;
      } else if (file.url) {
        url = file.url;
      } else {
        url = file.thumbUrl;
      }
      setImage({
        url,
        visible: true,
      });
    },
  };

  const uploadButton = (
    <div>
      <PlusOutlined />
      <div style={{ marginTop: 8 }}>上传图片</div>
    </div>
  );
  return (
    <>
      <Image
        src={image.url}
        width={0}
        height={0}
        preview={{
          visible: image?.visible,
          onVisibleChange: () => {
            if (image?.visible) {
              setImage((s) => ({
                ...s,
                visible: false,
              }));
            }
          },
        }}
      />
      {fieldProps?.crop ? (
        <ImgCrop
          rotate
          grid
          quality={1}
          shape={fieldProps?.crop?.shape ?? "rect"} //裁切区域形状,'rect' 或 'round'
          aspect={fieldProps?.crop?.aspect ?? 1 / 1} //裁切区域宽高比,width / height
        >
          <Upload {...defaultconfig}>
            {!value
              ? uploadButton
              : value?.length < fieldProps.limit
              ? uploadButton
              : null}
          </Upload>
        </ImgCrop>
      ) : (
        <Upload {...defaultconfig}>
          {!value
            ? uploadButton
            : value?.length < fieldProps.limit
            ? uploadButton
            : null}
        </Upload>
      )}
    </>
  );
}

//upload Image
function UploadImage({ item, colProps }) {
  let col = item.colProps ?? colProps;
  return (
    <Col {...col}>
      <ProForm.Item
        name={item.key ?? item.dataIndex}
        label={item.title}
        {...item.formItemProps}
        transform={(value) => {
          const key = item.key ?? item.dataIndex;
          const transvalue = value?.map((it) => {
            if (it.response) {
              return it?.response?.data?.dataList[0];
            } else {
              return it;
            }
          });
          return {
            [key]: transvalue,
          };
        }}
      >
        <UploadImg fieldProps={{ ...item?.fieldProps }} />
      </ProForm.Item>
    </Col>
  );
}

// uploadDragger
function UploadDragger({ item, colProps }) {
  return (
    <>
      <ProFormUploadDragger
        fieldProps={{
          ...item?.fieldProps,
          action: REACT_APP_URL + "/file/upload",
          onPreview: (file) => {
            let url = "";
            if (file.response) {
              url = file.response.data.dataList[0].url;
            } else if (file.url) {
              url = file.url;
            } else {
              url = file.thumbUrl;
            }
            window.open(url);
          },
        }}
        transform={(value) => {
          const key = item.key ?? item.dataIndex;
          const transvalue = value?.map((it) => {
            if (it.response) {
              return it?.response?.data?.dataList[0];
            } else {
              return it;
            }
          });
          return {
            [key]: transvalue,
          };
        }}
        formItemProps={item.formItemProps}
        name={item.key ?? item.dataIndex}
        colProps={item.colProps ?? colProps}
        label={item.title}
      />
    </>
  );
}

// editor
function Editor({ item, colProps, formRef }) {
  let col = item.colProps ?? colProps;
  let curkey = item.key ?? item.dataIndex;
  return (
    <Col {...col}>
      <ProForm.Item
        // convertValue={(value) => {
        //   return BraftEditor.createEditorState(value);
        // }}
        transform={(value) => {
          return {
            [curkey]: value.toHTML(),
          };
        }}
        name={curkey}
        label={item.title}
        {...item.formItemProps}
      >
        <EditorItem
          item={item}
          params={item.params}
          formRef={formRef}
          curkey={curkey}
        />
      </ProForm.Item>
    </Col>
  );
}

function FormList({ item, colProps, formRef }) {
  let col = item.colProps ?? colProps;
  let fields = item.columns;

  return (
    <Col {...col}>
      <ProFormList
        name={item.key ?? item.dataIndex}
        label={item.title}
        min={item.min ?? 1}
        max={item.max ?? 100}
        itemContainerRender={(doms) => {
          return <ProForm.Group>{doms}</ProForm.Group>;
        }}
        alwaysShowItemLabel={false}
      >
        {(f, index, action) => {
          return (
            <FormRender
              fields={fields}
              action={action}
              curindex={index}
              formRef={formRef}
              name={item.key ?? item.dataIndex}
            />
          );
        }}
      </ProFormList>
    </Col>
  );
}

function TableSelect({ item, value, onChange, params = {} }) {
  const rowKey = item?.rowKey ?? "id";
  const [chooses, setchooses] = useState([]); //mark 标记
  const [activetab, setactivetab] = useState(1);
  const actionRef = useRef();

  const menu = (selectedRows) => (
    <Menu
      style={{ width: 160 }}
      items={
        selectedRows.length > 0
          ? selectedRows.map((it) => ({
              key: it[rowKey],
              label: (
                <div
                  className="spread"
                  onClick={(e) => {
                    e.stopPropagation();
                    let key = it[rowKey];
                    setchooses((s) => {
                      let news = [...s];
                      if (s.includes(key)) {
                        news = news.filter((it) => {
                          return it != key;
                        });
                      } else {
                        news.push(key);
                      }
                      return news;
                    });
                  }}
                >
                  <span
                    style={{
                      color: chooses.includes(it[rowKey])
                        ? "#1890ff"
                        : "#333333",
                      transition: "all 0.4s",
                      userSelect: "none",
                    }}
                  >
                    {it[item.rowName]}
                  </span>
                  <CloseOutlined
                    onClick={(e) => {
                      e.stopPropagation();
                      let newvalue = value.filter(
                        (its) => its[rowKey] != it[rowKey]
                      );
                      onChange(newvalue);
                      setchooses((s) => {
                        let news = [...s];
                        news = news.filter((its) => {
                          return its != it[rowKey];
                        });
                        return news;
                      });
                    }}
                  />
                </div>
              ),
            }))
          : [
              {
                key: -1,
                label: "请先选择",
              },
            ]
      }
    />
  );

  useDidUpdateEffect(() => {
    onChange(null);
    actionRef?.current?.reload?.();
  }, [params]);

  const Todo = (
    <EditTable
      actionRef={actionRef}
      defaultValue={value} //调用接口合并初始值
      path={item.path}
      extraparams={params ?? {}}
      rowKey={rowKey}
      columns={item.columns}
      resizeable={false}
      alwaysShowAlert={false}
      tableAlertRender={false}
      tableAlertOptionRender={false}
      rowClassName={(record) => {
        if (chooses.includes(record[rowKey])) {
          return "lightblue";
        } else {
          return "";
        }
      }}
      rowSelection={{
        ...item.rowSelection,
        columnWidth: 44,
        preserveSelectedRowKeys: true,
        selectedRowKeys: value ? value?.map((it) => it[rowKey]) : [],
        onChange: (selectedKeys, selectedRows) => {
          const rowkeylist = value ? value?.map((it) => it[rowKey]) : [];
          const newValue = selectedRows?.map((its) => {
            if (rowkeylist.includes(its[rowKey])) {
              return value.filter((it) => it[rowKey] == its[rowKey])[0];
            } else {
              return its;
            }
          });
          onChange(newValue);
        },
      }}
      editable={{
        onValuesChange: (record) => {
          const newValue = value?.map((its) => {
            if (its[rowKey] == record[rowKey]) {
              return record;
            } else {
              return its;
            }
          });
          onChange(newValue);
        },
      }}
    />
  );

  const Done = (
    <EditTable
      value={value}
      rowKey={rowKey}
      columns={item.columns}
      resizeable={false}
      alwaysShowAlert={false}
      tableAlertRender={false}
      tableAlertOptionRender={false}
      rowClassName={(record) => {
        if (chooses.includes(record[rowKey])) {
          return "lightblue";
        } else {
          return "";
        }
      }}
      rowSelection={{
        ...item.rowSelection,
        columnWidth: 44,
        preserveSelectedRowKeys: true,
        selectedRowKeys: value ? value?.map((it) => it[rowKey]) : [],
        onChange: (selectedKeys, selectedRows) => {
          const rowkeylist = value ? value?.map((it) => it[rowKey]) : [];
          const newValue = selectedRows?.map((its) => {
            if (rowkeylist.includes(its[rowKey])) {
              return value.filter((it) => it[rowKey] == its[rowKey])[0];
            } else {
              return its;
            }
          });
          onChange(newValue);
        },
      }}
      editable={{
        onValuesChange: (record) => {
          const newValue = value?.map((its) => {
            if (its[rowKey] == record[rowKey]) {
              return record;
            } else {
              return its;
            }
          });
          onChange(newValue);
        },
      }}
    />
  );

  return (
    <div className="selecttable">
      <Tabs
        tabBarExtraContent={
          <div className="center">
            <Dropdown menu={menu(value ?? [])}>
              <a>
                已选择{value?.length ?? 0}项 <DownOutlined />
              </a>
            </Dropdown>
            <div
              className="center"
              style={{
                color: "red",
                cursor: "pointer",
                margin: "0 6px 0 16px",
              }}
              onClick={() => {
                onChange([]);
                setchooses([]);
              }}
            >
              <RedoOutlined rotate={-90} />
              清空
            </div>
          </div>
        }
        onChange={setactivetab}
        items={[
          { label: "数据选择", key: 1, children: activetab == 1 && Todo },
          {
            label: `选择结果${value?.length ?? 0}项`,
            key: 2,
            children: activetab == 2 && Done,
          },
        ]}
      />
    </div>
  );
}

function LinkSelectList({ item, colProps }) {
  let col = item.colProps ?? colProps;
  let curlinkparams = item?.linkParams ?? {}; //获取linkParams下声明的key
  return (
    <Col {...col}>
      <ProFormDependency name={Object.keys(curlinkparams)}>
        {(params) => {
          const curkey = item.key ?? item.dataIndex;
          let result = {};
          for (let key in curlinkparams) {
            let reversekey = !curlinkparams[key] ? key : curlinkparams[key];
            result[reversekey] = params[key];
          }
          return (
            <Form.Item name={curkey} label={item.title} {...item.formItemProps}>
              <TableSelect item={item} params={result} />
            </Form.Item>
          );
        }}
      </ProFormDependency>
    </Col>
  );
}

function NolinkSelectList({ item, colProps }) {
  let col = item.colProps ?? colProps;
  let curkey = item.key ?? item.dataIndex; //获取key
  return (
    <Col {...col}>
      <Form.Item name={curkey} label={item.title} {...item.formItemProps}>
        <TableSelect item={item} params={item.params} />
      </Form.Item>
    </Col>
  );
}

function FormSelectList(props) {
  let ifs = props?.item?.linkParams;
  if (ifs) {
    return <LinkSelectList {...props} />;
  } else {
    return <NolinkSelectList {...props} />;
  }
}

const FormItems = {
  Input,
  Password,
  Money,
  Textarea,
  Digit,
  DigitRange,
  Date,
  Time,
  DateTime,
  DateWeek,
  DateMonth,
  DateQuarter,
  DateYear,
  DateRange,
  TimeRange,
  DateTimeRange,
  Select,
  TreeSelect,
  Checkbox,
  Radio,
  Switch,
  Cascader,
  Rate,
  Slider,
  UploadBtn,
  UploadImage,
  UploadDragger,
  Editor,
  FormList,
  FormSelectList,
  CheckboxItem,
  RadioItem,
};

let FormRender = memo(({ fields = [], name, curindex, formRef }) => {
  return (
    <>
      {fields
        .filter((it) => it.hideInForm !== true)
        .map((item) => {
          let key = item?.valueType ? upperCase(item?.valueType) : "Input";
          let { hideInForm } = item;
          if (hideInForm && Object.keys(hideInForm)) {
            return (
              <ProFormDependency name={Object.keys(hideInForm)}>
                {(params) => {
                  let ifs = true;
                  let res = Object.keys(hideInForm).map((its) => {
                    if (Array.isArray(hideInForm[its])) {
                      return !hideInForm[its].includes(params[its]);
                    } else {
                      let vals = hideInForm[its].reverse; //取反 即不存在当前数组中的
                      return vals.indexOf(params[its]) != -1;
                    }
                  });
                  ifs = res.includes(false);
                  if (ifs) {
                    return (
                      <Col {...item.colProps}>
                        {curindex == 0 ? (
                          <p>
                            <label htmlFor="">{item.title}</label>
                            <p style={{ padding: "6px 0 0 0", margin: 0 }}>
                              <b style={{ color: "red" }}>!</b>{" "}
                              需满足条件才可以填写{item.title}
                            </p>
                          </p>
                        ) : (
                          <p style={{ padding: "4px 0 0 0", margin: 0 }}>
                            <b style={{ color: "red" }}>!</b>{" "}
                            需满足条件才可以填写{item.title}
                          </p>
                        )}
                      </Col>
                    );
                  } else {
                    return (
                      <>
                        {createElement(FormItems[key], {
                          item: item,
                          colProps: item.colProps,
                          key: item.dataIndex,
                          name: name,
                          formRef,
                          curindex,
                        })}
                      </>
                    );
                  }
                }}
              </ProFormDependency>
            );
          } else {
            return (
              <>
                {createElement(FormItems[key], {
                  item: item,
                  colProps: item.colProps,
                  key: item.dataIndex,
                  name: name,
                  formRef,
                  curindex,
                })}
              </>
            );
          }
        })}
    </>
  );
});

export default {
  Input,
  Password,
  Money,
  Textarea,
  Digit,
  DigitRange,
  Date,
  Time,
  DateTime,
  DateWeek,
  DateMonth,
  DateQuarter,
  DateYear,
  DateRange,
  TimeRange,
  DateTimeRange,
  Select,
  TreeSelect,
  Checkbox,
  Radio,
  Switch,
  Cascader,
  Rate,
  Slider,
  UploadBtn,
  UploadImage,
  UploadDragger,
  Editor,
  FormList,
  FormSelectList,
  CheckboxItem,
  RadioItem,
};