<template>
  <Form :layout="'vertical'" ref="propertyFormRef" :model="propertyModelRef">
    <Row :gutter="24">
      <Col :span="12">
        <FormItem name="properties" label="设置属性" :rules="[{ required: true, message: '请选择设置属性' }]">
          <Select showSearch placeholder="请选择属性" v-model:value="propertyModelRef.properties" @change="onChange">
            <SelectOption
              v-for="item in (metadata?.properties || [])?.filter((i) => i?.expands?.type?.includes('write')) || []"
              :value="item?.id"
              :key="item?.id"
              >{{ item?.name }}</SelectOption
            >
          </Select>
        </FormItem>
      </Col>
      <Col :span="12" v-if="propertyModelRef.properties">
        <FormItem name="propertiesValue" label="属性值" :rules="[{ required: true, message: '请选择' }]">
          <ParamsDropdown
            :options="handleOptions"
            :tabsOptions="tabOptions"
            :metricOptions="upperOptions"
            v-model:value="propertyModelRef.propertiesValue"
            v-model:source="propertyModelRef.source"
            @select="onValueChange"
            valueName="id"
          >
            <template #default="{ label }">
              <Input readonly :value="label" placeholder="请选择" />
            </template>
          </ParamsDropdown>
        </FormItem>
      </Col>
    </Row>
  </Form>
</template>

<script lang="ts" setup>
  import { cloneDeep, isObject } from 'lodash-es';
  import ParamsDropdown from '../../../components/ParamsDropdown';
  import { handleParamsData } from './index';
  import { computed, reactive, ref, watch } from 'vue';
  // @ts-ignore
  import { Col, Form, FormItem, Row, Select, SelectOption, Input } from 'linker-ui-components';

  const props = defineProps({
    value: {
      type: Object,
      default: () => {}
    },
    metadata: {
      type: Object,
      default: () => {
        return {
          properties: []
        };
      }
    },
    builtInList: {
      type: Array,
      default: () => []
    }
  });

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

  const propertyFormRef = ref();

  const propertyModelRef = reactive({
    properties: undefined,
    propertiesValue: undefined,
    source: 'fixed'
  });

  const getType = computed(() => {
    return props.metadata.properties.find((item: any) => item.id === propertyModelRef.properties);
  });

  const tabOptions = computed(() => {
    return [
      {
        label: '手动输入',
        component: getType.value?.valueType?.type,
        key: 'fixed'
      },
      {
        label: '内置参数',
        component: 'tree',
        key: 'upper'
      }
    ];
  });

  const filterParamsData = (type?: string, data?: any[]): any[] => {
    if (type && data) {
      const list = data.filter((item) => {
        if (item.children) {
          const _children = filterParamsData(type, item.children);
          item.children = _children;
          return !!_children.length;
        } else if (item.type === type) {
          return true;
        }
        return false;
      });
      return handleParamsData(list);
    }
    return data || [];
  };

  const upperOptions = computed(() => {
    return filterParamsData(getType.value?.valueType?.type, cloneDeep(props?.builtInList));
  });

  const handleOptions = computed(() => {
    const _item = getType.value?.valueType;
    const _type = _item?.type;
    if (_type === 'boolean') {
      return [
        {
          label: _item.trueText || true,
          name: _item.trueText || true,
          value: _item.trueValue || true,
          id: String(_item.trueValue || true)
        },
        {
          label: _item.falseText || false,
          name: _item.falseText || false,
          value: _item.falseValue || false,
          id: String(_item.falseValue || false)
        }
      ];
    }
    if (_type === 'enum') {
      return _item?.elements.map((i: any) => {
        return {
          label: i.text,
          name: i.text,
          value: i.value,
          id: i.value
        };
      });
    }
    return [];
  });

  const onChange = () => {
    propertyModelRef.propertiesValue = undefined;
    propertyModelRef.source = 'fixed';
    emit('update:value', {
      [`${propertyModelRef.properties}`]: {
        value: propertyModelRef?.propertiesValue,
        source: propertyModelRef?.source
      }
    });
  };

  const onValueChange = (val: any, label: string) => {
    const optionColumn = isObject(val) && (val as any).metadata ? [(val as any).column] : [];

    const objectValue: any = {
      value: propertyModelRef?.propertiesValue,
      source: propertyModelRef?.source
    };

    if (propertyModelRef?.source === 'upper') {
      objectValue.upperKey = propertyModelRef?.propertiesValue;
    }

    const obj = {
      [`${propertyModelRef.properties}`]: objectValue
    };
    emit('update:value', obj);
    emit('change', label || val, optionColumn);
  };

  watch(
    () => props.value,
    (newVal) => {
      if (newVal) {
        const _keys = Object.keys(newVal)?.[0];
        if (_keys) {
          propertyModelRef.properties = _keys as any;
          // @ts-ignore
          propertyModelRef.propertiesValue = newVal[_keys]?.value;
          // @ts-ignore
          propertyModelRef.source = newVal[_keys]?.source;
        }
      }
    },
    { deep: true, immediate: true }
  );

  const onSave = () => {
    return new Promise((resolve, reject) => {
      propertyFormRef.value
        .validate()
        .then(() => {
          resolve(true);
        })
        .catch((err: any) => {
          reject(err);
        });
    });
  };

  defineExpose({ onSave });
</script>
