<template>
    <el-dialog
        v-model="visible"
        class="ba-operate-dialog"
        :close-on-click-modal="false"
        width="560px"
        @open="onOpen"
    >
        <template #header>
            <div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
                {{ t('mall.dailyPush.export_title') }}
            </div>
        </template>

        <el-alert type="info" :closable="false" class="export-tip">
            {{ t('mall.dailyPush.export_tip') }}
        </el-alert>

        <div class="export-section">
            <div class="section-title">{{ t('mall.dailyPush.export_fields') }}</div>
            <div class="field-actions">
                <el-button link type="primary" @click="selectAllFields">{{ t('mall.dailyPush.export_select_all') }}</el-button>
                <el-button link type="primary" @click="clearFields">{{ t('mall.dailyPush.export_clear_all') }}</el-button>
            </div>
            <el-checkbox-group v-model="form.fields" class="field-group">
                <el-checkbox v-for="item in fieldOptions" :key="item.value" :label="item.value" :value="item.value">
                    {{ item.label }}
                </el-checkbox>
            </el-checkbox-group>
        </div>

        <div class="export-section">
            <div class="section-title">{{ t('mall.dailyPush.export_limit') }}</div>
            <div class="limit-row">
                <el-input-number v-model="form.exportLimit" :min="0" :max="matchedCount || undefined" :step="1000" controls-position="right" />
                <div class="limit-presets">
                    <el-button
                        v-for="preset in limitPresets"
                        :key="preset"
                        size="small"
                        :type="form.exportLimit === preset ? 'primary' : 'default'"
                        @click="form.exportLimit = preset"
                    >
                        {{ preset }}
                    </el-button>
                    <el-button size="small" :type="form.exportLimit === 0 ? 'primary' : 'default'" @click="useMatchedCount">
                        {{ t('mall.dailyPush.export_all_matched') }}
                    </el-button>
                </div>
            </div>
            <div class="count-info" v-loading="countLoading">
                {{ t('mall.dailyPush.export_matched_count', { count: matchedCount }) }}
                <span v-if="actualExportCount > 0">
                    ，{{ t('mall.dailyPush.export_actual_count', { count: actualExportCount }) }}
                </span>
            </div>
            <el-alert v-if="actualExportCount > 10000" type="warning" :closable="false" class="large-export-warning">
                {{ t('mall.dailyPush.export_large_warning') }}
            </el-alert>
        </div>

        <template #footer>
            <el-button @click="visible = false">{{ t('Cancel') }}</el-button>
            <el-button type="primary" :loading="exporting" :disabled="form.fields.length === 0" @click="submitExport">
                {{ t('mall.dailyPush.export_confirm') }}
            </el-button>
        </template>
    </el-dialog>
</template>

<script setup lang="ts">
import { computed, inject, reactive, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { ElNotification } from 'element-plus'
import createAxios from '/@/utils/axios'
import type baTableClass from '/@/utils/baTable'
import { SYSTEM_ZINDEX } from '/@/stores/constant/common'

const { t } = useI18n()
const baTable = inject('baTable') as baTableClass

const visible = defineModel<boolean>({ default: false })

const exporting = ref(false)
const countLoading = ref(false)
const matchedCount = ref(0)
const limitPresets = [1000, 5000, 10000, 50000]

const fieldOptions = computed(() => [
    { value: 'id', label: t('mall.dailyPush.id') },
    { value: 'user_id', label: t('mall.dailyPush.user_id') },
    { value: 'date', label: t('mall.dailyPush.date') },
    { value: 'username', label: t('mall.dailyPush.username') },
    { value: 'yesterday_win_loss_net', label: t('mall.dailyPush.yesterday_win_loss_net') },
    { value: 'yesterday_total_deposit', label: t('mall.dailyPush.yesterday_total_deposit') },
    { value: 'lifetime_total_deposit', label: t('mall.dailyPush.lifetime_total_deposit') },
    { value: 'lifetime_total_withdraw', label: t('mall.dailyPush.lifetime_total_withdraw') },
    { value: 'create_time', label: t('mall.dailyPush.create_time') },
])

const form = reactive({
    fields: fieldOptions.value.map((item) => item.value),
    exportLimit: 0,
})

const actualExportCount = computed(() => {
    if (form.exportLimit <= 0) {
        return matchedCount.value
    }
    return Math.min(form.exportLimit, matchedCount.value)
})

const selectAllFields = () => {
    form.fields = fieldOptions.value.map((item) => item.value)
}

const clearFields = () => {
    form.fields = []
}

const useMatchedCount = () => {
    form.exportLimit = 0
}

const buildExportParams = () => {
    const filter = baTable.table.filter || {}
    return {
        ...filter,
        fields: form.fields,
        export_limit: form.exportLimit <= 0 ? 0 : form.exportLimit,
    }
}

const loadMatchedCount = async () => {
    countLoading.value = true
    try {
        const res = await createAxios<{ count: number; max_limit: number }>({
            url: '/admin/mall.DailyPush/exportCount',
            method: 'get',
            params: baTable.table.filter || {},
        })
        matchedCount.value = res.data.count
    } catch {
        matchedCount.value = baTable.table.total || 0
    } finally {
        countLoading.value = false
    }
}

const parseBlobError = async (blob: Blob): Promise<string> => {
    try {
        const text = await blob.text()
        const json = JSON.parse(text)
        if (json && typeof json.msg === 'string' && json.msg !== '') {
            return json.msg
        }
    } catch {
        // ignore
    }
    return t('mall.dailyPush.export_failed')
}

const downloadBlob = (blob: Blob, filename: string) => {
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = filename
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)
}

const submitExport = async () => {
    if (form.fields.length === 0) {
        return
    }
    exporting.value = true
    try {
        const response = await createAxios<Blob>(
            {
                url: '/admin/mall.DailyPush/export',
                method: 'get',
                params: buildExportParams(),
                responseType: 'blob',
                timeout: 0,
            },
            {
                reductDataFormat: false,
                showErrorMessage: false,
                cancelDuplicateRequest: false,
            }
        )

        const blob = response.data
        const contentType = String(response.headers['content-type'] || '')
        if (contentType.includes('application/json')) {
            throw new Error(await parseBlobError(blob))
        }

        const disposition = String(response.headers['content-disposition'] || '')
        const filenameMatch = disposition.match(/filename="?([^";]+)"?/i)
        const filename = filenameMatch?.[1] || `daily_push_${Date.now()}.xlsx`
        downloadBlob(blob, filename)

        ElNotification({
            type: 'success',
            message: t('mall.dailyPush.export_success', { count: actualExportCount.value }),
            zIndex: SYSTEM_ZINDEX,
        })
        visible.value = false
    } catch (error) {
        const message = error instanceof Error ? error.message : t('mall.dailyPush.export_failed')
        ElNotification({
            type: 'error',
            message,
            zIndex: SYSTEM_ZINDEX,
        })
    } finally {
        exporting.value = false
    }
}

const onOpen = () => {
    loadMatchedCount()
}
</script>

<style scoped lang="scss">
.export-tip {
    margin-bottom: 16px;
}
.export-section {
    margin-bottom: 18px;
}
.section-title {
    font-weight: 600;
    margin-bottom: 8px;
}
.field-actions {
    margin-bottom: 8px;
}
.field-group {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px 12px;
}
.limit-row {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.limit-presets {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.count-info {
    margin-top: 10px;
    color: var(--el-text-color-secondary);
    font-size: 13px;
}
.large-export-warning {
    margin-top: 12px;
}
</style>
