import {
  AppComponentType,
  AppFormSchema,
  AppFormProps,
} from './../../model/generator/appFormConfig';
import { ComponentType, SubFormColumn } from '/@/components/Form/src/types';
import {
  CardComponentProps,
  FormProps,
  FormSchema,
  GridComponentProps,
  TabComponentProps,
} from '/@/components/Form';
import { ComponentOptionModel, FormJson } from '/@/model/generator/codeGenerator';
import { uploadApi } from '/@/api/sys/upload';
import { camelCaseString, isValidJSON } from '/@/utils/event/design';
import { ColumnType } from '/@/components/Designer/src/types';
import { useI18n } from '/@/hooks/web/useI18n';
import { cloneDeep } from 'lodash-es';

const { t } = useI18n();
export const displayColumn = ['grid', 'form', 'divider'];
export const replaceColumn = ['select', 'radio', 'checkbox', 'cascader', 'upload'];

/**
 *
 * @param json 表单设计json
 * @param convertCamel 是否需要转换 表名和字段名
 * @returns
 */
export function buildOption(json: FormJson, convertCamel = true): FormProps {
  const { list, config, hiddenComponent } = json;
  const formSchema = buildFormScheme(list, convertCamel);
  const formProp: FormProps = {
    labelCol: config.labelCol,
    labelAlign: config.labelAlign,
    layout: config.layout,
    size: config.size,
    schemas: formSchema,
    showActionButtonGroup: false,
    buttonLocation: config.buttonLocation ? config.buttonLocation : 'center',
    actionColOptions: {
      span: 24,
    },
    showResetButton: false,
    showSubmitButton: false,
    hiddenComponent,
  };

  return formProp;
}

