<template>
    <el-dialog v-model="show" width="70vw" :close-on-click-modal="false" :destroy-on-close="true" draggable
        @open="onOpen">
        <template #header>
            <div class="dlg-title">
                <span>主播管理</span>
                <span class="muted">（已选 {{ selectedCount }} / 共 {{ hosts.length }}）</span>
            </div>
        </template>

        <!-- 工具栏 -->
        <div class="toolbar">
            <!-- 操作按钮行 -->
            <div class="toolbar-row">
                <el-button size="small" @click="selectAll">全选</el-button>
                <el-button size="small" @click="selectNone">全不选</el-button>
                <el-button size="small" @click="invertSelect">反选</el-button>
                <el-button size="small" type="danger" :disabled="!selectedCount"
                    @click="deleteSelected">删除选中</el-button>
                <el-button size="small" @click="resetFilter">重置</el-button>

                <el-tooltip placement="bottom" effect="dark">
                    <template #content>
                        在空白区域按下左键拖拽进行框选<br />
                    </template>
                    <el-icon class="hint">i</el-icon>
                </el-tooltip>
            </div>

            <!-- 金票 / 普票 + 筛选条件行（支持自动换行） -->
            <div class="toolbar-row toolbar-filter">
                <el-switch v-model="filters.gold" :loading="goldLoading" :before-change="goldBeforeChange" inline-prompt
                    active-text="金票" inactive-text="金票" size="large" style="--el-switch-on-color: #db9600;" />
                <el-switch v-model="filters.ordinary" :loading="ordinaryLoading" :before-change="ordinaryBeforeChange"
                    inline-prompt inactive-text="普票" active-text="普票" size="large" />


                <!-- 在线人数 -->
                <span class="filter-label">在线人数</span>
                <el-input-number v-model="filters.min_onlineFans" :min="0" size="small" controls-position="right"
                    placeholder="最小" class="filter-input-number" />
                <span>~</span>
                <el-input-number v-model="filters.max_onlineFans" :min="0" size="small" controls-position="right"
                    placeholder="最大" class="filter-input-number" />

                <!-- 主播等级（多选） -->
                <span class="filter-label">主播等级</span>
                <el-tree-select v-model="filters.hostslevel" :data="levelTreeData" multiple show-checkbox collapse-tags
                    collapse-tags-tooltip size="small" placeholder="选择等级" class="filter-select-multi" node-key="value"
                    :render-after-expand="false" />



            </div>
        </div>

        <!-- 列表区域 -->
        <div ref="gridRef" class="grid" @mousedown="onMouseDown" @mousemove="onMouseMove" @mouseup="onMouseUp"
            @mouseleave="onMouseUp" @scroll="recalcRectsSoon">
            <div v-for="it in hosts" :key="it.anchorId" class="item-card" :class="{ selected: isSelected(it.anchorId) }"
                :ref="el => setCardRef(it.anchorId, el)" @click.stop="toggleSelect(it.anchorId)">
                <div class="row top">
                    <span class="id" :title="it.anchorId">{{ it.anchorId }}</span>
                    <button v-if="it.state == 0" class="x" title="不执行">X</button>
                    <button v-else class="y" title="执行">√</button>
                </div>
                <div class="row meta">
                    <span class="country" :title="it.country">{{ it.country || '—' }}</span>
                    <span class="state" :class="{ done: it.invitationType == 2 }">
                        {{ it.invitationType == 2 ? '金票' : '普票' }}
                    </span>
                </div>
            </div>

            <!-- 框选矩形 -->
            <div v-if="selecting" class="selection-rect" :style="selectionStyle"></div>
        </div>

        <template #footer>
            <div class="foot">
                <el-button type="primary" @click="applyFilter">保存</el-button>
                <el-button @click="show = false;">关闭</el-button>
            </div>
        </template>
    </el-dialog>
</template>

<script setup>
import { ref, reactive, computed, watch, nextTick, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getHostfilters, setHostfilters } from '@/stores/storage'
import { anchorList, deleteAnchorWithIds, updateAnchorList, } from '@/api/ios'
// v-model:visible 接口
const props = defineProps({
    visible: { type: Boolean, default: false }
})

const emit = defineEmits(['update:visible', 'save', 'invitType'])
const show = computed({
    get: () => props.visible,
    set: (v) => emit('update:visible', v)
})



