<template>
    <div class="super-custom-search">
        <div class="super-custom-search-fixed">
            <el-row :gutter="16" type="flex">
                <template v-if="fixedOptionList_.length">
                    <template v-for="item in fixedOptionList_.slice(0, firstLineColumnCount)">
                        <el-col
                            v-if="item.hidden !== true"
                            :key="item.prop"
                            :span="item.span ? item.span : 4"
                        >
                            <div :key="item.prop" class="fixed-search-item">
                                <template v-if="item.type === 'input'">
                                    <el-input
                                        v-model="item.value"
                                        :placeholder="`${item.placeholder ? item.placeholder : `请输入${item.title}`}`"
                                        :type="item.number ? 'number' : 'text'"
                                        clearable
                                        style="width: 100%"
                                    />
                                </template>
                                <template v-if="item.type === 'select'">
                                    <el-select
                                        v-model="item.value"
                                        :allow-create="item.allowCreate"
                                        :multiple="item.multiple"
                                        :placeholder="`${item.placeholder ? item.placeholder : `请选择${item.title}`}`"
                                        :clearable="
                                            item.clearable || item.clearable === false
                                                ? item.clearable
                                                : true
                                        "
                                        filterable
                                        style="width: 100%"
                                    >
                                        <el-option
                                            v-for="opt in item.options"
                                            :key="opt.value"
                                            :label="opt.name"
                                            :value="opt.value"
                                        ></el-option>
                                    </el-select>
                                </template>
                                <template v-if="item.type === 'date'">
                                    <el-date-picker
                                        v-model="item.value"
                                        :clearable="item.clearable"
                                        :default-time="item.dateOption.defaultTime"
                                        :end-placeholder="`${item.placeholderEnd ? item.placeholderEnd : `${item.title}结束`}`"
                                        :format="item.dateOption.format || undefined"
                                        :placeholder="item.dateOption.placeholder || `请选择${item.title}`"
                                        :start-placeholder="`${item.placeholderStart ? item.placeholderStart : `${item.title}开始`}`"
                                        :type="item.dateOption.type || 'date'"
                                        :valueFormat="item.dateOption.valueFormat || undefined"
                                        range-separator="至"
                                        style="width: 100%; box-sizing: border-box"
                                    />
                                </template>
                                <template v-if="item.type === 'cascader'">
                                    <el-cascader
                                        v-model="item.value"
                                        :options="item.options"
                                        :placeholder="`${item.placeholder ? item.placeholder : `请选择${item.title}`}`"
                                        :props="item.props"
                                        :show-all-levels="item.showAllLevels"
                                        clearable
                                        style="width: 100%"
                                    />
                                </template>
                            </div>
                        </el-col>
                    </template>
                </template>
                <slot name="fixed"></slot>
                <el-col :span="btnColumnSpan ? btnColumnSpan : 6">
                    <div class="super-search-btn-group">
                        <el-button icon="Search" type="primary" @click="handlesearch">
                            搜索
                        </el-button>
                        <el-button icon="RefreshRight" type="primary" @click="handleReset">
                            重置
                        </el-button>
                        <el-button
                            v-if="showShowAll"
                            :icon="showAll ? 'ArrowUp' : 'ArrowDown'"
                            type="primary"
                            @click="toggleShowAll"
                        >
                            {{ showAll ? '收起' : '展开' }}
                        </el-button>
                    </div>
                </el-col>
            </el-row>
            <el-row v-if="fixedOptionList_.length" :gutter="16" type="flex">
                <template v-for="item in fixedOptionList_.slice(firstLineColumnCount)">
                    <el-col
                        v-if="item.hidden !== true"
                        :key="item.prop"
                        :span="item.span ? item.span : 4"
                    >
                        <div :key="item.prop" class="fixed-search-item">
                            <template v-if="item.type === 'input'">
                                <el-input
                                    v-model="item.value"
                                    :placeholder="`${item.placeholder ? item.placeholder : `请输入${item.title}`}`"
                                    class="sharedStyles"
                                    clearable
                                />
                            </template>
                            <template v-if="item.type === 'select'">
                                <el-select
                                    v-model="item.value"
                                    :allow-create="item.allowCreate"
                                    :multiple="item.multiple"
                                    :placeholder="`${item.placeholder ? item.placeholder : `请选择${item.title}`}`"
                                    class="sharedStyles"
                                    :clearable="
                                        item.clearable || item.clearable === false
                                            ? item.clearable
                                            : true
                                    "
                                    filterable
                                >
                                    <el-option
                                        v-for="opt in item.options"
                                        :key="opt.value"
                                        :label="opt.name"
                                        :value="opt.value"
                                    ></el-option>
                                </el-select>
                            </template>
                            <template v-if="item.type === 'date'">
                                <el-date-picker
                                    v-model="item.value"
                                    :clearable="item.clearable"
                                    :default-time="item.dateOption.defaultTime || undefined"
                                    :end-placeholder="`${item.placeholderEnd ? item.placeholderEnd : `${item.title}结束`}`"
                                    :format="item.dateOption.format || undefined"
                                    :placeholder="item.dateOption.placeholder || `请选择${item.title}`"
                                    :start-placeholder="`${item.placeholderStart ? item.placeholderStart : `${item.title}开始`}`"
                                    :type="item.dateOption.type || 'date'"
                                    :valueFormat="item.dateOption.valueFormat || undefined"
                                    class="sharedStyles"
                                    range-separator="至"
                                />
                            </template>
                            <template v-if="item.type === 'cascader'">
                                <el-cascader
                                    v-model="item.value"
                                    :options="item.options"
                                    :placeholder="`${item.placeholder ? item.placeholder : `请选择${item.title}`}`"
                                    :props="item.props"
                                    :show-all-levels="item.showAllLevels"
                                    class="sharedStyles"
                                    clearable
                                />
                            </template>
                        </div>
                    </el-col>
                </template>
            </el-row>
        </div>
        <div v-if="showCustomSearch" class="super-custom-search-custom">
            <div class="add-condition-btn" @click="addCustomCondition">
                <i class="el-icon-plus"></i><span>添加条件</span>
            </div>
            <div class="custom-search-item-wrapper">
                <el-row
                    v-for="(item, index) in customConditionList"
                    :key="item.prop + '_' + index"
                    :gutter="16"
                    class="custom-search-item"
                    type="flex"
                >
                    <el-col :span="4">
                        <el-select
                            v-model="item.prop"
                            class="sharedStyles"
                            placeholder="请选择查询字段"
                            @change="handleCustomPropChange(item, index)"
                        >
                            <el-option
                                v-for="opt in customOptionList_"
                                :key="opt.prop"
                                :label="opt.title"
                                :value="opt.prop"
                            ></el-option>
                        </el-select>
                    </el-col>
                    <el-col :span="3">
                        <el-select
                            v-model="item.operation"
                            class="sharedStyles"
                            placeholder="请选择查询类型"
                        >
                            <template v-if="item.type === 'date'">
                                <el-option
                                    v-for="opt in conditionList"
                                    :key="opt.value"
                                    :label="opt.label"
                                    :value="opt.value"
                                ></el-option>
                            </template>
                            <template v-else>
                                <el-option
                                    v-for="opt in conditionList.slice(0, conditionList.length - 1)"
                                    :key="opt.value"
                                    :label="opt.label"
                                    :value="opt.value"
                                ></el-option>
                            </template>
                        </el-select>
                    </el-col>
                    <el-col :span="6">
                        <template v-if="item.type === 'input'">
                            <el-input
                                v-model="item.value"
                                :placeholder="`${item.placeholder ? item.placeholder : `请输入${item.title}`}`"
                                :type="item.number ? 'number' : 'text'"
                                class="sharedStyles"
                                clearable
                            />
                        </template>
                        <template v-if="item.type === 'select'">
                            <el-select
                                v-model="item.value"
                                :allow-create="item.allowCreate"
                                :multiple="item.multiple"
                                :placeholder="`${item.placeholder ? item.placeholder : `请选择${item.title}`}`"
                                class="sharedStyles"
                                clearable
                                filterable
                            >
                                <el-option
                                    v-for="opt in item.options"
                                    :key="opt.value"
                                    :label="opt.name"
                                    :value="opt.value"
                                ></el-option>
                            </el-select>
                        </template>
                        <template v-if="item.type === 'date'">
                            <el-date-picker
                                v-model="item.value"
                                :clearable="item.clearable"
                                :default-time="item.dateOption.defaultTime || undefined"
                                :end-placeholder="`${item.placeholderEnd ? item.placeholderEnd : `${item.title}结束`}`"
                                :format="item.dateOption.format || undefined"
                                :placeholder="item.dateOption.placeholder || `请选择${item.title}`"
                                :start-placeholder="`${item.placeholderStart ? item.placeholderStart : `${item.title}开始`}`"
                                :type="item.dateOption.type || 'date'"
                                :valueFormat="item.dateOption.valueFormat || undefined"
                                class="sharedStyles"
                                range-separator="至"
                            />
                        </template>
                        <template v-if="item.type === 'cascader'">
                            <el-cascader
                                v-model="item.value"
                                :options="item.options"
                                :placeholder="`${item.placeholder ? item.placeholder : `请选择${item.title}`}`"
                                :props="item.props"
                                :show-all-levels="item.showAllLevels"
                                class="sharedStyles"
                                clearable
                            />
                        </template>
                    </el-col>
                    <el-col :span="1">
                        <el-icon class="el-icon-remove" @click="removeCustomCondition(index)">
                            <RemoveFilled />
                        </el-icon>
                    </el-col>
                </el-row>
            </div>
        </div>
    </div>