export function buildFormScheme(list: ComponentOptionModel[], convertCamel: boolean): FormSchema[] {
  const componentsoptions: FormSchema[] = list.map((item) => {
    if (item.type === 'divider') {
      const dividerSchema: FormSchema = {
        key: item.key,
        field: '',
        label: item.label,
        colProps: {
          span: 24,
        },
        type: item.type,
        component: 'Divider',
        componentProps: {
          dashed: false, //是否虚线
          orientation: item.options!.orientation,
          text: item.options!.defaultValue,
          isShow: item.options!.isShow,
          style: {
            marginTop: item.options!.marginTop + 'px',
            marginBottom: item.options!.marginBottom + 'px',
          },
        },
      };
      return dividerSchema;
    }

    //如果是栅格布局组件
    if (item.type === 'grid') {
      const gridSchema: FormSchema = {
        key: item.key,
        field: '',
        label: '',
        type: item.type,
        colProps: { span: 24 },
        component: buildComponentType(item.type) as ComponentType,
        children: [],
        componentProps: item.options,
      };
      item.layout?.map((el) => {
        const gridProps: GridComponentProps = {
          span: el.span,
          list: [],
        };

        gridProps.list = buildFormScheme(el.list, convertCamel);
        gridSchema.children?.push(gridProps);
      });
      return gridSchema;
    }
    //如果是表格布局组件
    if (item.type === 'table-layout') {
      const gridSchema: FormSchema = {
        key: item.key,
        field: '',
        label: '',
        type: item.type,
        colProps: { span: 24 },
        component: buildComponentType(item.type) as ComponentType,
        children: [],
        componentProps: item.options,
      };
      item.layout?.map((el) => {
        const gridProps: any = {
          list: [],
        };
        el.list.map((li) => {
          const gridChild: any = { ...li };
          gridChild.children = buildFormScheme(li.children!, convertCamel);
          gridProps.list.push(gridChild);
        });

        gridSchema.children?.push(gridProps);
      });
      return gridSchema;
    }
    //如果是子表单布局组件
    if (item.type === 'form') {
      const formSchema: FormSchema = {
        key: item.key,
        label: item.label,
        field: (convertCamel ? camelCaseString(item.bindTable) : item.bindTable) + 'List',
        type: item.type,
        component: buildComponentType(item.type) as ComponentType,
        required: true,
        colProps: { span: 24 },
      };
      const childSchamas = item.children?.map((column) => buildSubFormSchema(column, convertCamel));
      if (
        item.options?.isShowDelete ||
        (item.options?.buttonList && item.options?.buttonList.length > 0)
      ) {
        childSchamas?.push({
          title: t('操作'),
          key: 'action',
          fixed: 'right',
          width: '50px',
        });
      }

      formSchema.componentProps = {
        mainKey: (convertCamel ? camelCaseString(item.bindTable) : item.bindTable) + 'List',
        columns: childSchamas,
        ...item.options,
        rowSpan: item.options?.rowSpan
          ? convertCamel
            ? camelCaseString(item.options.rowSpan)
            : item.options.rowSpan
          : undefined,
      };
      return formSchema;
    }

    //如果是子表单一对一布局组件
    if (item.type === 'one-for-one') {
      const oneForOneSchema: FormSchema = {
        key: item.key,
        label: item.label,
        field: (convertCamel ? camelCaseString(item.bindTable) : item.bindTable) + 'List',
        type: item.type,
        component: buildComponentType(item.type) as ComponentType,
        colProps: { span: 24 },
        children: [],
        componentProps: {
          isShow: item.options?.isShow,
        },
      };

      const childSchamas = buildFormScheme(item.children!, convertCamel);
      // const childSchamas = item.children?.map((column) => buildFormScheme(column, convertCamel));

      oneForOneSchema.componentProps = {
        mainKey: (convertCamel ? camelCaseString(item.bindTable) : item.bindTable) + 'List',
        childSchemas: childSchamas,
        ...item.options,
      };

      return oneForOneSchema;
    }

    if (item.type === 'tab') {
      const tabSchema: FormSchema = {
        key: item.key,
        field: '',
        label: '',
        type: item.type,
        colProps: { span: 24 },
        component: 'Tab',
        children: [],
        componentProps: {
          tabPosition: item.options!.tabPosition ?? 'top',
          size: item.options!.tabSize ?? 'default',
          type: item.options!.type ?? 'line',
          isShow: item.options!.isShow,
          events: item.options!.events,
        },
      };

      item.layout?.map((el) => {
        const tabProps: TabComponentProps = {
          span: el.span,
          name: el.name,
          prefix: el.prefix,
          suffix: el.suffix,
          activeColor: el.activeColor,
          folderId: el.folderId,
          imageUrl: el.imageUrl,
          conFolderId: el.conFolderId,
          conImageUrl: el.conImageUrl,
          list: [],
        };

        tabProps.list = buildFormScheme(el.list, convertCamel);
        tabSchema.children?.push(tabProps);
      });
      return tabSchema;
    }

    if (item.type === 'upload') {
      const uploadSchema: FormSchema = {
        key: item.key,
        field: convertCamel ? camelCaseString(item.bindField)! : item.bindField!,
        label: item.label,
        type: item.type,
        component: buildComponentType(item.type) as ComponentType,
        colProps: {
          span: 24,
        },
        componentProps: {
          api: uploadApi,
          ...item.options,
        },
      };
      return uploadSchema;
    }

    if (item.type === 'card') {
      const tabSchema: FormSchema = {
        key: item.key,
        field: '',
        label: '',
        type: item.type,
        colProps: { span: 24 },
        component: 'Card',
        children: [],
        componentProps: {
          title: item.options!.title,
          isShow: item.options!.isShow,
          cardStyle: item.options!.cardStyle,
        },
      };

      item.layout?.map((el) => {
        const cardProps: CardComponentProps = {
          span: el.span,
          name: el.name,
          list: [],
        };

        cardProps.list = buildFormScheme(el.list, convertCamel);
        tabSchema.children?.push(cardProps);
      });
      return tabSchema;
    }

    if (item.type === 'time-range' || item.type === 'date-range') {
      const rangeSchema: FormSchema = {
        key: item.key,
        field: `${convertCamel ? camelCaseString(item.bindStartTime!) : item.bindStartTime},${
          convertCamel ? camelCaseString(item.bindEndTime!) : item.bindEndTime
        }`,
        label: item.label,
        type: item.type,
        component: buildComponentType(item.type) as ComponentType,
        componentProps: {
          ...item.options,
          style: { width: item.options!.width },
          placeholder: [item.options!.startTimePlaceholder, item.options!.endTimePlaceholder],
        },
        colProps: { span: 24 },
      };
      return rangeSchema;
    }

    if (item.type === 'picker-color') {
      const colorPickerSchema: FormSchema = {
        key: item.key,
        field: convertCamel ? camelCaseString(item.bindField)! : item.bindField,
        label: item.label,
        type: item.type,
        component: buildComponentType(item.type) as ComponentType,
        colProps: {
          span: 24,
        },
        defaultValue: item.options!.defaultValue,
        componentProps: {
          ...item.options,
          style: { 'pointer-events': item.options!.disabled ? 'none' : 'auto' },
        },
      };
      return colorPickerSchema;
    }

    if (item.type === 'button') {
      const options = cloneDeep(item.options);
      camelCaseOptionsField(options, item.type, convertCamel);
      const buttonSchema: FormSchema = {
        key: item.key,
        field: convertCamel ? camelCaseString(item.bindField)! : item.bindField,
        label: item.label,
        type: item.type,
        component: buildComponentType(item.type) as ComponentType,
        colProps: {
          span: 24,
        },
        componentProps: {
          ...options,
          width: item.options?.buttonWidth,
          height: item.options?.buttonHeight,
        },
      };
      return buttonSchema;
    }

    if (item.type === 'hiddenComponent') {
      const hiddenComponentSchema: FormSchema = {
        key: item.key,
        field: convertCamel ? camelCaseString(item.bindField)! : item.bindField!,
        label: item.label,
        type: item.type,
        component: buildComponentType(item.type) as ComponentType,
        colProps: {
          span: 24,
        },
        defaultValue: item.value,
      };
      return hiddenComponentSchema;
    }

    return buildSchema(item, convertCamel);
  });
  return componentsoptions;
}

export function buildSchema(model: ComponentOptionModel, convertCamel: boolean): FormSchema {
  const componentName = buildComponentType(model.type);
  const options = cloneDeep(model.options);
  camelCaseOptionsField(options, model.type, convertCamel);
  const schema: FormSchema = {
    key: model.key,
    field: (convertCamel ? camelCaseString(model.bindField)! : model.bindField) || '',
    label: model.label,
    type: model.type,
    component: componentName as ComponentType,
    colProps: {
      span: 24,
    },
    defaultValue: model.options?.defaultValue,
    componentProps: {
      ...options,
      style: { width: model.options?.width },
    },
  };
  return schema;
}

/**
 * 构建子表单Schema
 * @param model 当前组件配置
 * @returns
 */
