<script setup>
import { computed, nextTick, reactive, ref, watchEffect } from 'vue'
import useDialog from 'stores/dialog'
import { isEmpty, map, size } from 'lodash'
import useBrowserStore from 'stores/browser.js'
import { decodeRedisKey } from '@/utils/key_convert.js'

const deleteForm = reactive({
    server: '',
    db: 0,
    key: '',
    showAffected: false,
    loadingAffected: false,
    affectedKeys: [],
    async: true,
    direct: false,
})

const dialogStore = useDialog()
const browserStore = useBrowserStore()

watchEffect(() => {
    if (dialogStore.deleteKeyDialogVisible) {
        const { server, db, key } = dialogStore.deleteKeyParam
        deleteForm.server = server
        deleteForm.db = db
        deleteForm.key = key
        deleteForm.loadingAffected = false
        // deleteForm.async = true
        loading.value = false
        deleting.value = false
        if (key instanceof Array) {
            deleteForm.showAffected = true
            deleteForm.affectedKeys = key
        } else {
            deleteForm.showAffected = false
            deleteForm.affectedKeys = []
        }
    }
})

const loading = ref(false)
const deleting = ref(false)
const scanAffectedKey = async () => {
    try {
        loading.value = true
        deleteForm.loadingAffected = true
        const { keys = [] } = await browserStore.scanKeys({
            server: deleteForm.server,
            db: deleteForm.db,
            match: deleteForm.key,
            loadType: 2,
        })
        deleteForm.affectedKeys = keys || []
        deleteForm.showAffected = true
    } finally {
        deleteForm.loadingAffected = false
        loading.value = false
    }
}

const resetAffected = () => {
    deleteForm.showAffected = false
    deleteForm.affectedKeys = []
}

const keyLines = computed(() => {
    return map(deleteForm.affectedKeys, (k) => decodeRedisKey(k))
})

const onConfirmDelete = async () => {
    try {
        deleting.value = true
        const { server, db, key, affectedKeys } = deleteForm
        await nextTick()
        browserStore.deleteKeys(server, db, affectedKeys).catch((e) => {})
    } catch (e) {
        $message.error(e.message)
        return
    } finally {
        deleting.value = false
    }
    dialogStore.closeDeleteKeyDialog()
}

const onConfirmDirectDelete = async () => {
    try {
        deleting.value = true
        const { server, db, key } = deleteForm
        await nextTick()
        browserStore.deleteByPattern(server, db, key).catch((e) => {})
    } catch (e) {
        $message.error(e.message)
        return
    } finally {
        deleting.value = false
    }
    dialogStore.closeDeleteKeyDialog()
}

const onClose = () => {
    dialogStore.closeDeleteKeyDialog()
}
</script>

<template>
    <n-modal
        v-model:show="dialogStore.deleteKeyDialogVisible"
        :closable="false"
        :mask-closable="false"
        :show-icon="false"
        :title="$t('interface.batch_delete_key')"
        close-on-esc
        preset="dialog"
        transform-origin="center"
        @esc="onClose">
        <n-spin :show="loading">
            <n-form :model="deleteForm" :show-require-mark="false" label-placement="top">
                <n-grid :x-gap="10">
                    <n-form-item-gi :label="$t('dialogue.key.server')" :span="12">
                        <n-input :autofocus="false" :value="deleteForm.server" readonly />
                    </n-form-item-gi>
                    <n-form-item-gi :label="$t('dialogue.key.db_index')" :span="12">
                        <n-input :autofocus="false" :value="deleteForm.db.toString()" readonly />
                    </n-form-item-gi>
                </n-grid>
                <n-form-item
                    v-if="!(deleteForm.key instanceof Array)"
                    :label="$t('dialogue.key.key_expression')"
                    required>
                    <n-input v-model:value="deleteForm.key" placeholder="" @input="resetAffected" />
                </n-form-item>
                <n-checkbox v-if="!deleteForm.showAffected" v-model:checked="deleteForm.direct">
                    {{ $t('dialogue.key.direct_delete') }}
                </n-checkbox>
                <n-card
                    v-if="deleteForm.showAffected"
                    :title="$t('dialogue.key.affected_key') + `(${size(deleteForm.affectedKeys)})`"
                    embedded
                    size="small">
                    <n-skeleton v-if="deleteForm.loadingAffected" :repeat="10" text />
                    <n-virtual-list v-else :item-size="25" :items="keyLines" class="list-wrapper">
                        <template #default="{ item }">
                            <div class="line-item content-value">
                                {{ item }}
                            </div>
                        </template>
                    </n-virtual-list>
                </n-card>
            </n-form>
        </n-spin>

        <template #action>
            <div class="flex-item n-dialog__action">
                <n-button :disabled="loading" :focusable="false" @click="onClose">{{ $t('common.cancel') }}</n-button>
                <n-button
                    v-if="deleteForm.direct"
                    :focusable="false"
                    :loading="loading"
                    type="primary"
                    @click="onConfirmDirectDelete">
                    {{ $t('dialogue.key.confirm_delete') }}
                </n-button>
                <template v-else>
                    <n-button
                        v-if="!deleteForm.showAffected"
                        :focusable="false"
                        :loading="loading"
                        type="primary"
                        @click="scanAffectedKey">
                        {{ $t('dialogue.key.show_affected_key') }}
                    </n-button>
                    <n-button
                        v-else
                        :disabled="isEmpty(deleteForm.affectedKeys)"
                        :focusable="false"
                        :loading="loading"
                        type="primary"
                        @click="onConfirmDelete">
                        {{ $t('dialogue.key.confirm_delete_key', { num: size(deleteForm.affectedKeys) }) }}
                    </n-button>
                </template>
            </div>
        </template>
    </n-modal>
</template>

<style lang="scss" scoped>
.line-item {
    line-height: 1.6;
}

.list-wrapper {
    box-sizing: border-box;
    max-height: 180px;
    user-select: text;
    cursor: text;
}
</style>