const defaultFilters = {
    gold: null,
    ordinary: null,
    min_onlineFans: null,
    max_onlineFans: null,
    hostslevel: []
}

// 数据
const hosts = ref([]) // {country, text, state}
const selected = reactive(new Set()) // 选中的 text 集合

// 主播等级树形数据（A / B / C / D）
const levelTreeData = [
    {
        label: 'A',
        value: 'A',
        children: [
            { label: 'A1', value: 'A1' },
            { label: 'A2', value: 'A2' },
            { label: 'A3', value: 'A3' },
        ]
    },
    {
        label: 'B',
        value: 'B',
        children: [
            { label: 'B1', value: 'B1' },
            { label: 'B2', value: 'B2' },
            { label: 'B3', value: 'B3' },
            { label: 'B4', value: 'B4' },
            { label: 'B5', value: 'B5' },
        ]
    },
    {
        label: 'C',
        value: 'C',
        children: [
            { label: 'C1', value: 'C1' },
            { label: 'C2', value: 'C2' },
            { label: 'C3', value: 'C3' },
            { label: 'C4', value: 'C4' },
            { label: 'C5', value: 'C5' },
        ]
    },
    {
        label: 'D',
        value: 'D',
        children: [
            { label: 'D1', value: 'D1' },
            { label: 'D2', value: 'D2' },
            { label: 'D3', value: 'D3' },
            { label: 'D4', value: 'D4' },
            { label: 'D5', value: 'D5' },
        ]
    }
]

let goldLoading = ref(false)


let ordinaryLoading = ref(false)

// 筛选参数
const filters = reactive({ ...defaultFilters })



// 卡片 DOM 引用与位置缓存
const gridRef = ref(null)
const cardRefs = reactive({}) // text -> el
const rectCache = reactive({}) // text -> DOMRect
let rectRecalcTimer = null

const processedCount = computed(() => hosts.value.filter(it => !!it?.state).length)
function setCardRef(key, el) {
    if (el) {
        cardRefs[key] = el
    } else {
        delete cardRefs[key]
        delete rectCache[key]
    }
}

async function getStoredHostList() {
    const v = await anchorList()
    return v ? v : []
}

async function onOpen() {
    hosts.value = await getStoredHostList()
    console.log(hosts.value)
    selected.clear()
    await nextTick()
    recalcRects()
}

// 应用筛选（通过 getMQMessagesByFilter）
async function applyFilter() {
    try {
        const params = {
            gold: filters.gold,
            ordinary: filters.ordinary,
            min_onlineFans: filters.min_onlineFans,
            max_onlineFans: filters.max_onlineFans,
            // 多选等级转成 "D5,D4,B3" 这种格式给后端
            hostslevel: filters.hostslevel
        }

        // 清除 null / 空字符串，避免传一堆 undefined
        const cleanParams = {}
        Object.keys(params).forEach(key => {
            const v = params[key]
            if (v !== null && v !== '' && v !== undefined) {
                cleanParams[key] = v
            }
        })
        console.log(filters)
        setHostfilters(filters)
        show.value = false
        selected.clear()
        await nextTick()
        recalcRects()
    } catch (error) {
        console.error(error)
        ElMessage.error('筛选失败：' + (error.message || '未知错误'))
    }
}

// 重置筛选条件
async function resetFilter() {
    filters.gold = true
    filters.ordinary = true
    filters.min_onlineFans = null
    filters.max_onlineFans = null
    filters.hostslevel = []   // 清空多选
    // 恢复默认列表
    hosts.value = await getStoredHostList()
    selected.clear()
    await nextTick()
    recalcRects()
}

// 选择相关
const selectedCount = computed(() => selected.size)
function isSelected(id) { return selected.has(id) }
function toggleSelect(id) {
    if (selected.has(id)) selected.delete(id)
    else selected.add(id)
}
function selectAll() { selected.clear(); hosts.value.forEach(it => selected.add(it.anchorId)) }
function selectNone() { selected.clear() }
function invertSelect() {
    const next = new Set()
    hosts.value.forEach(it => { if (!selected.has(it.anchorId)) next.add(it.anchorId) })
    selected.clear(); next.forEach(id => selected.add(id))
}