export function buildSubFormSchema(
  model: ComponentOptionModel,
  convertCamel = true,
): SubFormColumn {
  if (model.type === 'upload') {
    const uploadSchema: SubFormColumn = {
      key: model.key,
      dataIndex: convertCamel ? camelCaseString(model.bindField) : model.bindField,
      title: model.label,
      componentType: buildComponentType(model.type) as ComponentType,
      componentProps: {
        api: uploadApi,
        ...model.options,
      },
    };
    return uploadSchema;
  }

  if (model.type === 'time-range' || model.type === 'date-range') {
    if (model.options && !model.options.listStyle) {
      model.options.listStyle = "return 'border: 0'";
    }
    const rangeSchema: SubFormColumn = {
      key: model.key,
      dataIndex: `${convertCamel ? camelCaseString(model.bindStartTime!) : model.bindStartTime},${
        convertCamel ? camelCaseString(model.bindEndTime!) : model.bindEndTime
      }`,
      title: model.label,
      //ellipsis: true,
      componentType: buildComponentType(model.type) as ComponentType,
      componentProps: {
        ...model.options,
        style: { width: model.options!.width },
        placeholder: [model.options!.startTimePlaceholder, model.options!.endTimePlaceholder],
      },
    };
    return rangeSchema;
  }

  if (model.type === 'picker-color') {
    const colorPickerSchema: SubFormColumn = {
      key: model.key,
      dataIndex: convertCamel ? camelCaseString(model.bindField) : model.bindField,
      title: model.label,
      componentType: buildComponentType(model.type) as ComponentType,
      defaultValue: model.options!.defaultValue,
      componentProps: {
        ...model.options,
        style: { 'pointer-events': model.options!.disabled ? 'none' : 'auto' },
      },
    };
    return colorPickerSchema;
  }

  if (model.type === 'sun-form') {
    const formSchema: SubFormColumn = {
      key: model.key,
      mainKey: (convertCamel ? camelCaseString(model.bindTable) : model.bindTable) + 'List',
      componentType: buildComponentType(model.type) as ComponentType,
    };
    const childSchamas = model.children?.map((column) => buildSubFormSchema(column, convertCamel));
    childSchamas?.push({
      title: t('操作'),
      key: 'action',
      fixed: 'right',
      width: '50px',
    });
    formSchema.componentProps = {
      mainKey: (convertCamel ? camelCaseString(model.bindTable) : model.bindTable) + 'List',
      columns: childSchamas,
      ...model.options,
      rowSpan: model.options?.rowSpan
        ? convertCamel
          ? camelCaseString(model.options.rowSpan)
          : model.options.rowSpan
        : undefined,
    };
    return formSchema;
  }
  const options = cloneDeep(model.options);
  camelCaseOptionsField(options, model.type, convertCamel);
  const formStyleComp = [
    'select',
    'associate-select',
    'organization',
    'area',
    'cascader',
    'tree-select-component',
  ];
  if (formStyleComp.includes(model.type)) {
    if (options && !options.listStyle) {
      options.listStyle = "return 'border: 0'";
    }
  }
  if (['number'].includes(model.type)) {
    if (options && !options.listStyle) {
      options.listStyle = "return 'width:100%'";
    }
  }
  const column: SubFormColumn = {
    key: model.key,
    title: model.label,
    //ellipsis: true,
    dataIndex:
      model.type == 'button'
        ? ''
        : convertCamel
        ? camelCaseString(model.bindField)
        : model.bindField,
    componentType: buildComponentType(model.type) as ComponentType,
    defaultValue: model.options!.defaultValue,
    componentProps: options,
  };

  return column;
}

/**
 * 构建子表单的card  tab  grid 组件的子级 Schema
 * TODO 暂时搁浅 先不做
 *
 * @param model 当前组件配置
 * @returns
 */
export function buildSubFormChildSchema(modelList: ComponentOptionModel[]): SubFormColumn[] {
  const childSchamas = modelList.map((item) => {
    const column: SubFormColumn = {
      title: item.label,
      dataIndex: camelCaseString(item.bindField),
      componentType: buildComponentType(item.type) as ComponentType,
      defaultValue: item.options!.defaultValue,
    };

    //如果是包含自己的组件
    if (['card', 'tab', 'grid', 'form'].includes(item.type)) {
      if (['card', 'tab', 'grid'].includes(item.type)) {
        if (item.children && item.children.length > 0) {
          column.children = buildSubFormChildSchema(item.children);
        }
      }
    }

    return column;
  });

  return childSchamas;
}

