<script lang="ts" setup>
/**
 * 角色小程序功能入口分配抽屉：勾选入口 + 上移/下移排序，保存调 wx-workbench-entry/batch-save
 * 交互完整复刻 workbench-widget.vue（模块少用箭头排序，不引拖拽库）；
 * 与之的差异：可选项来自 xk_wx_workbench_entry 字典并按 group_name 分组展示
 */
import { computed, ref } from 'vue';

import { useVbenDrawer } from '@vben/common-ui';
import { IconifyIcon as VbenIcon } from '@vben/icons';

import { Button, Checkbox, message } from 'ant-design-vue';

import {
  batchSaveWxWorkbenchEntry,
  getWxWorkbenchEntryByRoleId,
  getWxWorkbenchEntryOptions,
} from '../api';

/** 字典入口项 */
type EntryOption = {
  code: string;
  description: string;
  group_name: string;
  id: number;
  name: string;
};

const record = ref<any>({});
const options = ref<EntryOption[]>([]);
/** 已分配的入口 id（数组顺序即小程序展示顺序） */
const enabledIds = ref<number[]>([]);

const drawerTitle = computed(() => {
  const roleName = record.value?.name || '';
  return roleName ? `小程序入口 - ${roleName}` : '小程序入口';
});

/** 未分配的入口，按分组聚合（供勾选添加） */
const disabledGroups = computed(() => {
  const rest = options.value.filter(
    (item) => !enabledIds.value.includes(item.id),
  );
  const groups: { items: EntryOption[]; name: string }[] = [];
  rest.forEach((item) => {
    const name = item.group_name || '未分组';
    let group = groups.find((g) => g.name === name);
    if (!group) {
      group = { name, items: [] };
      groups.push(group);
    }
    group.items.push(item);
  });
  return groups;
});

/**
 * 入口 id → 展示名（带分组前缀便于区分不同端的同名入口，如两端都有「提现管理」）
 */
function labelOf(id: number) {
  const item = options.value.find((option) => option.id === id);
  if (!item) return `#${id}`;
  return item.group_name ? `【${item.group_name}】${item.name}` : item.name;
}

/**
 * 勾选/取消某入口
 */
function toggle(id: number, checked: boolean) {
  if (checked) {
    if (!enabledIds.value.includes(id)) {
      enabledIds.value.push(id);
    }
  } else {
    enabledIds.value = enabledIds.value.filter((item) => item !== id);
  }
}

/**
 * 上移/下移调整顺序（offset -1 上移 / 1 下移）
 */
function move(index: number, offset: number) {
  const target = index + offset;
  if (target < 0 || target >= enabledIds.value.length) return;
  const list = [...enabledIds.value];
  const [item] = list.splice(index, 1);
  list.splice(target, 0, item!);
  enabledIds.value = list;
}

/**
 * 拉取字典 + 角色已分配入口
 */
async function fetchData() {
  const roleId = Number(record.value?.id || 0);
  if (!roleId) return;
  try {
    const [opts, assigned] = await Promise.all([
      getWxWorkbenchEntryOptions(),
      getWxWorkbenchEntryByRoleId(roleId),
    ]);
    options.value = Array.isArray(opts) ? opts : [];
    enabledIds.value = (Array.isArray(assigned) ? assigned : []).map(
      (item: any) => Number(item.entry_id),
    );
  } catch {
    message.error('获取小程序入口配置失败');
    options.value = [];
    enabledIds.value = [];
  }
}

/**
 * 保存配置（空数组表示清空该角色全部入口，小程序端会回落硬编码菜单保可用）
 */
async function handleSave() {
  const roleId = Number(record.value?.id || 0);
  if (!roleId) {
    message.error('角色ID不能为空');
    return;
  }
  DrawerApi.lock();
  try {
    await batchSaveWxWorkbenchEntry({
      role_id: roleId,
      entry_ids: enabledIds.value,
    });
    message.success('保存成功');
    DrawerApi.close();
  } catch {
    message.error('保存失败');
  } finally {
    DrawerApi.unlock();
  }
}

const [Drawer, DrawerApi] = useVbenDrawer({
  onOpenChange(isOpen) {
    if (isOpen) {
      record.value = DrawerApi.getData()?.record || {};
      options.value = [];
      enabledIds.value = [];
      DrawerApi.setState({ loading: true });
      fetchData().finally(() => {
        DrawerApi.setState({ loading: false });
      });
    }
  },
  onConfirm: handleSave,
});

defineExpose({
  DrawerApi,
});
</script>

<template>
  <Drawer :title="drawerTitle" class="w-[420px]">
    <div class="entry-config">
      <div class="entry-config__section-title">已分配（自上而下为展示顺序）</div>
      <div v-if="enabledIds.length > 0" class="entry-config__list">
        <div
          v-for="(id, index) in enabledIds"
          :key="id"
          class="entry-config__row"
        >
          <span class="entry-config__label">{{ labelOf(id) }}</span>
          <span class="entry-config__ops">
            <Button
              :disabled="index === 0"
              size="small"
              type="text"
              @click="move(index, -1)"
            >
              <VbenIcon icon="lucide:arrow-up" />
            </Button>
            <Button
              :disabled="index === enabledIds.length - 1"
              size="small"
              type="text"
              @click="move(index, 1)"
            >
              <VbenIcon icon="lucide:arrow-down" />
            </Button>
            <Button danger size="small" type="text" @click="toggle(id, false)">
              <VbenIcon icon="lucide:x" />
            </Button>
          </span>
        </div>
      </div>
      <div v-else class="entry-config__empty">
        未分配任何入口，小程序端将回落默认菜单
      </div>

      <div class="entry-config__section-title mt-4">可添加</div>
      <template v-if="disabledGroups.length > 0">
        <div
          v-for="group in disabledGroups"
          :key="group.name"
          class="entry-config__group"
        >
          <div class="entry-config__group-title">{{ group.name }}</div>
          <div class="entry-config__list">
            <div
              v-for="item in group.items"
              :key="item.id"
              class="entry-config__row"
            >
              <Checkbox
                :checked="false"
                @update:checked="(val: boolean) => toggle(item.id, val)"
              >
                {{ item.name }}
                <span v-if="item.description" class="entry-config__desc">
                  {{ item.description }}
                </span>
              </Checkbox>
            </div>
          </div>
        </div>
      </template>
      <div v-else class="entry-config__empty">全部入口已分配</div>
    </div>
  </Drawer>
</template>

<style scoped>
.entry-config__section-title {
  margin-bottom: 8px;
  font-size: 13px;
  font-weight: 600;
  color: hsl(var(--foreground));
}

.entry-config__group {
  margin-bottom: 10px;
}

.entry-config__group-title {
  margin-bottom: 6px;
  font-size: 12px;
  color: hsl(var(--muted-foreground));
}

.entry-config__list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.entry-config__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 10px;
  background: hsl(var(--muted) / 0.25);
  border: 1px solid hsl(var(--border));
  border-radius: 6px;
}

.entry-config__label {
  font-size: 13px;
  color: hsl(var(--foreground));
}

.entry-config__desc {
  margin-left: 6px;
  font-size: 12px;
  color: hsl(var(--muted-foreground));
}

.entry-config__ops {
  display: flex;
  gap: 2px;
  align-items: center;
}

.entry-config__empty {
  padding: 12px 0;
  font-size: 12px;
  color: hsl(var(--muted-foreground));
}
</style>
