<template>
  <div>
    <!--如果是grid 组件 需要新增grid布局包裹-->
    <template v-if="schema.component.includes('Grid')">
      <Row
        type="flex"
        :gutter="(schema.componentProps as any ).gutter ?? 0"
        :justify="(schema.componentProps as any ).justify"
        :align="(schema.componentProps as any ).align"
        v-show="getIsShow(schema)"
      >
        <Col v-for="(col, colIndex) in schema.children" :key="colIndex" :span="col.span">
          <template v-for="childSchema in col.list" :key="childSchema.field">
            <OneForOneItem
              v-if="showComponent(childSchema)"
              :refreshFieldObj="refreshFieldObj"
              :form-api="formApi"
              :schema="childSchema"
              :main-key="mainKey"
              :isWorkFlow="isWorkFlow"
              v-model:value="formModel![mainKey!][0][childSchema.field]"
            />
          </template>
        </Col>
      </Row>
    </template>
    <!--如果是tab 组件 需要新增tab组件包裹-->
    <template v-else-if="schema.component.includes('Tab')">
      <Tabs
        v-model:activeKey="activeKey"
        :tabPosition="(schema.componentProps as any ).tabPosition"
        :type="(schema.componentProps as any ).type"
        :size="(schema.componentProps as any ).tabSize"
        v-show="getIsShow(schema)"
      >
        <TabPane
          v-for="(tab, tabIndex) in schema.children"
          :tab="tab.name"
          :forceRender="true"
          :key="tabIndex"
        >
          <template v-for="childSchema in tab.list" :key="childSchema.field">
            <OneForOneItem
              v-if="showComponent(childSchema)"
              :refreshFieldObj="refreshFieldObj"
              :form-api="formApi"
              :schema="childSchema"
              :main-key="mainKey"
              :isWorkFlow="isWorkFlow"
              v-model:value="formModel![mainKey!][0][childSchema.field]"
            />
          </template>
        </TabPane>
      </Tabs>
    </template>
    <!--如果是子表单 组件 需要v-model:value="表单对象[字段名]"-->
    <!-- <template v-else-if="schema.component.includes('Form')">
      <FormItem
        :key="schema.key"
        :name="schema.field"
        :label="getComponentsProps.showLabel ? schema.label : ''"
        :label-col="labelCol"
        :labelAlign="formProps?.labelAlign"
        :wrapperCol="itemLabelWidthProp.wrapperCol"
        v-if="getShow(schema)"
      >
        <component
          :disabled="getDisable"
          :is="componentMap.get(schema.component)"
          :size="formProps?.size"
          v-bind="schema.componentProps"
          v-model:value="formModel![mainKey!][0][schema.field]"
        />
      </FormItem>
    </template> -->
    <!--如果是子表单 组件 需要v-model:value="表单对象[字段名]"-->
    <!-- <template v-else-if="schema.component.includes('OneForOne')">
      <FormItem
        :key="schema.key"
        :name="schema.field"
        :label="getComponentsProps.showLabel ? schema.label : ''"
        :label-col="labelCol"
        :labelAlign="formProps?.labelAlign"
        :wrapperCol="itemLabelWidthProp.wrapperCol"
        v-if="getShow(schema)"
      >
        <component
          :disabled="getDisable"
          :refreshFieldObj="refreshFieldObj"
          :is="componentMap.get(schema.component)"
          :size="formProps?.size"
          v-bind="schema.componentProps"
          v-model:value="formModel![mainKey!][0][schema.field]"
        />
      </FormItem>
    </template> -->
    <!--如果是时间区间 组件 需要v-model:startField="表单对象[字段名]" v-model:endField="表单对象[字段名]"-->
    <template v-else-if="schema.component.includes('Range')">
      <FormItem
        :key="schema.key"
        :name="[mainKey, 0, schema.field]"
        :label="getComponentsProps.showLabel ? schema.label : ''"
        :label-col="labelCol"
        :wrapperCol="itemLabelWidthProp.wrapperCol"
        :validateTrigger="['blur', 'change']"
        :rules="rules"
        v-if="getShow(schema)"
        v-show="getIsShow(schema)"
      >
        <component
          :disabled="getDisable"
          :is="componentMap.get(schema.component)"
          :size="formProps?.size"
          v-bind="schema.componentProps"
          v-model:startField="schema.field.split(',')[0]"
          v-model:endField="schema.field.split(',')[1]"
          :mainKey="mainKey"
          :tableIndex="0"
          v-model:value="formModel![mainKey!][0][schema.field]"
          v-model:record="formModel![mainKey!][0]"
        />
      </FormItem>
      <!-- 因为Range会变为 开始时间 和 结束时间 2个属性给与表单数据 所以需要2个隐藏框绑定  starTime  和 endTime -->
      <FormItem
        :key="schema.key"
        v-show="false"
        :name="schema.field.split(',')[0]"
        :label="getComponentsProps.showLabel ? schema.label : ''"
      >
        <input type="hidden" />
      </FormItem>
      <FormItem
        :key="schema.key"
        v-show="false"
        :name="schema.field.split(',')[1]"
        :label="getComponentsProps.showLabel ? schema.label : ''"
      >
        <input type="hidden" />
      </FormItem>
    </template>
    <!--如果checked  或者 switch组件 需要v-model:checked="表单对象[字段名]" "-->
    <template v-else-if="checkedValueComponents.includes(schema.component)">
      <FormItem
        :key="schema.key"
        :name="schema.field"
        :label="getComponentsProps.showLabel ? schema.label : ''"
        :label-col="labelCol"
        :wrapperCol="itemLabelWidthProp.wrapperCol"
        :rules="rules"
        v-if="getShow(schema)"
        v-show="getIsShow(schema)"
      >
        <component
          :key="refreshFieldObj[schema.field]"
          :is="componentMap.get(schema.component)"
          :disabled="getDisable"
          :size="formProps?.size"
          v-bind="getComponentsProps"
          v-model:checked="formModel![mainKey!][0][schema.field]"
        />
      </FormItem>
    </template>
    <!--如果是card 组件 需要新增card组件包裹-->
    <template v-else-if="schema.component.includes('Card')">
      <CollapseContainer
        :title="(schema.componentProps as any ).title"
        :bordered="false"
        :hasLeftBorder="true"
        v-show="getIsShow(schema)"
      >
        <template v-for="childSchema  in schema.children![0].list" :key="childSchema.field">
          <OneForOneItem
            v-if="showComponent(childSchema)"
            :refreshFieldObj="refreshFieldObj"
            :form-api="formApi"
            :schema="childSchema"
            :main-key="mainKey"
            :isWorkFlow="isWorkFlow"
            v-model:value="formModel![mainKey!][0][childSchema.field]"
          />
        </template>
      </CollapseContainer>
    </template>
    <!--如果是 分割线 组件 需要新增divider组件包裹-->
    <template v-else-if="schema.component.includes('Divider')">
      <FormItem v-show="getIsShow(schema)">
        <Divider v-bind="getComponentsProps"> {{ getComponentsProps.text }}</Divider>
      </FormItem>
    </template>
    <!--如果是 意见簿 组件 需要使用defaultValue直接赋值 -->
    <template v-else-if="schema.component.includes('Opinion')">
      <FormItem
        v-if="getShow(schema)"
        v-show="getIsShow(schema)"
        :key="schema.key"
        :name="schema.field"
        :label="getComponentsProps.showLabel ? schema.label : ''"
        :label-col="labelCol"
        :wrapperCol="itemLabelWidthProp.wrapperCol"
        :rules="rules"
        :validateTrigger="['blur', 'change']"
      >
        <component
          :is="componentMap.get(schema.component)"
          :key="refreshFieldObj[schema.field]"
          :disabled="getDisable"
          :size="formProps?.size"
          v-bind="getComponentsProps"
          :value="schema.defaultValue"
        />
      </FormItem>
    </template>
    <template v-else-if="schema.component.includes('Slot')">
      <FormItem
        v-if="getShow(schema)"
        v-show="getIsShow(schema)"
        :key="schema.key"
        :name="[mainKey!, 0, schema.field]"
        :label="getComponentsProps.showLabel ? schema.label : ''"
        :label-col="labelCol"
        :wrapperCol="itemLabelWidthProp.wrapperCol"
        :rules="rules"
        :validateTrigger="['blur', 'change']"
      >
        <component
          :is="props.slots![schema.slot!]"
          :key="refreshFieldObj[schema.field]"
          :disabled="getDisable"
          :size="formProps?.size"
          v-bind="getComponentsProps"
          :index="0"
          :mainKey="mainKey"
          v-model:value="formModel![mainKey!][0][schema.field]"
          :formModel="formModel"
          :field="schema.field"
        />
      </FormItem>
    </template>
    <template v-else>
      <FormItem
        v-if="getShow(schema)"
        v-show="getIsShow(schema)"
        :key="schema.key"
        :name="[mainKey!, 0, schema.field]"
        :label="getComponentsProps.showLabel ? schema.label : ''"
        :label-col="labelCol"
        :wrapperCol="itemLabelWidthProp.wrapperCol"
        :rules="rules"
        :validateTrigger="['blur', 'change']"
      >
        <component
          :is="componentMap.get(schema.component)"
          :key="refreshFieldObj[schema.field]"
          :disabled="getDisable"
          :size="formProps?.size"
          v-bind="getComponentsProps"
          :index="0"
          :mainKey="mainKey"
          :isView="isView"
          v-model:value="formModel![mainKey!][0][schema.field]"
        />
      </FormItem>
    </template>
  </div>