export function buildComponentType(type: string): string {
  switch (type) {
    case 'input':
      return 'Input';

    case 'password':
      return 'InputPassword';

    case 'labelComponent':
      return 'LabelComponent';

    case 'textarea':
      return 'InputTextArea';

    case 'book':
      return 'InputTextArea';

    case 'number':
      return 'InputNumber';

    case 'radio':
      return 'ApiRadioGroup';

    case 'checkbox':
      return 'ApiCheckboxGroup';

    case 'select':
      return 'XjrSelect';

    case 'cascader':
      return 'ApiCascader';

    case 'time':
      return 'TimePicker';

    case 'date':
      return 'DatePicker';

    case 'time-range':
      return 'TimeRangePicker';

    case 'date-range':
      return 'RangePicker';
    case 'rate':
      return 'Rate';

    case 'switch':
      return 'Switch';

    case 'slider':
      return 'Slider';

    case 'divider':
      return 'Divider';

    case 'upload':
      return 'Upload';

    case 'richtext-editor':
      return 'RichTextEditor';

    case 'form':
      return 'SubForm';

    case 'sun-form':
      return 'SunForm';

    case 'one-for-one':
      return 'OneForOne';

    case 'grid':
      return 'Grid';

    case 'card':
      return 'Card';

    case 'user':
      return 'User';
    case 'role':
      return 'Role';
    case 'organization':
      return 'Dept';

    case 'info':
      return 'Info';

    case 'area':
      return 'Area';

    case 'multiple-popup':
      return 'MultiplePopup';

    case 'associate-popup':
      return 'MultiplePopup';

    case 'associate-select':
      return 'AssociateSelect';

    case 'button':
      return 'Button';

    case 'computational':
      return 'Computation';

    case 'picker-color':
      return 'ColorPicker';

    case 'title':
      return 'Title';
    case 'text':
      return 'Text';
    case 'opinion':
      return 'Opinion';

    case 'image':
      return 'Image';

    case 'auto-code':
      return 'AutoCodeRule';

    case 'money-chinese':
      return 'MoneyChineseInput';

    case 'map':
      return 'SelectMap';

    case 'qrcode':
      return 'XjrQrcode';

    case 'tree-component':
      return 'TreeComponent';

    case 'tree-select-component':
      return 'TreeSelectComponent';

    case 'auto-complete':
      return 'AutoComplete';

    case 'form-view':
      return 'FormView';

    case 'iframe':
      return 'XjrIframe';

    case 'table-layout':
      return 'TableLayout';

    case 'barcode':
      return 'BarCode';

    case 'signature':
      return 'Signature';
    case 'file':
      return 'File';

    case 'custom':
      return 'CustomComponent';
    case 'modal':
      return 'XjrCustomModal';
    case 'drawer':
      return 'XjrCustomDrawer';
    case 'ai-answer':
      return 'AiAnswer';
    default:
      return 'Input';
  }
}

export function buildAppComponentType(type: string): AppComponentType {
  switch (type) {
    case 'input':
      return AppComponentType.input;

    case 'password':
      return AppComponentType.input;

    case 'textarea':
      return AppComponentType.input;

    case 'number':
      return AppComponentType.inputNumber;

    case 'radio':
      return AppComponentType.radio;

    case 'checkbox':
      return AppComponentType.checkbox;

    case 'select':
      return AppComponentType.select;

    case 'area':
    case 'cascader':
      return AppComponentType.cascader;

    case 'time':
      return AppComponentType.timeRange;

    case 'date':
      return AppComponentType.dateTime;

    case 'time-range':
      return AppComponentType.timeRange;

    case 'date-range':
      return AppComponentType.dateTimeRange;

    case 'rate':
      return AppComponentType.rate;

    case 'switch':
      return AppComponentType.switch;

    case 'slider':
      return AppComponentType.slider;

    case 'divider':
      return AppComponentType.divider;

    case 'upload':
      return AppComponentType.upload;
    case 'file':
      return AppComponentType.file;
    case 'richtext-editor':
      return AppComponentType.editor;
    case 'opinion':
      return AppComponentType.opinion;

    case 'form':
      return AppComponentType.subForm;

    case 'one-for-one':
      return AppComponentType.singleForm;

    case 'form-view':
      return AppComponentType.formView;

    case 'iframe':
      return AppComponentType.iframe;

    case 'auto-code':
      return AppComponentType.autoCode;

    case 'image':
      return AppComponentType.image;

    case 'picker-color':
      return AppComponentType.color;

    case 'qrcode':
      return AppComponentType.qrcode;
    case 'barcode':
      return AppComponentType.barcode;
    case 'title':
      return AppComponentType.title;
    case 'text':
      return AppComponentType.text;
    case 'map':
      return AppComponentType.map;

    case 'organization':
      return AppComponentType.organization;

    case 'user':
      return AppComponentType.user;
    case 'role':
      return AppComponentType.role;
    case 'computational':
      return AppComponentType.computation;

    case 'money-chinese':
      return AppComponentType.moneyChinese;

    case 'associate-select':
      return AppComponentType.associatePicker;

    case 'associate-popup':
      return AppComponentType.associatePopup;

    case 'multiple-popup':
      return AppComponentType.multiplePopup;

    case 'info':
      return AppComponentType.info;
    case 'button':
      return AppComponentType.button;
    case 'table-layout':
      return AppComponentType.tableLayout;
    case 'tree-select-component':
      return AppComponentType.TreeSelect;
    case 'tree-component':
      return AppComponentType.TreeChecked;
    case 'signature':
      return AppComponentType.signature;
    case 'modal':
      return AppComponentType.customModal;
    case 'drawer':
      return AppComponentType.customDrawer;
    case 'custom':
      return AppComponentType.customComp;
    case 'labelComponent':
      return AppComponentType.LabelComp;
    case 'ai-answer':
      return AppComponentType.aiAnswer;
    default:
      return AppComponentType.input;
  }
}

export function JavaTypeConvertTsType(type: string): ColumnType {
  switch (type) {
    case 'Integer':
      return ColumnType.NUMBER;
    case 'Long':
      return ColumnType.LONG;
    case 'Float':
      return ColumnType.NUMBER;
    case 'Double':
      return ColumnType.NUMBER;
    case 'BigDecimal':
      return ColumnType.NUMBER;
    case 'Short':
      return ColumnType.NUMBER;
    case 'Byte':
      return ColumnType.NUMBER;
    case 'Boolean':
      return ColumnType.BOOL;
    case 'LocalDateTime':
      return ColumnType.DATE;
    case 'LocalTime':
      return ColumnType.TIME;
    default:
      return ColumnType.STRING;
  }
}

