<template>
  <section class="mmcg">
    <header class="mmcg-head">
      <span class="mmcg-title">{{ title }}</span>
      <el-tag size="small" effect="plain" type="info">{{ summaryText }}</el-tag>
      <div class="spacer" />
      <el-button-group v-if="available.length">
        <el-button size="small" :disabled="!canSelectAll" @click="selectAll">全选</el-button>
        <el-button size="small" :disabled="!selected.length" @click="clearAll">清空</el-button>
      </el-button-group>
    </header>

    <p v-if="!available.length" class="mmcg-empty muted">{{ emptyTip }}</p>

    <el-checkbox-group
      v-else
      :model-value="selected"
      class="mmcg-grid"
      @update:model-value="onChange">
      <el-checkbox v-for="key in available" :key="key" :value="key" :label="key" class="mmcg-cb" />
    </el-checkbox-group>

    <!-- 处理"残留键"：已勾选但不再出现在 available 里（后端实现变了 / 插件卸载了）-->
    <div v-if="orphanKeys.length" class="mmcg-orphans">
      <el-alert
        type="warning"
        :closable="false"
        show-icon
        :title="`检测到 ${orphanKeys.length} 个残留键（后端已经不再暴露，但仍在白名单中）`">
        <template #default>
          <div class="orphan-list">
            <el-tag
              v-for="key in orphanKeys"
              :key="key"
              type="warning"
              size="small"
              closable
              @close="removeOrphan(key)">
              {{ key }}
            </el-tag>
            <el-button link type="warning" size="small" @click="clearOrphans">一键清理全部残留</el-button>
          </div>
        </template>
      </el-alert>
    </div>
  </section>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import type { CheckboxValueType } from 'element-plus'

const props = defineProps<{
  title: string
  available: string[]
  selected: string[]
  emptyTip?: string
}>()

const emit = defineEmits<{
  (e: 'update:selected', value: string[]): void
}>()

const summaryText = computed(() => {
  if (!props.available.length) return '空'
  if (!props.selected.length) return `白名单空 = 显示全部 (${props.available.length})`
  return `${props.selected.length} / ${props.available.length}`
})

// available 是后端最新扫描结果。selected 里可能有 "残留"——之前勾选过但后端现在不再返回（插件
// 卸载 / 类型重命名）。这些键不会出现在 checkbox-group 里（避免渲染陌生项），但要单独列出来
// 让用户决定是否清理；不主动删，避免误清"暂时离线的插件键"。
const orphanKeys = computed(() =>
  props.selected.filter((k) => !props.available.includes(k))
)

const canSelectAll = computed(() => props.available.length > props.selected.length)

function onChange(v: CheckboxValueType[]) {
  // element-plus 在泛型推断下会拿到 CheckboxValueType（string | number | boolean）。我们这里键
  // 全是 string，强制断言；同时把可能残留的 orphan 键并回去，避免「在某 kind 全选」操作把
  // orphan 默默丢掉（用户应该走"清理残留"显式确认）。
  const next = (v as string[]).filter((x) => typeof x === 'string')
  const merged = [...next, ...orphanKeys.value]
  emit('update:selected', merged)
}

function selectAll() {
  emit('update:selected', [...props.available, ...orphanKeys.value])
}

function clearAll() {
  // 仅清空 available 内的；orphan 保留（防误删，要走"残留清理"流程）
  emit('update:selected', [...orphanKeys.value])
}

function removeOrphan(key: string) {
  emit('update:selected', props.selected.filter((k) => k !== key))
}

function clearOrphans() {
  emit('update:selected', props.selected.filter((k) => props.available.includes(k)))
}
</script>

<style scoped>
.mmcg {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
  background: var(--mg-veil-1);
  border: 1px solid var(--mg-veil-border);
  border-radius: 8px;
}
.mmcg-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.mmcg-title {
  font-weight: 600;
  font-size: 13px;
  color: var(--mg-text-light);
}
.mmcg-head .spacer { flex: 1; }
.mmcg-empty {
  margin: 4px 0 0;
  font-size: 12px;
  font-style: italic;
}
.muted { color: var(--mg-text-dim); }

.mmcg-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 4px 12px;
  align-items: center;
}
.mmcg-grid :deep(.el-checkbox) {
  margin-right: 0;
  height: 28px;
}
.mmcg-grid :deep(.el-checkbox__label) {
  color: var(--mg-text-light);
  font-size: 12.5px;
  font-family: ui-monospace, Menlo, Consolas, monospace;
}

.mmcg-orphans { margin-top: 4px; }
.orphan-list {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}
</style>
