<script lang="ts" setup>
  import { Card } from 'ant-design-vue';
  import { nextTick, onBeforeUpdate, onUpdated } from 'vue';
  import { DataTypeEnum } from '../StructForm/config';
  import { BasicCreateFormParams } from './type';
  import { DynamicProps } from '/#/utils';
  import { Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel';
  import { BasicForm, FormProps, FormSchema, useForm } from '/@/components/Form';

  const props = withDefaults(
    defineProps<{
      inputData?: StructJSON[];
      formProps?: FormProps;
      value?: Recordable;
    }>(),
    {
      inputData: () => [] as StructJSON[],
      formProps: () => ({}),
      value: () => ({}),
    }
  );

  const emit = defineEmits(['update:value']);

  const [register, { setProps, getFieldsValue, setFieldsValue }] = useForm({
    schemas: [],
    showActionButtonGroup: false,
    layout: 'inline',
    labelWidth: 80,
    wrapperCol: { span: 12 },
    ...(props.formProps || ({} as unknown as Partial<DynamicProps<FormProps>>)),
  });

  const syncValue = (key: string, value: any) => {
    const record = getFieldsValue();
    emit('update:value', { ...record, [key]: value });
  };

  const createInputNumber = ({
    identifier,
    functionName,
    specs,
  }: BasicCreateFormParams): FormSchema => {
    const { valueRange } = specs! as Partial<Specs>;
    const { max = 2147483647, min = -2147483648 } = valueRange || {};
    return {
      field: identifier,
      label: functionName,
      component: 'InputNumber',
      rules: [
        {
          type: 'number',
          trigger: 'change',
          validator: (_rule, value) => {
            if (value < min || value > max) {
              return Promise.reject(`${functionName}取值范围在${min}~${max}之间`);
            }
            return Promise.resolve(value);
          },
        },
      ],
      componentProps: {
        max,
        min,
        // step: step,
        // formatter: (value: string) => value,
        // parser: (string: string) => {
        //   if (dataType === DataTypeEnum.IS_NUMBER_INT) {
        //     return Number(Number(string).toFixed());
        //   }
        //   return Number(string);
        // },
        onChange: (value: string) => {
          syncValue(identifier, value);
        },
      },
    } as FormSchema;
  };

  const createInput = ({ identifier, functionName, specs }: BasicCreateFormParams): FormSchema => {
    const { length = 10240 } = specs! as Partial<Specs>;
    return {
      field: identifier,
      label: functionName,
      component: 'Input',
      rules: [
        {
          type: 'string',
          trigger: 'change',
          validator: (_rule, value) => {
            if (value.length > length) {
              return Promise.reject(`${functionName}数据长度应该小于${length}`);
            }
            return Promise.resolve(value);
          },
        },
      ],
      componentProps: {
        maxLength: length,
        onChange: (value: InputEvent) => {
          syncValue(identifier, (value.target as HTMLInputElement).value);
        },
      },
    } as FormSchema;
  };

  const createSelect = ({ identifier, functionName, specs }: BasicCreateFormParams): FormSchema => {
    const { boolClose, boolOpen } = specs! as Partial<Specs>;
    return {
      field: identifier,
      label: functionName,
      component: 'Select',
      componentProps: {
        options: [
          { label: `${boolClose}-0`, value: 0 },
          { label: `${boolOpen}-0`, value: 1 },
        ],
        onChange: (value: string) => {
          syncValue(identifier, value);
        },
      },
    };
  };

  const createInputJson = ({ identifier, functionName }: BasicCreateFormParams): FormSchema => {
    return {
      field: identifier,
      label: functionName,
      component: 'InputTextArea',
      componentProps: {
        onChange: (value: InputEvent) => {
          syncValue(identifier, (value.target as HTMLInputElement).value);
        },
      },
    };
  };

  const transformToFormSchema = (inputData: StructJSON[]) => {
    const schemas: FormSchema[] = [];
    for (const item of inputData) {
      const { dataType, identifier, functionName } = item;
      const { type, specs } = dataType! || {};

      const params: BasicCreateFormParams = {
        identifier: identifier!,
        functionName: functionName!,
        dataType: dataType! as unknown as DataTypeEnum,
        specs: specs as Partial<Specs>,
      };
      if (type === DataTypeEnum.IS_NUMBER_INT || type === DataTypeEnum.IS_NUMBER_DOUBLE) {
        schemas.push(createInputNumber(params));
      }

      if (type === DataTypeEnum.IS_BOOL) {
        schemas.push(createSelect(params));
      }

      if (type === DataTypeEnum.IS_STRING) {
        schemas.push(createInput(params));
      }

      if (type === DataTypeEnum.IS_STRUCT) {
        schemas.push(createInputJson(params));
      }
    }

    return schemas;
  };

  onBeforeUpdate(() => {
    if (props.inputData && props.inputData.length) {
      const schemas = transformToFormSchema(props.inputData);
      setProps({ schemas });
    }
  });

  onUpdated(async () => {
    if (props.inputData && props.inputData.length) {
      await nextTick();
      setFieldsValue(props.value);
    }
  });
</script>

<template>
  <Card bordered class="!border-dashed !rounded-lg !border-2px">
    <!-- <Alert class="!mb-4 w-32" message="服务参数配置" type="info" /> -->
    <BasicForm class="object-model-validate-form" @register="register" />
  </Card>
</template>

<style lang="less">
  .object-model-validate-form {
    .ant-input-number {
      width: 100% !important;
    }
  }
</style>