/**
 * 将web端设计json 转换为 手机端所需要form
 */
export function buildAppFormProps(json: FormJson, convertCamel = true): AppFormProps {
  const { config, hiddenComponent } = json;
  let list = json.list;
  list = list.concat(hiddenComponent);
  const formSchema = buildAppFormScheme(list, convertCamel);
  const formProp: AppFormProps = {
    validateTrigger: 'submit',
    labelPosition: config.layout === 'vertical' || config.layout === 'inline' ? 'top' : 'left',
    labelWidth: 75,
    labelAlign: !config.labelAlign ? 'center' : config.labelAlign,
    errShowType: 'undertext',
    border: false,
    schemas: formSchema,
    rules: [],
  };

  return formProp;
}

export function buildAppFormScheme(
  list: ComponentOptionModel[],
  convertCamel: boolean,
): AppFormSchema[] {
  let schemas: AppFormSchema[] = [];

  for (const item of list) {
    if (item.type === 'divider') {
      const dividerSchema: AppFormSchema = {
        key: item.key,
        field: item.bindField,
        name: item.label,
        component: AppComponentType.divider,
        componentProps: {
          text: item.options!.defaultValue,
          align: item.options!.orientation,
          isShow: item.options?.isShow,
        },
      };
      schemas.push(dividerSchema);

      continue;
    }
    if (item.type === 'iframe') {
      const iframeSchema: AppFormSchema = {
        key: item.key,
        field: '',
        name: item.label,
        label: item.label,
        component: AppComponentType.iframe,
        componentProps: {
          isShow: item.options?.isShow,
        },
        url: item.options?.url,
      };
      schemas.push(iframeSchema);

      continue;
    }
    //如果是栅格布局组件或者表格布局组件 手机端没有  必须要扁平化
    if (item.type === 'grid') {
      item.layout?.map((el) => {
        schemas = schemas.concat(buildAppFormScheme(el.list, convertCamel));
      });
      continue;
    }

    if (item.type === 'table-layout') {
      const layoutSchema: AppFormSchema = {
        key: item.key,
        name: item.label,
        component: AppComponentType.tableLayout,
        componentProps: {
          isShow: item.options?.isShow || false,
        },
        layout: [],
      };

      item.layout?.map((el, index) => {
        const child = {
          name: el.name,
          value: index,
          children: [] as AppFormSchema[],
        };
        el.list?.map((chil) => {
          if (chil.children && chil.children.length > 0) {
            child.children = child.children.concat(buildAppFormScheme(chil.children, convertCamel));
          }
        });
        layoutSchema.layout?.push(child);
      });
      schemas.push(layoutSchema);
      continue;
    }
    //如果是tab组件 转换为手机端配置
    if (item.type === 'tab') {
      const tabSchema: AppFormSchema = {
        key: item.key,
        name: item.label,
        component: AppComponentType.segmented,
        layout: [],
        componentProps: {
          isShow: item.options?.isShow,
        },
      };

      item.layout?.map((el, index) => {
        const child = {
          name: el.name,
          value: index,
          children: [] as AppFormSchema[],
        };
        child.children = buildAppFormScheme(el.list, convertCamel);
        tabSchema.layout?.push(child);
      });
      schemas.push(tabSchema);
      continue;
    }

    //如果是tab组件 转换为手机端配置
    if (item.type === 'card') {
      const cardSchema: AppFormSchema = {
        key: item.key,
        name: item.options?.title || item.label,
        component: AppComponentType.collapse,
        componentProps: {
          isShow: item.options?.isShow,
        },
        layout: [],
      };

      item.layout?.map((el, index) => {
        const child = {
          name: el.name,
          value: index,
          children: [] as AppFormSchema[],
        };
        child.children = buildAppFormScheme(el.list, convertCamel);
        cardSchema.layout?.push(child);
      });
      schemas.push(cardSchema);
      continue;
    }

    //如果是子表单组件
    if (item.type === 'form' || item.type === 'sun-form' || item.type === 'one-for-one') {
      const formSchema: AppFormSchema = {
        field: (convertCamel ? camelCaseString(item.bindTable) : item.bindTable) + 'List', //字段
        key: item.key,
        name: item.label,
        component:
          item.type === 'form'
            ? AppComponentType.subForm
            : item.type === 'sun-form'
            ? AppComponentType.sunForm
            : AppComponentType.singleForm,
        columns: [],
        componentProps: {
          isShow: item.options?.isShow === undefined ? true : item.options?.isShow,
        },
      };
      if (item.options?.useSelectButton !== undefined) {
        formSchema.useSelectButton = item.options.useSelectButton;
        formSchema.buttonName = item.options.buttonName;
      }
      if (item.options?.preloadType) {
        formSchema.preloadType = item.options.preloadType;
        if (formSchema.preloadType == 'dic') {
          if (item.options.itemId) formSchema.itemId = item.options.itemId;
          if (item.options.dicOptions) {
            formSchema.associateOptions = item.options.dicOptions;
          }
        } else if (formSchema.preloadType == 'api') {
          if (item.options.apiConfig?.path)
            formSchema.apiConfig = setApiConfig(item.options.apiConfig);
          if (item.options.apiConfig?.outputParams) {
            formSchema.associateOptions = item.options.apiConfig.outputParams;
          }
        }
      }
      formSchema.columns = buildAppFormScheme(item.children!, convertCamel);
      schemas.push(formSchema);
      continue;
    }

    schemas.push(buildAppSchema(item, convertCamel));
  }

  return schemas;
}

