<script lang="ts" setup>
/**
 * VIP 功能反绑会员等级：卡片勾选 + 徽章图 + 全选/取消全选/反选
 * 真相源仍是 xk_vip_level.permissions
 */
import { computed, ref } from 'vue';

import { useVbenModal } from '@vben/common-ui';
import { Button, Empty, message } from 'ant-design-vue';

import { getVipLevelOption } from '../../level/api';
import { bindVipFeatureLevels } from '../api';

type LevelCard = {
  id: number;
  name: string;
  code: string;
  badge_url: string;
  weight: number;
  price: number;
};

const feature = ref<Record<string, any>>({});
const levelOptions = ref<LevelCard[]>([]);
const selectedIds = ref<number[]>([]);
const loadingOptions = ref(false);
const onSaved = ref<null | (() => void)>(null);

const selectedSet = computed(() => new Set(selectedIds.value));
const selectedCount = computed(() => selectedIds.value.length);

/** 是否已选中某等级 */
function isSelected(id: number) {
  return selectedSet.value.has(id);
}

/**
 * 点击卡片切换选中（不用 CheckboxGroup，避免嵌套点击问题）
 */
function toggleLevel(id: number) {
  const set = new Set(selectedIds.value);
  if (set.has(id)) {
    set.delete(id);
  } else {
    set.add(id);
  }
  selectedIds.value = Array.from(set);
}

/** 全选当前列表中的等级 */
function selectAll() {
  selectedIds.value = levelOptions.value.map((row) => row.id);
}

/** 取消全选 */
function clearAll() {
  selectedIds.value = [];
}

/** 反选 */
function invertAll() {
  const set = new Set(selectedIds.value);
  selectedIds.value = levelOptions.value
    .map((row) => row.id)
    .filter((id) => !set.has(id));
}

/**
 * 拉取启用中的等级选项（含徽章）
 */
async function loadLevelOptions() {
  loadingOptions.value = true;
  try {
    const rows = await getVipLevelOption();
    const list = Array.isArray(rows) ? rows : [];
    levelOptions.value = list
      .map((row: any) => ({
        id: Number(row.id),
        name: String(row.name || row.code || ''),
        code: String(row.code || ''),
        badge_url: String(row.badge_url || ''),
        weight: Number(row.level_weight || 0),
        price: Number(row.price || 0),
      }))
      .filter((row) => row.id > 0)
      .sort((a, b) => a.weight - b.weight || a.id - b.id);
  } finally {
    loadingOptions.value = false;
  }
}

const [Modal, modalApi] = useVbenModal({
  title: '绑定会员等级',
  class: 'w-[780px]',
  draggable: true,
  confirmText: '保存绑定',
  async onConfirm() {
    const id = Number(feature.value.id || 0);
    if (!id) {
      message.warning('功能无效');
      return;
    }
    modalApi.setState({ confirmLoading: true });
    try {
      await bindVipFeatureLevels({
        id,
        code: feature.value.code,
        level_ids: selectedIds.value.slice(),
      });
      message.success('绑定已更新（低档勾选会自动补齐更高档）');
      onSaved.value?.();
      modalApi.close();
    } finally {
      modalApi.setState({ confirmLoading: false });
    }
  },
  async onOpenChange(isOpen: boolean) {
    if (!isOpen) {
      feature.value = {};
      selectedIds.value = [];
      onSaved.value = null;
      return;
    }
    const data = modalApi.getData<{
      feature?: Record<string, any>;
      onSaved?: () => void;
    }>();
    feature.value = data?.feature || {};
    onSaved.value = data?.onSaved || null;
    await loadLevelOptions();
    const ids = Array.isArray(feature.value.bound_level_ids)
      ? feature.value.bound_level_ids.map((x: any) => Number(x)).filter(Boolean)
      : (feature.value.bound_levels || []).map((x: any) => Number(x.id));
    selectedIds.value = ids;
    modalApi.setState({
      title: feature.value.name
        ? `绑定会员等级 - ${feature.value.name}`
        : '绑定会员等级',
    });
  },
});
</script>

