<template>
    <div class="field" :key="field.name">
        <!-- 运算符 -->
        <info-select
            :row="rule.andOr"
            :modelData="field"
        />
        <infoFormItem
            :item="rule.name"
            :config="{}"
        >
            <!-- 字段 -->
            <info-custom-select
                :row="rule.name"
                :modelData="field"
            />
        </infoFormItem>
        <infoFormItem
            :item="rule.oper"
            :config="{}"
        >
            <!-- 操作符 -->
            <info-select
                :row="rule.oper"
                :modelData="field"
            />
        </infoFormItem>
        <infoFormItem
            ref="valueItem"
            :item="rule.value"
            :config="{}"
        >
            <!-- 值 -->
            <info-input
                v-if="showFormItem === 'infoInput'"
                :row="rule.value"
                :modelData="field"
            />
            <info-select
                v-else-if="showFormItem === 'infoSelect'"
                :row="rule.value"
                :modelData="field"
            />
            <info-custom-select
                v-else-if="showFormItem === 'infoCustomSelect'"
                :row="rule.value"
                :modelData="field"
            />
            <info-cascader
                v-else-if="showFormItem === 'infoCascader'"
                :row="rule.value"
                :modelData="field"
            />
            <info-date-picker
                v-else-if="showFormItem === 'infoDatePicker'"
                :row="rule.value"
                :modelData="field"
            />
            <div
                v-else-if="showFormItem === 'infoNumberRange'"
                class="info-number-range"
            >
                <el-input
                    v-model="field.value[0]"
                    :placeholder="$t('minValue')"
                    type="number"
                />
                <span>-</span>
                <el-input
                    v-model="field.value[1]"
                    :placeholder="$t('maxValue')"
                    type="number"
                />
            </div>
        </infoFormItem>
    </div>
</template>

<script lang="ts" setup>
import { reactive, ref, computed, watch, onBeforeMount } from 'vue'
import infoFormItem from '../../infoForm/infoFormItem.vue'
import infoCustomSelect from '../../form/customSelect/index.vue'
import infoCascader from '../../form/cascader/index.vue'
import infoSelect from '../../form/select/index.vue'
import infoInput from '../../form/input/index.vue'
import infoDatePicker from '../../form/datePicker/index.vue'
import { ObjectInterface } from '../../../script'
import { conditions } from '../../../hooks/option'

const props = defineProps({
    searchList: {
        type: Array,
        default: () => {}
    },
    columnI18n: {
        type: Boolean,
        default: true
    },
    field: { // modelData
        type: Object,
        default: () => {
        }
    },
    index: { // 组内索引
        type: Number,
        default: () => {
        }
    },
    validate: { // 是否校验
        type: Boolean,
        default: true
    }
})
const emit = defineEmits(['pullSql'])
/* data */
let column:ObjectInterface = reactive({})

const validator = (rule2, value, callback) => {
    if (!props.validate) {
        return callback()
    }
    if (['EQUAL', 'NOT_EQUAL', 'IS_NULL', 'NOT_NULL'].includes(props.field.oper) && rule2.field === 'value') { // 允许为空
        return callback()
    }
    value = props.field[rule2.field]
    if (value === null || value.length === 0) { // null '' []
        callback(new Error($t('cannotBeEmpty')))
    } else {
        if (showFormItem.value === 'infoNumberRange' && rule2.field === 'value') {
            if (value.includes(NaN) || value.includes('')) {
                return callback(new Error($t('cannotBeEmpty')))
            } else if (Number(value[0]) > Number(value[1])) {
                return callback(new Error($t('inputRangeError')))
            }
        }
        callback()
    }
}
const rule = reactive({
    andOr: {
        label: '',
        model: 'andOr',
        type: 'infoSelect',
        disabled: () => props.index === 0,
        clearable: false,
        placeholder: () => 'pleaseSelectOperator',
        options: () => [{
            label: 'and',
            value: 'AND'
        }, {
            label: 'or',
            value: 'OR'
        }],
        i18n: true
    },
    name: {
        label: '',
        model: 'name',
        type: 'infoCustomSelect',
        validate: [{ validator: validator, trigger: 'change' }],
        options: () => {
            return props.searchList.map((item:any) => {
                const { label, prop, type, ...other } = item
                return {
                    label: $t(label), // props.columnI18n
                    value: prop,
                    type: type || 'string',
                    ...other
                }
            })
        },
        i18n: true,
        methods: (value, item) => {
            if (!item) {
                item = { type: 'string' }
            }
            Object.assign(column, item)
            props.field.value = ''
            props.field.oper = ''
            // 根据字段调整值所需类型
            setValueItemByName(column)
            if (['infoDatePicker'].includes(showFormItem.value)) {
                props.field.value = []
            }
        }
    },
    oper: {
        label: '',
        model: 'oper',
        type: 'infoSelect',
        placeholder: () => 'pleaseSelectOperator',
        validate: [{ validator: validator, trigger: 'change' }],
        options: () => {
            return operators.value.filter((item) => {
                return item.support.length === 0 || item.support.includes(column.type || 'string') // support:[]所有类型支持
            }).filter(item => {
                return column.queryFeature ? !['IS_NULL', 'NOT_NULL'].includes(item.value) : true
            })
        },
        i18n: true,
        methods: (value, item) => {
            // 根据字段调整值所需类型
            setValueItemByOper(value)
        }
    },
    value: { // 动态配置
        label: '',
        model: 'value',
        type: 'infoInput',
        placeholder: () => 'pleaseInput',
        validate: [{ validator: validator, trigger: 'change' }],
        disabled: () => false,
        methods: (v) => {
            // console.log(v)
        }
    }
})
const pullTimer = ref()
const valueItem = ref()

