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

        <!-- 工具栏 -->
        <div class="toolbar">
            <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" type="warning" :disabled="!processedCount" @click="deleteProcessed">
                删除已处理
            </el-button>

            <el-button size="small" type="primary" @click="saveAll">保存</el-button>
            <el-tooltip placement="bottom" effect="dark">
                <template #content>
                    在空白区域按下左键拖拽进行框选<br />

                </template>
                <el-icon class="hint">i</el-icon>
            </el-tooltip>
        </div>

        <!-- 列表区域 -->
        <div ref="gridRef" class="grid" @mousedown="onMouseDown" @mousemove="onMouseMove" @mouseup="onMouseUp"
            @mouseleave="onMouseUp" @scroll="recalcRectsSoon">
            <div v-for="it in hosts" :key="it.text" class="item-card" :class="{ selected: isSelected(it.text) }"
                :ref="el => setCardRef(it.text, el)" @click.stop="toggleSelect(it.text)">
                <div class="row top">
                    <span class="id" :title="it.text">{{ it.text }}</span>
                    <button class="x" title="删除此项" @click.stop="deleteOne(it.text)">×</button>
                </div>
                <div class="row meta">
                    <span class="country" :title="it.country">{{ it.country || '—' }}</span>
                    <span class="state" :class="{ done: !!it.state }">{{ it.state ? '已处理' : '未处理' }}</span>
                </div>
            </div>

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

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

<script setup>
import { ref, reactive, computed, watch, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getHostList, setHostList } from '@/stores/storage'

// v-model:visible 接口
const props = defineProps({
    visible: { type: Boolean, default: false }
})
const emit = defineEmits(['update:visible', 'save'])
const show = computed({
    get: () => props.visible,
    set: (v) => emit('update:visible', v)
})

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

// 卡片 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]
    }
}

function getStoredHostList() {
    const v = getHostList()
    return Array.isArray(v) ? v : []
}

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

function saveAll() {
    setHostList(hosts.value)
    ElMessage.success('已保存')
    emit('save', hosts.value)
}

// 选择相关
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.text)) }
function selectNone() { selected.clear() }
function invertSelect() {
    const next = new Set()
    hosts.value.forEach(it => { if (!selected.has(it.text)) next.add(it.text) })
    selected.clear(); next.forEach(id => selected.add(id))
}

function deleteSelected() {
    if (!selected.size) return
    ElMessageBox.confirm(`确认删除选中的 ${selected.size} 项吗？`, '提示', { type: 'warning' })
        .then(() => {
            const keep = []
            for (const it of hosts.value) if (!selected.has(it.text)) keep.push(it)
            hosts.value = keep
            selected.clear()
            setHostList(keep)
            recalcRectsSoon()
            ElMessage.success('已删除选中')
        })
        .catch(() => { })
}

function deleteOne(id) {
    const idx = hosts.value.findIndex(it => it.text === 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.text]
        if (!r) continue
        const hit = !(r.left > x2 || r.right < x1 || r.top > y2 || r.bottom < y1)
        if (hit) current.add(it.text)
    }
    // 覆盖 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.text === id)) selected.delete(id)
            }

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

watch(hosts, () => nextTick().then(recalcRects))
</script>

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

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

.toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
}

.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;
}

.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 .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: #67c23a;
    border-color: #67c23a;
}

.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>