<template>
  <Modal>
    <div class="mb-3 text-sm text-[hsl(var(--muted-foreground))]">
      功能编码：
      <span class="font-medium text-[hsl(var(--foreground))]">{{
        feature.code || '—'
      }}</span>
      。点击卡片勾选/取消；勾选较低档时，更高档会自动补齐。
    </div>
    <div class="mb-3 flex flex-wrap items-center gap-2">
      <Button size="small" @click="selectAll">全选</Button>
      <Button size="small" @click="clearAll">取消全选</Button>
      <Button size="small" @click="invertAll">反选</Button>
      <span class="ml-auto text-xs text-[hsl(var(--muted-foreground))]">
        已选 {{ selectedCount }} / {{ levelOptions.length }}
      </span>
    </div>
    <Empty
      v-if="!loadingOptions && !levelOptions.length"
      description="暂无启用中的会员等级"
    />
    <div
      v-else
      class="grid max-h-[420px] grid-cols-2 gap-3 overflow-y-auto pr-1 md:grid-cols-3"
    >
      <div
        v-for="opt in levelOptions"
        :key="opt.id"
        class="vip-level-card"
        :class="{ 'vip-level-card--on': isSelected(opt.id) }"
        @click="toggleLevel(opt.id)"
      >
        <div class="vip-level-card__check">
          {{ isSelected(opt.id) ? '✓' : '' }}
        </div>
        <div class="vip-level-card__badge">
          <img
            v-if="opt.badge_url"
            :src="opt.badge_url"
            :alt="opt.name"
            class="vip-level-card__img"
          />
          <div v-else class="vip-level-card__placeholder">
            {{ (opt.name || opt.code || '?').slice(0, 1) }}
          </div>
        </div>
        <div class="vip-level-card__name">
          {{ opt.name || opt.code || '—' }}
          <span v-if="opt.code" class="vip-level-card__code">{{
            opt.code
          }}</span>
        </div>
        <div class="vip-level-card__meta">权重 {{ opt.weight }}</div>
      </div>
    </div>
  </Modal>
</template>

<style scoped>
.vip-level-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 14px 10px 12px;
  border: 1px solid hsl(var(--border));
  border-radius: 10px;
  background: hsl(var(--card, var(--background)));
  cursor: pointer;
  transition:
    border-color 0.15s,
    background 0.15s,
    box-shadow 0.15s;
  user-select: none;
}
.vip-level-card:hover {
  border-color: hsl(var(--primary) / 0.45);
}
.vip-level-card--on {
  border-color: hsl(var(--primary));
  background: hsl(var(--primary) / 0.08);
  box-shadow: 0 0 0 1px hsl(var(--primary) / 0.25);
}
.vip-level-card__check {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1px solid hsl(var(--border));
  background: hsl(var(--background));
  color: hsl(var(--primary));
  font-size: 12px;
  line-height: 18px;
  text-align: center;
  font-weight: 700;
}
.vip-level-card--on .vip-level-card__check {
  border-color: hsl(var(--primary));
  background: hsl(var(--primary));
  color: #fff;
}
.vip-level-card__badge {
  width: 72px;
  height: 72px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 8px;
}
.vip-level-card__img {
  max-width: 72px;
  max-height: 72px;
  object-fit: contain;
}
.vip-level-card__placeholder {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: hsl(var(--muted) / 0.5);
  color: hsl(var(--muted-foreground));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 600;
}
.vip-level-card__name {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 4px 6px;
  font-size: 14px;
  font-weight: 600;
  color: hsl(var(--foreground));
  text-align: center;
}
.vip-level-card__code {
  font-size: 12px;
  font-weight: 500;
  color: hsl(var(--primary));
}
.vip-level-card__meta {
  margin-top: 4px;
  font-size: 11px;
  color: hsl(var(--muted-foreground));
  text-align: center;
}
</style>