</template>
<script lang="ts" setup>
  import { Form, Col, Row, Tabs, TabPane, Divider } from 'ant-design-vue';
  import { isBoolean, isFunction, upperFirst, cloneDeep } from 'lodash-es';
  import { computed, onMounted, ref, unref, inject, Ref, watch } from 'vue';
  import { componentMap } from '/@/components/Form/src/componentMap';
  import { checkedValueComponents } from '/@/components/Form/src/helper';
  import { useItemLabelWidth } from '/@/components/Form/src/hooks/useLabelWidth';
  import { FormActionType, FormProps, FormSchema } from '/@/components/Form/src/types/form';
  import { CollapseContainer } from '/@/components/Container';
  import {
    noShowWorkFlowComponents,
    noShowGenerateComponents,
  } from '/@/components/Form/src/helper';
  import { useMessage } from '/@/hooks/web/useMessage';
  const FormItem = Form.Item;

  const props = defineProps({
    // 表单配置规则
    schema: {
      type: Object as PropType<FormSchema>,
      default: () => {},
    },
    value: [Object, String, Number, Boolean, Array],
    formApi: {
      type: Object as PropType<FormActionType>,
    },
    mainKey: {
      type: String,
      required: true,
    },
    //刷新api使用
    refreshFieldObj: {
      type: Object,
      default: () => {},
    },
    //是否是工作流
    isWorkFlow: {
      type: Boolean,
      default: false,
    },
    //插槽节点
    slots: [Object, Array],
    isView: Boolean,
  });

  const formModel = inject<Recordable>('formModel');
  const formProps = inject<Ref<FormProps>>('formProps');

  const activeKey = ref<string>();
  const { notification } = useMessage();
  const getSchema = computed(() => {
    return props.schema as FormSchema;
  });

  const getDisable = computed(() => {
    const { disabled: globDisabled } = formProps!.value;
    const { dynamicDisabled } = getSchema.value;
    const { disabled: itemDisabled = false } = unref(getComponentsProps);
    let disabled = !!globDisabled || itemDisabled;
    if (isBoolean(dynamicDisabled)) {
      disabled = dynamicDisabled;
    }
    if (isFunction(dynamicDisabled)) {
      disabled = dynamicDisabled({
        values: formModel![getSchema.value.field],
        model: formModel!,
        schema: unref(getSchema),
        field: unref(getSchema).field,
      });
    }
    return disabled;
  });

  const getComponentsProps = computed(() => {
    let { componentProps = {} } = props.schema;
    if (isFunction(componentProps)) {
      componentProps =
        componentProps({ schema: props.schema, formModel, formActionType: props.formApi }) ?? {};
    } else {
      if (componentProps['events']) {
        for (const eventKey in componentProps['events']) {
          try {
            const event = new Function(
              'schema',
              'formModel',
              'formActionType',
              `${componentProps['events'][eventKey]}`,
            );
            componentProps['on' + upperFirst(eventKey)] = function () {
              event(props.schema, formModel, props.formApi);
            };
          } catch (error) {
            console.log('error', error);
            notification.error({
              message: 'Tip',
              description: '触发事件填写有误！',
            });
          }
        }
      }
    }
    if (isBoolean(props.schema.dynamicDisabled)) {
      componentProps['disabled'] = props.schema.dynamicDisabled;
    }
    if (isBoolean(props.schema.required)) {
      componentProps['required'] = props.schema.required;
    }

    return componentProps as Recordable;
  });

  const labelCol = computed(() => {
    return unref(getComponentsProps).span
      ? { span: unref(getComponentsProps).span }
      : unref(itemLabelWidthProp).labelCol;
  });

  const rules = computed(() => {
    const requiredRule = {
      required: unref(getComponentsProps).required || false,
      message: `${props.schema.label}是必填项`,
    };
    const rulesList = cloneDeep(unref(getComponentsProps).rules);
    if (!rulesList) return [requiredRule];
    rulesList?.map((item) => (item.pattern = eval(item.pattern)));
    return [...rulesList, requiredRule];
  });

  //根据labelwidth 生成labelCol
  const itemLabelWidthProp = useItemLabelWidth(getSchema, formProps!);
  watch(
    () => formModel,
    () => {
      //填值以后需要手动校验的组件
      const validateComponents = ['User', 'RichTextEditor', 'Upload', 'SelectMap'];
      if (validateComponents.includes(props.schema.component) && formModel![props.schema.field]) {
        setTimeout(() => {
          props.formApi?.validateFields([props.schema.field]);
        }, 100);
      }
    },
    {
      deep: true,
      immediate: true,
    },
  );
  onMounted(() => {
    console.log('onMounted');
    // if (
    //   staticDataComponents.includes(props.schema.component) &&
    //   (props.schema.componentProps as any)?.datasourceType === 'staticData'
    // ) {
    //   let { defaultSelect } = props.schema.componentProps as any;
    //   emit('update:value', defaultSelect);
    //   console.log('update:value1', defaultSelect);
    // } else {
    //   let { defaultValue } = props.schema;
    //   if (!!props.schema.field && !noDefaultValueComponents.includes(props.schema.component)) {
    //     console.log('update:value', props.schema.component === 'SubForm' ? [] : defaultValue);
    //     emit('update:value', defaultValue);
    //   }
    // }
  });

  function showComponent(schema) {
    return props.isWorkFlow
      ? !noShowWorkFlowComponents.includes(schema.type)
      : !noShowGenerateComponents.includes(schema.type);
  }
  function getShow(schema: FormSchema): boolean {
    const { show } = schema;
    let isIfShow = true;

    if (isBoolean(show)) {
      isIfShow = show;
    }
    return isIfShow;
  }

  function getIsShow(schema: FormSchema): boolean {
    const { componentProps } = schema as any;
    let show = true;
    if (isBoolean(componentProps?.isShow)) {
      show = componentProps?.isShow;
    }
    return show;
  }
</script>
<style lang="less" scoped>
  :deep(.ant-form-item-label > label) {
    white-space: normal;
    display: inline;
    line-height: 28px;
  }
</style>