function deleteSelected() {
    if (!selected.size) return
    ElMessageBox.confirm(`确认删除选中的 ${selected.size} 项吗？`, '提示', { type: 'warning' })
        .then(() => {

            const keep = []
            const selectHost = []
            console.log("selected", selected)

            for (const it of hosts.value) {
                if (selected.has(it.anchorId)) {
                    keep.push(it)
                } else {
                    selectHost.push(it)
                }
            }
            console.log("keep", keep)

            hosts.value = selectHost
            selected.clear()
            deleteAnchorWithIds(keep)
            recalcRectsSoon()
            ElMessage.success('已删除选中')
        })
        .catch(() => { })
}

function deleteOne(id) {
    const idx = hosts.value.findIndex(it => it.anchorId === id)
    if (idx !== -1) {
        hosts.value.splice(idx, 1)
        selected.delete(id)
        // setHostList(hosts.value)
        recalcRectsSoon()
    }
}

// —— 框选逻辑 ——
// ... 这部分不变 ...
const selecting = ref(false)
const anchor = ref({ x: 0, y: 0 })
const cursor = ref({ x: 0, y: 0 })
const baseSelection = ref(new Set()) // 框选开始时的已有选择（支持累加）

const selectionStyle = computed(() => {
    const root = gridRef.value
    if (!root) return {}
    // 使用容器坐标系定位矩形
    const box = root.getBoundingClientRect()
    const x1 = Math.min(anchor.value.x, cursor.value.x) - box.left + root.scrollLeft
    const y1 = Math.min(anchor.value.y, cursor.value.y) - box.top + root.scrollTop
    const x2 = Math.max(anchor.value.x, cursor.value.x) - box.left + root.scrollLeft
    const y2 = Math.max(anchor.value.y, cursor.value.y) - box.top + root.scrollTop
    return { left: x1 + 'px', top: y1 + 'px', width: (x2 - x1) + 'px', height: (y2 - y1) + 'px' }
})

function onMouseDown(e) {
    if (e.button !== 0) return
    const root = gridRef.value
    if (!root) return
    // 只在空白处拖拽，或按着 Alt 任意处拖拽
    const onItem = e.target && e.target.closest && e.target.closest('.item-card')
    if (onItem && !e.altKey) return

    // 记录锚点（client 坐标，方便和 DOMRect 比较）
    anchor.value = { x: e.clientX, y: e.clientY }
    cursor.value = { x: e.clientX, y: e.clientY }
    selecting.value = true
    // 是否保留原选择
    baseSelection.value = (e.ctrlKey || e.metaKey) ? new Set(Array.from(selected)) : new Set()
    // 防止选中文本
    e.preventDefault()
}

function onMouseMove(e) {
    if (!selecting.value) return
    cursor.value = { x: e.clientX, y: e.clientY }
    updateSelectionByRect()
}

function onMouseUp() {
    if (!selecting.value) return
    selecting.value = false
}

function updateSelectionByRect() {
    const x1 = Math.min(anchor.value.x, cursor.value.x)
    const y1 = Math.min(anchor.value.y, cursor.value.y)
    const x2 = Math.max(anchor.value.x, cursor.value.x)
    const y2 = Math.max(anchor.value.y, cursor.value.y)

    // 实时选择集合
    const current = new Set(baseSelection.value)
    for (const it of hosts.value) {
        const r = rectCache[it.anchorId]
        if (!r) continue
        const hit = !(r.left > x2 || r.right < x1 || r.top > y2 || r.bottom < y1)
        if (hit) current.add(it.anchorId)
    }
    // 覆盖 selected
    selected.clear(); current.forEach(id => selected.add(id))
}

function recalcRects() {
    for (const [key, el] of Object.entries(cardRefs)) {
        try { rectCache[key] = el.getBoundingClientRect() } catch { }
    }
}

function recalcRectsSoon() {
    clearTimeout(rectRecalcTimer)
    rectRecalcTimer = setTimeout(() => nextTick().then(recalcRects), 16)
}

function deleteProcessed() {
    if (!processedCount.value) return
    ElMessageBox.confirm(
        `确认删除所有“已处理”项（${processedCount.value} 个）吗？此操作不可撤销。`,
        '提示',
        { type: 'warning' }
    )
        .then(() => {
            // 仅保留未处理
            const keep = hosts.value.filter(it => !it?.state)
            hosts.value = keep

            // 清理已不存在的选中项
            for (const id of Array.from(selected)) {
                if (!keep.find(it => it.anchorId === id)) selected.delete(id)
            }

            deleteAnchorWithIds(keep)      // 同步回缓存
            recalcRectsSoon()      // 重新计算卡片矩形，保证框选正常
            ElMessage.success('已删除已处理项')
        })
        .catch(() => { })
}