</template>

<script setup>
import { computed, ref, watch } from 'vue'
import moment from 'moment'

const conditionList = [
    {
        label: '等于',
        value: 'EQUAL'
    },
    {
        label: '忽略大小写等于',
        value: 'EQUAL_IGNORE_CASE'
    },
    {
        label: '小于',
        value: 'LESS'
    },
    {
        label: '大于',
        value: 'GREAT'
    },
    {
        label: '小于等于',
        value: 'LESS_EQUAL'
    },
    {
        label: '大于等于',
        value: 'GREAT_EQUAL'
    },
    {
        label: '不等于',
        value: 'NOT_EQUAL'
    },
    {
        label: '类似',
        value: 'LIKE'
    },
    {
        label: '左类似',
        value: 'LEFT_LIKE'
    },
    {
        label: '右类似',
        value: 'RIGHT_LIKE'
    },
    {
        label: '为空',
        value: 'IS_NULL'
    },
    {
        label: '不为空',
        value: 'NOTNULL'
    },
    {
        label: '在集合中',
        value: 'IN'
    },
    {
        label: '介于',
        value: 'BETWEEN'
    }
]

const props = defineProps({
    firstLineColumnCount: {
        type: Number,
        default: 4
    },
    fixedOptionList: {
        type: Array,
        default: () => []
    },
    customOptionList: {
        type: Array,
        default: () => []
    },
    btnColumnSpan: {
        type: Number,
        default: 6
    },
    showCustomSearch: {
        type: Boolean,
        default: true
    },
    showShowAll: {
        type: Boolean,
        default: true
    }
})