/* computed */
const operators = computed(() => { // 操作符
    // const conditions = [] // this.types.conditions
    return Object.keys(conditions).map((key) => {
        return {
            label: `${$t(conditions[key].label)}（${key}）`,
            value: key,
            support: conditions[key].support
        }
    })
})
const showFormItem = computed(() => {
    let type = 'infoInput'
    // 新版
    if (column.type === 'enum') {
        type = 'infoSelect'
        if (column.useCustom) {
            type = 'infoCustomSelect'
        }
        if (column.useCascader) {
            type = 'infoCascader'
        }
    } else if (column.type === 'date') {
        type = 'infoDatePicker'
    } else if (column.type === 'number' && ['BETWEEN', 'NOT_BETWEEN'].includes(props.field.oper)) {
        type = 'infoNumberRange'
    }
    return type
})

/* watch */
watch(
    props.field,
    (nv) => {
        clearTimeout(pullTimer.value)
        pullTimer.value = setTimeout(() => {
            const { group, type, key, queryFeature, ...field } = nv
            let valid = true
            for (let key in field) { // 校验4项
                const value = field[key]
                if (key === 'value') {
                    if (showFormItem.value === 'infoNumberRange') {
                        const res = value.map(v => {
                            return !(isNaN(v) || !v)
                        })
                        if (res.indexOf(false) >= 0) {
                            valid = false
                            break
                        }
                    } else if (!['EQUAL', 'NOT_EQUAL', 'IS_NULL', 'NOT_NULL'].includes(nv.oper)) {
                        if (value === null || value.length === 0) {
                            valid = false
                            break
                        }
                    }
                } else if (!value) {
                    valid = false
                    break
                }
            }
            valid && emit('pullSql', nv)
        }, 1000)
    },
    { deep: true }
)

onBeforeMount(() =>{
    if (props.field.name) {
        const name = props.field.queryFeature?.name || props.field.name
        const currentColumn = props.searchList.filter((item:any) => item.prop === name)[0]
        Object.assign(column, currentColumn)
        setValueItemByName(column)
    }
    if (props.field.oper) {
        $set(rule.value, 'multiple', ['IN', 'NOT_IN'].includes(props.field.oper))
        $set(rule.value, 'disabled', () => ['IS_NULL', 'NOT_NULL'].includes(props.field.oper))
    }
})

/* methods */
// 动态修改value配置
const setValueItemByName = (item) => {
    // props.field.value = ''
    // props.field.oper = ''
    rule.value = {
        label: '',
        model: 'value',
        type: 'infoInput',
        placeholder: () => 'pleaseInput',
        validate: [{ validator: validator, trigger: 'change' }],
        disabled: () => false,
        methods: (v) => {
            // console.log(v)
        }
    }
    rule.value.type = showFormItem.value
    if (item.type === 'number') {
        $set(rule.value, 'inputType', 'number')
    } else if (['infoSelect', 'infoCustomSelect', 'infoCascader'].includes(showFormItem.value)) {
        const { options, optionsLabel, optionsValue, i18n } = item
        $set(rule.value, 'options', options)
        $set(rule.value, 'optionsLabel', optionsLabel)
        $set(rule.value, 'optionsValue', optionsValue)
        $set(rule.value, 'i18n', i18n)
        $set(rule.value, 'clearable', true)
        $set(rule.value, 'collapseTags', true)
        $set(rule.value, 'placeholder', () => 'pleaseSelect')
        $set(rule.value, 'methods', (val, item) => {
            if (showFormItem.value === 'infoCascader') return // 级联选择未传出行对象，暂不做处理
            // @ts-ignore
            if (rule.value.multiple) {
                props.field.label = item.map(opt => opt[optionsLabel || 'label'])
            } else {
                props.field.label = item[optionsLabel || 'label']
            }
        })
    } else if (['infoDatePicker'].includes(showFormItem.value)) {
        // $set(rule.value, 'interval', true)
        $set(rule.value, 'format', () => 'YYYY.MM.DD')
        $set(rule.value, 'valueFormat ', () => 'x')
        $set(rule.value, 'dateType', () => 'daterange')
        // props.field.value = []
    }
    props.field.queryFeature = column.queryFeature ? {} : null
}
const setValueItemByOper = (oper) => {
    props.field.value = ''
    if (showFormItem.value === 'infoNumberRange') {
        props.field.value = [NaN, NaN]
    } else if (['infoSelect', 'infoCustomSelect', 'infoCascader'].includes(showFormItem.value)) {
        const multiple = ['IN', 'NOT_IN'].includes(oper)
        $set(rule.value, 'multiple', multiple)
        multiple && (props.field.value = [])
    }
    $set(rule.value, 'disabled', () => ['IS_NULL', 'NOT_NULL'].includes(oper))
    valueItem.value.clearValidate()
}

const $set = (...args: any) => {
    // target, propertyKey, value
    Reflect.set.apply(this, args)
}

</script>

<style lang="scss" scoped>
.field {
    display: inline-flex;
    >div,
    >:deep(.el-date-editor.el-input__wrapper) {
        width: 30%;
        box-sizing: border-box;
        margin-right: 5px;
    }
    >div:nth-child(1),
    >div:nth-child(2) {
        width: 20%;
    }
    .el-form-item {
        margin-bottom: 15px;
    }
    .info-number-range {
        display: flex;
        > span {
            padding: 0 8px;
        }
    }
    .el-date-editor--daterange {
        width: auto;
    }
    :deep(.info-cascader) {
        div.el-input {
            margin-top: -2px;
            input.ep-input__inner {
                max-height: 32px;
                overflow: hidden;
            }
        }
        div.el-cascader__tags {
            span.el-tag {
                max-width: 35%;
            }
        }
    }
}
</style>