const ordinaryBeforeChange = () => {
    const next = !filters.ordinary       // 目标值（切换后）
    ordinaryLoading.value = true

    return new Promise((resolve) => {
        updateAnchorList({ invitationType: 1, state: next ? 1 : 0 })
            .then(async () => {
                ordinaryLoading.value = false
                hosts.value = await getStoredHostList()
                emit('invitType', 'ordinary', next)  // 把“切换后的目标布尔”抛给父组件
                resolve(true)   // 允许切换
            })
            .catch(error => {
                ordinaryLoading.value = false
                ElMessage.error('Operation failed: ' + error.message)
                resolve(false)  // 阻止切换
            })
    })
}

const goldBeforeChange = () => {
    const next = !filters.gold
    goldLoading.value = true

    return new Promise((resolve) => {
        updateAnchorList({ invitationType: 2, state: next ? 1 : 0 })
            .then(async () => {
                goldLoading.value = false
                hosts.value = await getStoredHostList()
                emit('invitType', 'gold', next)
                resolve(true)
            })
            .catch(error => {
                goldLoading.value = false
                ElMessage.error('Operation failed: ' + error.message)
                resolve(false)
            })
    })
}

// 从 localStorage 读取并回显
function loadFiltersFromCache() {
    try {
        const raw = getHostfilters()

        if (!raw) return
        // 只覆盖存在的字段，防止结构变更报错
        Object.keys(defaultFilters).forEach((key) => {
            if (raw[key] !== undefined) {
                // @ts-ignore
                filters[key] = raw[key]
            }
        })
    } catch (e) {
        console.error('读取筛选缓存失败:', e)
    }
}

// 监听 filters 变化，自动持久化

watch(hosts, () => nextTick().then(recalcRects))
// 组件挂载时加载一次缓存
onMounted(() => {
    loadFiltersFromCache()
    applyFilter()
})


</script>


<style scoped>
.dlg-title {
    display: flex;
    gap: 8px;
    align-items: baseline;
}

.dlg-title .muted {
    color: #909399;
    font-size: 12px;
}

.toolbar {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 10px;
}

/* 每一行都是 flex，允许内部自动换行 */
.toolbar-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

/* 第二行筛选条件，稍微紧凑一点 */
.toolbar-filter {
    align-items: center;
}

.toolbar .hint {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 1px solid #bbb;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    color: #666;
}

.filter-label {
    font-size: 12px;
    color: #666;
    margin-left: 8px;
}

.filter-input-number {
    width: 110px;
}

.filter-select-multi {
    width: 180px;
}

.grid {
    position: relative;
    height: 60vh;
    overflow: auto;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 10px;
    padding: 6px;
    user-select: none;
    border: 1px solid var(--el-border-color);
    border-radius: 8px;
}

/* 后面样式保持不变 */
.item-card {
    border: 1px solid var(--el-border-color);
    border-radius: 10px;
    padding: 8px 10px;
    background: var(--el-bg-color);
    cursor: pointer;
    transition: box-shadow .15s, border-color .15s;
}

.item-card:hover {
    box-shadow: 0 2px 8px rgba(0, 0, 0, .06);
}

.item-card.selected {
    border-color: var(--el-color-primary);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--el-color-primary) 20%, transparent);
}

.item-card .row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.item-card .row.top {
    margin-bottom: 4px;
}

.item-card .id {
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 75%;
}

.item-card .x {
    border: none;
    background: transparent;
    color: #f56c6c;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}

.item-card .y {
    border: none;
    background: transparent;
    color: #00a316;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}

.item-card .x:hover {
    color: #f33;
}

.item-card .meta {
    color: #666;
    font-size: 12px;
}

.item-card .state {
    padding: 2px 6px;
    border-radius: 999px;
    border: 1px solid #ddd;
}

.item-card .state.done {
    color: #db9600;
    border-color: #db9600;
}

.selection-rect {
    position: absolute;
    pointer-events: none;
    border: 1px dashed var(--el-color-primary);
    background: color-mix(in srgb, var(--el-color-primary) 12%, transparent);
    z-index: 10;
}

.foot {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}
</style>