const emit = defineEmits(['search', 'reset', 'show-all', 'clearQuery'])

const showAll = ref(false)
const fixedOptionList_ = ref([])
const customOptionList_ = ref([])
const customConditionList = ref([])

const defaultCondition = computed(() => {
    return customOptionList_.value && customOptionList_.value.length > 0
        ? { operation: 'EQUAL', ...customOptionList_.value[0] }
        : { operation: 'EQUAL' }
})

watch(
    () => props.customOptionList,
    (val) => {
        customOptionList_.value = val.map((item) => {
            const { value, ...rest } = item
            return {
                value,
                defaultValue: value,
                ...rest
            }
        })
    },
    { immediate: true, deep: true }
)

watch(
    () => props.fixedOptionList,
    (val) => {
        fixedOptionList_.value = val.map((item) => {
            const { value, ...rest } = item
            return {
                value,
                defaultValue: value,
                ...rest
            }
        })
    },
    { immediate: true, deep: true }
)

function handlesearch() {
    const searchParams = filterSearchParams(fixedOptionList_.value)
    const customParams = filterSearchParams(customConditionList.value)
    emit('search', [...searchParams, ...customParams])
}

function filterSearchParams(options) {
    return options.map((item) => {
        const { prop, value, type, number, operation, queryHandler, dateOption = {} } = item
        let value_
        if (type === 'input') {
            value_ = value
                ? number
                    ? Number(value) === NaN
                        ? ''
                        : Number(value)
                    : value.trim()
                : ''
        } else if (type === 'select' && item.multiple) {
            value_ = value.filter((v) => v)
        } else if (type === 'select') {
            value_ = value ? value : ''
        } else if (type === 'date') {
            const { type, valueFormat } = dateOption
            let tempValue = value || (type.indexOf('range') !== -1 ? '' : [])
            if (type.includes('range')) {
                if (Array.isArray(tempValue) && tempValue.length === 2) {
                    value_ = valueFormat
                        ? tempValue
                        : [
                              moment(tempValue[0]).format(valueFormat),
                              moment(tempValue[1]).format(valueFormat)
                          ]
                } else {
                    value_ = []
                }
            } else {
                if (tempValue) {
                    value_ = valueFormat ? tempValue : moment(tempValue).format(valueFormat)
                } else {
                    value_ = ''
                }
            }
        } else if (type === 'cascader') {
            value_ = value ? value : []
        }
        return {
            prop,
            operation,
            queryHandler,
            value: value_
        }
    })
}