export function buildAppSchema(model: ComponentOptionModel, convertCamel: boolean): AppFormSchema {
  const compType = buildAppComponentType(model.type);
  const params: any = {};
  let field = '';
  if (model.type == 'date-range' || model.type == 'time-range') {
    const start = convertCamel ? camelCaseString(model.bindStartTime!) : model.bindStartTime;
    const end = convertCamel ? camelCaseString(model.bindEndTime!) : model.bindEndTime;
    params.startTimeField = start;
    params.endTimeField = end;
    field = start + ',' + end;
  }
  if (model.options?.prestrainField) {
    params.prestrainField = model.options.prestrainField;
  }
  const rules: any = [];
  if (model.options?.required) {
    rules.push({
      required: model.options.required,
      errorMessage: model.label + '项必填',
    });
  }
  if (model.options?.rules && Array.isArray(model.options.rules)) {
    model.options.rules.forEach((o) => {
      rules.push({
        pattern: o.pattern,
        errorMessage: o.message,
      });
    });
  }
  const schema: AppFormSchema = {
    key: model.key,
    field: field
      ? field
      : (convertCamel ? camelCaseString(model.bindField)! : model.bindField) || '',
    label: model.options?.showLabel ? model.label : '',
    component: compType,
    defaultValue:
      model.type == 'signature'
        ? ''
        : model.type == 'hiddenComponent'
        ? model.value
        : model.type == 'number'
        ? model.options?.defaultValue > 0
          ? model.options?.defaultValue
          : 0
        : model.type == 'upload'
        ? Array.isArray(model.options?.defaultValue)
          ? ''
          : model.options?.defaultValue
        : model.options?.defaultValue || model.options?.defaultSelect,
    componentProps: buildAppComponentProps(model.type, model.options, model.key, model.bindTable),
    required: model.options?.required,
    rules: rules,
    name: model.label,
    ifShow:
      model.type == 'opinion' || model.type == 'hiddenComponent' ? false : model.options?.isShow,
    dynamicDisabled: model.options?.disabled,
    events: model.options?.events,
    ...params,
  };
  return schema;
}