function handleReset() {
    fixedOptionList_.value = clearOption(fixedOptionList_.value)
    customConditionList.value = clearOption(customConditionList.value)
    const searchParams = filterSearchParams(fixedOptionList_.value)
    const customParams = filterSearchParams(customConditionList.value)
    emit('reset', [...searchParams, ...customParams])
}

function clearOption(options) {
    return options.map((item) => {
        const { defaultValue, value, ...rest } = item
        return {
            defaultValue,
            value: defaultValue,
            ...rest
        }
    })
}

function toggleShowAll() {
    showAll.value = !showAll.value
    emit('show-all', showAll.value)
}

function handleCustomPropChange(item, index) {
    const { prop, type, dateOption, ...rest } = customOptionList_.value.find(
        (option) => option.prop === item.prop
    )
    let operation = 'EQUAL'
    if (type === 'date' && dateOption && dateOption.type) {
        dateOption.type.includes('range') ? (operation = 'BETWEEN') : ''
    }
    item = { prop, operation, type, dateOption, ...rest }
    customConditionList.value.splice(index, 1, item)
}

function addCustomCondition() {
    customConditionList.value.push({ operation: 'EQUAL', ...defaultCondition.value })
}

function removeCustomCondition(index) {
    const target = customConditionList.value[index]
    const removeCondition = clearOption([target])
    const targetParams = filterSearchParams(removeCondition)
    emit('clearQuery', [...targetParams])
    customConditionList.value.splice(index, 1)
}
</script>

<style lang="scss" scoped>
:deep(.sharedStyles) {
    width: 100%;
    box-sizing: border-box;
}

.super-custom-search {
    width: 100%;

    .super-search-content {
        max-height: 200px;
        overflow-y: auto;
        overflow-x: hidden;
    }

    .super-custom-search-fixed,
    .super-custom-search-custom {
        .el-row {
            width: 100%;
            align-items: center;
            flex-wrap: wrap;
        }
    }

    .super-custom-search-fixed {
        .el-col {
            margin-bottom: 16px;
        }
    }

    .super-search-btn-group {
        text-align: right;
    }

    .super-custom-search-custom {
        border-top: 1px solid var(--theme-border-search);
        min-height: 20px;
        padding: 16px 0;
        position: relative;

        .custom-search-item-wrapper {
            max-height: 156px;
            min-height: 46px;
            overflow-y: auto;
            box-sizing: border-box;
        }

        .custom-search-item ~ .custom-search-item {
            margin-top: 16px;
        }
    }

    .add-condition-btn {
        position: absolute;
        top: 16px;
        right: 16px;
        display: flex;
        justify-content: center;
        align-items: center;
        z-index: 55;
        cursor: pointer;

        i {
            font-size: 16px;
            margin-right: 5px;
            margin-top: 2px;
            color: $color-primary;
        }

        span {
            font-size: 14px;
            color: $color-primary;
        }
    }

    .add-condition-btn:hover {
        i,
        span {
            color: var(--theme-add-condition-hover);
        }
    }

    .el-icon-remove {
        cursor: pointer;
        font-size: 16px;
        color: var(--theme-remove-icon) !important;
    }

    .el-icon-remove:hover {
        color: #e5456d !important;
    }
}
</style>