export function buildAppComponentProps(type, options, key, bindTable) {
  const params: any = {};
  const defaultParams = { isShow: options.isShow };
  switch (type) {
    case 'input':
      return {
        placeholder: options.placeholder,
        prefixIcon: options.prefix,
        suffixIcon: options.suffix,
        addonBefore: options.addonBefore,
        addonAfter: options.addonAfter,
        clearable: options.allowClear,
        maxlength: options.maxlength || -1,
        addressKey: options.addressKey,
        ...defaultParams,
      };

    case 'password':
      return {
        type: 'password',
        placeholder: options.placeholder,
        prefixIcon: options.prefix,
        addonBefore: options.addonBefore,
        addonAfter: options.addonAfter,
        clearable: options.allowClear,
        maxlength: options.maxlength || -1,
        ...defaultParams,
      };

    case 'textarea':
      return {
        type: 'textarea',
        placeholder: options.placeholder,
        maxlength: options.maxlength || -1,
        showCount: options.showCount,
        autoHeight: options.autoSize,
        clearable: options.allowClear,
        ...defaultParams,
      };
    case 'number':
      return {
        min: options.min,
        placeholder: options.placeholder,
        max: options.max,
        step: options.step,
        maxlength: options.maxlength || -1,
        ...defaultParams,
      };
    case 'auto-code':
      return {
        autoCodeRule: options.autoCodeRule,
        placeholder: options.placeholder,
        prefixIcon: options.prefix,
        suffixIcon: options.suffix,
        addonBefore: options.addonBefore,
        addonAfter: options.addonAfter,
        ...defaultParams,
      };
    case 'radio':
    case 'checkbox':
    case 'select':
    case 'associate-select':
    case 'multiple-popup':
    case 'associate-popup':
      const remoteComponents = ['associate-select', 'multiple-popup', 'associate-popup'];
      if (options.datasourceType == 'staticData') {
        params.localdata = options.staticOptions;
        params.map = {
          text: options.labelField,
          value: options.valueField,
        };
      } else if (options.datasourceType == 'dic') {
        params.itemId = options.itemId;
        params.map = {
          text: options.labelField,
          value: options.valueField,
        };
        if (remoteComponents.includes(type)) {
          params.associateOptions = [...options.dicOptions];
        }
      } else if (options.datasourceType == 'api') {
        params.apiConfig = setApiConfig(options.apiConfig);
        params.map = {
          text: options.labelField,
          value: options.valueField,
        };
        if (remoteComponents.includes(type) && options.apiConfig?.outputParams) {
          params.associateOptions = [...options.apiConfig.outputParams];
        }
      }
      if (type == 'checkbox') {
        params.multiple = true;
      }
      if (type == 'radio') {
        params.mode = options.optionType;
      }
      if (type == 'select') {
        params.multiple = options.isMultiple;
        params.isSearch = options.showSearch;
      }
      return {
        placeholder: options.placeholder,
        ...defaultParams,
        ...params,
      };
    case 'tree-component':
    case 'tree-select-component':
      params.treeConfig = options.treeConfig;
      return {
        ...params,
      };
    case 'area':
    case 'cascader':
      if (type == 'area') {
        params.showFormat = 'all';
        params.split = '/';
        params.selectedConfig = 'any';
        params.type = 'area';
      } else {
        params.apiConfig = setApiConfig(options.apiConfig);
        params.showFormat = options.showFormat;
        params.split = options.separator;
        params.selectedConfig = options.selectedConfig;
      }
      return {
        placeholder: options.placeholder,
        clearIcon: options.allowClear,
        ...defaultParams,
        ...params,
      };
    case 'slider':
      return {
        step: options.step,
        min: options.min,
        max: options.max,
        ...defaultParams,
      };
    case 'switch':
      return {
        checkedText: options.checkedChildren,
        unCheckedText: options.unCheckedChildren,
        checkedColor: options.checkedColor,
        unCheckedColor: options.unCheckedColor,
        ...defaultParams,
      };
    case 'date':
      return {
        clearIcon: options.allowClear,
        placeholder: options.placeholder,
        type:
          options.format == 'YYYY-MM-DD HH:mm:ss'
            ? 'datetime'
            : options.format == 'YYYY-MM-DD'
            ? 'date'
            : 'date',
        formatType:
          options.format == 'YYYY-MM'
            ? 'month'
            : options.format == 'YYYY'
            ? 'year'
            : options.format == 'YYYY-MM-DD HH:mm:ss'
            ? 'datetime'
            : 'date',
        ...defaultParams,
      };
    case 'date-range':
      return {
        type: 'daterange',
        startPlaceholder: options.startTimePlaceholder,
        endPlaceholder: options.endTimePlaceholder,
        ...defaultParams,
      };
    case 'time':
      return {
        placeholder: options.placeholder,
        clearable: options.allowClear,
        ...defaultParams,
      };
    case 'time-range':
      return {
        startTimePlaceholder: options.startTimePlaceholder,
        endTimePlaceholder: options.endTimePlaceholder,
        isRange: true,
        clearable: options.allowClear,
        ...defaultParams,
      };
    case 'rate':
      return {
        max: options.count,
        allowHalf: options.allowHalf,
        ...defaultParams,
      };
    case 'qrcode':
      if (options.codeType == 'api') {
        params.apiConfig = setApiConfig(options.apiConfig);
      } else {
        params.text = options.defaultValue;
      }
      return {
        codeType: options.codeType,
        codekey: key,
        ...params,
        ...defaultParams,
      };
    case 'barcode':
      if (options.codeType == 'api') {
        params.apiConfig = setApiConfig(options.apiConfig);
      } else {
        params.val = options.defaultValue;
      }
      return {
        format: options.format.toLowerCase(),
        codeType: options.codeType,
        ...params,
      };
    case 'title':
      return {
        color: options.color,
        fontSize: options.fontSize,
        align: options.align,
        title: options.defaultValue,
        ...defaultParams,
      };
    case 'map':
      return {
        address: options.address,
        prefixIcon: options.prefix,
        suffixIcon: options.suffix,
        latiAndLong: options.latiAndLong,
        placeholder: options.placeholder,
        bindTable: bindTable + 'List',
        ...defaultParams,
      };
    case 'upload':
      return {
        showType: options.listType,
        fileExtname: options.accept ? options.accept.split(',') : [],
        limit: options.maxNumber,
        multiple: options.multiple,
        maxSize: options.maxSize,
        sourceType: options.sourceType ? options.sourceType.split(',') : ['album', 'camera'],
        ...defaultParams,
      };
    case 'file':
      return {
        defaultValue: options.defaultValue,
        ...defaultParams,
      };
    case 'image':
      return {
        showType: 'image',
        fileExtname: ['.png', '.jpg', '.bmp', '.jpeg', '.gif', '.svg'],
        maxSize: 10,
        isUpload: options.isUpload,
        sourceType: options.sourceType ? options.sourceType.split(',') : ['album', 'camera'],
        ...defaultParams,
      };
    case 'organization':
      return {
        placeholder: options.placeholder,
        ...defaultParams,
      };

    case 'user':
    case 'role':
      if (type == 'user') {
        params.multiple = options.multiple;
      }
      return {
        placeholder: options.placeholder,
        prefixIcon: options.prefix,
        suffixIcon: options.suffix,
        ...params,
        ...defaultParams,
      };

    case 'computational':
      return {
        placeholder: options.placeholder,
        prefixIcon: options.prefix,
        addonBefore: options.addonBefore,
        addonAfter: options.addonAfter,
        computationalConfig: options.computationalConfig,
        decimals: options.decimals,
        ...defaultParams,
      };

    case 'money-chinese':
      return {
        placeholder: options.placeholder,
        prefixIcon: options.prefix,
        suffixIcon: options.suffix,
        addonBefore: options.addonBefore,
        addonAfter: options.addonAfter,
        computationalConfig: options.computationalConfig,
        decimals: options.decimals,
        ...defaultParams,
      };
    case 'info':
      return {
        infoType: options.infoType,
        loadAgain: options.loadAgain,
        ...defaultParams,
      };
    case 'button':
      if (options.buttonType === 2) {
        params.tableColumns = options.tableColumns;
      }
      if (options.buttonType === 1 || options.buttonType === 2) {
        params.buttonType = options.buttonType;
        if (options.datasourceType == 'dic') {
          params.itemId = options.itemId;
          params.map = {
            text: options.labelField,
            value: options.valueField,
          };
          params.associateOptions = [...options.dicOptions];
        } else if (options.datasourceType == 'api') {
          params.apiConfig = setApiConfig(options.apiConfig);
          params.map = {
            text: options.labelField,
            value: options.valueField,
          };
          if (options.apiConfig?.outputParams) {
            params.associateOptions = [...options.apiConfig.outputParams];
          }
        }
      }
      return {
        width: options.buttonWidth,
        height: options.buttonHeight,
        prefixIcon: options.prefix,
        suffixIcon: options.suffix,
        name: options.name,
        ...params,
        ...defaultParams,
      };
    case 'text':
      return {
        fontFamily: options.fontFamily,
        fontSize: options.fontSize + 'px',
        fontWeight: options.fontWeight,
        color: options.color,
        fontStyle: options.fontStyle,
        align: options.align,
        ...defaultParams,
      };

    case 'signature':
      return {
        prefixIcon: options.prefix,
        suffixIcon: options.suffix,
        addonBefore: options.addonBefore,
        addonAfter: options.addonAfter,
        associateComponents: options.associateComponents,
        defaultValue: options.defaultValue,
        isCallSign: options.isCallSign,
        signValueType: options.signValueType,
        ...params,
      };
    case 'modal':
    case 'drawer':
      return {
        innerParams: options.innerParams,
        outParams: options.outParams,
        bindModal: options.bindModal,
        ...params,
      };
    case 'labelComponent':
      if (options.datasourceType == 'dic') {
        params.itemId = options.itemId;
        params.map = 'name';
      } else if (options.datasourceType == 'api') {
        params.apiConfig = setApiConfig(options.apiConfig);
        params.map = 'label';
      }
      return {
        placeholder: options.placeholder,
        styleConfig: options.styleConfig,
        ...params,
      };
    default:
      return { ...defaultParams };
  }
}
export function setApiConfig(config) {
  const data: any = {};
  data.method = config.method;
  data.path = config.path;
  data.requestParamsConfigs = [];
  data.requestHeaderConfigs = [];
  data.requestBodyConfigs = [];
  if (config.apiParams) {
    config.apiParams.forEach((o) => {
      if (o.key == 1 && o.tableInfo?.length) {
        o.tableInfo.forEach((element) => {
          data.requestParamsConfigs.push({
            name: element.name, //API入参名称
            dataType: element.dataType, //API入参类型
            assignmentType: element.bindType, //赋值类型
            value: element.value, //值
            config: '', //赋值配置
          });
        });
      } else if (o.key == 2 && o.tableInfo?.length) {
        o.tableInfo.forEach((element) => {
          data.requestHeaderConfigs.push({
            name: element.name, //API入参名称
            dataType: element.dataType, //API入参类型
            assignmentType: element.bindType, //赋值类型
            value: element.value, //值
            config: '', //赋值配置
          });
        });
      } else if (o.key == 3 && o.tableInfo?.length) {
        o.tableInfo.forEach((element) => {
          data.requestBodyConfigs.push({
            name: element.name, //API入参名称
            dataType: element.dataType, //API入参类型
            assignmentType: element.bindType, //赋值类型
            value: element.value, //值
            config: '', //赋值配置
          });
        });
      }
    });
  }

  return data;
}

export function camelCaseOptionsField(options, type, convertCamel) {
  if (convertCamel) {
    if (options.dicOptions && options.dicOptions.length > 0) {
      options.dicOptions.forEach((o) => {
        o.bindField = camelCaseString(o.bindField);
      });
    }
    if (options.tableColumns && options.tableColumns.length > 0) {
      options.tableColumns.forEach((o) => {
        o.bindField = camelCaseString(o.bindField);
        o.bindTable = camelCaseString(o.bindTable);
      });
    }
    if (options.apiConfig) {
      camelCaseApiConfig(options.apiConfig);
    }
    if (options.computationalConfig?.length > 0) {
      options.computationalConfig.forEach((o) => {
        o.bindField = camelCaseString(o.bindField);
        o.bindTable = camelCaseString(o.bindTable);
      });
    }
    if (options.address && type == 'map') {
      options.address = camelCaseString(options.address);
    }
    if (options.latiAndLong && type == 'map') {
      options.latiAndLong = camelCaseString(options.latiAndLong);
    }
    if (options.rowSpan && type == 'form-view') {
      options.rowSpan = camelCaseString(options.rowSpan);
    }
    if (type == 'modal' || type == 'drawer') {
      options.innerParams.forEach((o) => {
        if (o.type == 'api') {
          camelCaseApiConfig(o.apiConfig);
        } else if (o.type == 'form') {
          o.value = camelCaseTableField(o.value);
        }
      });
      options.outParams.forEach((o) => {
        o.mainComponent = camelCaseTableField(o.mainComponent);
      });
    }
  }
}
function camelCaseTableField(json) {
  const comp = isValidJSON(json);
  if (comp && comp.table) {
    comp.table = camelCaseString(comp.table);
  }
  if (comp && comp.field) {
    comp.field = camelCaseString(comp.field);
  }
  json = JSON.stringify(comp);
  return json;
}
function camelCaseApiConfig(apiConfig) {
  if (apiConfig.apiParams?.length > 0) {
    apiConfig.apiParams.forEach((o) => {
      if (o.tableInfo?.length > 0) {
        o.tableInfo.forEach((x) => {
          if (x.bindType == 'data') {
            const paramsArr = x.value.split('-');
            if (paramsArr[0] === '3') return;
            const val = isValidJSON(x.value);
            if (val && val.bindTable) {
              val.bindTable = camelCaseString(val.bindTable);
            }
            if (val && val.bindField) {
              val.bindField = camelCaseString(val.bindField);
            }
            x.value = JSON.stringify(val);
          }
        });
      }
    });
  }
  if (apiConfig.outputParams?.length > 0) {
    apiConfig.outputParams.forEach((o) => {
      o.bindField = camelCaseString(o.bindField);
    });
  }
}
