<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue';
import { fetchGetDeptSimpleList, fetchGetUserSimpleList } from '@/service/api';
import { buildMenuTree } from '@/views/system/shared/menu-tree';
import IconEpOfficeBuilding from '~icons/ep/office-building';
import IconEpUser from '~icons/ep/user';

defineOptions({ name: 'AttendeeUserPicker' });

type Source = 'team' | 'all' | 'dept';
type TreeCheckState = 'none' | 'partial' | 'all';

interface AttendeeItem {
  userId: string;
  nickname: string;
}

interface TeamUser {
  userId: string;
  userNickname: string;
  roleName?: string | null;
}

interface Props {
  teamOptions?: TeamUser[];
  teamTabLabel?: string;
  showDeptTab?: boolean;
  showAllUsersTab?: boolean;
}

const props = defineProps<Props>();

const model = defineModel<AttendeeItem[]>({ default: () => [] });

const hasTeamTab = computed(() => props.teamOptions !== undefined);
const hasDeptTab = computed(() => props.showDeptTab !== false);
const hasAllUsersTab = computed(() => props.showAllUsersTab !== false);
const sourceTabs = computed(() => {
  const tabs: Array<{ key: Source; label: string }> = [];
  if (hasTeamTab.value) {
    tabs.push({ key: 'team', label: props.teamTabLabel || '团队' });
  }

  if (hasDeptTab.value) {
    tabs.push({ key: 'dept', label: '部门' });
  }

  if (hasAllUsersTab.value) {
    tabs.push({ key: 'all', label: '全部用户' });
  }
  return tabs;
});

const getInitialSource = (): Source => {
  if (hasTeamTab.value) return 'team';
  if (hasDeptTab.value) return 'dept';
  return 'all';
};

const source = ref<Source>(getInitialSource());
const popoverVisible = ref(false);
const currentDeptId = ref<string | null>(null);
const treeSearch = ref('');
const userSearch = ref('');
const hideSelected = ref(false);
const allUsers = ref<Api.SystemManage.UserSimple[]>([]);
const deptTree = ref<Api.SystemManage.DeptSimple[]>([]);
const allUsersLoading = ref(false);
const deptTreeLoading = ref(false);
let allUsersLoaded = false;
let deptTreeLoaded = false;

const selectedIdSet = computed(() => new Set(model.value.map(item => item.userId)));
const selectedCount = computed(() => model.value.length);
const referenceSelectedItems = computed(() => model.value.slice(0, 3));
const referenceOverflowCount = computed(() => Math.max(model.value.length - referenceSelectedItems.value.length, 0));

const teamUsers = computed<Api.SystemManage.UserSimple[]>(() =>
  (props.teamOptions ?? []).map(item => ({
    id: item.userId,
    nickname: item.userNickname,
    deptName: item.roleName ?? null
  }))
);

const mergedUserMap = computed(() => {
  const map = new Map<string, Api.SystemManage.UserSimple>();

  for (const user of allUsers.value) {
    map.set(user.id, user);
  }

  for (const user of teamUsers.value) {
    if (!map.has(user.id)) {
      map.set(user.id, user);
    }
  }

  return map;
});

const currentSourceUsers = computed(() => {
  if (!isSourceAvailable(source.value)) {
    return [];
  }

  if (source.value === 'team') {
    return teamUsers.value;
  }

  if (source.value === 'all') {
    return allUsers.value;
  }

  if (!currentDeptId.value) {
    return allUsers.value;
  }

  const node = findDeptNode(deptTree.value, currentDeptId.value);
  if (!node) {
    return allUsers.value;
  }

  const deptIds = new Set(collectDeptIds(node));
  return allUsers.value.filter(user => user.deptId && deptIds.has(user.deptId));
});

const filteredUsers = computed(() => {
  const keyword = userSearch.value.trim().toLowerCase();
  let list = currentSourceUsers.value;

  if (hideSelected.value) {
    list = list.filter(item => !selectedIdSet.value.has(item.id));
  }

  if (!keyword) {
    return list;
  }

  return list.filter(item => {
    return (
      item.nickname.toLowerCase().includes(keyword) ||
      (item.username ?? '').toLowerCase().includes(keyword) ||
      (item.deptName ?? '').toLowerCase().includes(keyword)
    );
  });
});

const deptTreeProps = { children: 'children', label: 'name' } as const;

async function ensureAllUsers() {
  if (allUsersLoaded) {
    return;
  }

  allUsersLoading.value = true;
  const { error, data } = await fetchGetUserSimpleList();
  allUsersLoading.value = false;

  if (!error && data) {
    allUsers.value = data;
    allUsersLoaded = true;
  }
}

async function ensureDeptTree() {
  if (deptTreeLoaded) {
    return;
  }

  deptTreeLoading.value = true;
  const { error, data } = await fetchGetDeptSimpleList();
  deptTreeLoading.value = false;

  if (!error && data) {
    deptTree.value = buildMenuTree(data);
    deptTreeLoaded = true;
  }
}

async function switchSource(next: Source) {
  if (!isSourceAvailable(next)) {
    return;
  }

  if (source.value === next) {
    return;
  }

  source.value = next;
  userSearch.value = '';
  treeSearch.value = '';
  currentDeptId.value = null;

  if (next === 'all') {
    await ensureAllUsers();
  }

  if (next === 'dept') {
    await Promise.all([ensureAllUsers(), ensureDeptTree()]);
  }
}

function isSourceAvailable(next: Source) {
  return sourceTabs.value.some(tab => tab.key === next);
}

async function syncSourceWithAvailableTabs() {
  if (isSourceAvailable(source.value)) {
    return;
  }

  const fallback = sourceTabs.value[0]?.key;

  if (fallback) {
    await switchSource(fallback);
  }
}

async function preloadCurrentSource() {
  if (!isSourceAvailable(source.value)) {
    return;
  }

  if (source.value === 'all') {
    await ensureAllUsers();
  }

  if (source.value === 'dept') {
    await Promise.all([ensureAllUsers(), ensureDeptTree()]);
  }
}

function handleVisibleChange(value: boolean) {
  popoverVisible.value = value;

  if (value) {
    preloadCurrentSource();
  }
}

function normalizeUser(user: Api.SystemManage.UserSimple): AttendeeItem {
  return {
    userId: user.id,
    nickname: user.nickname
  };
}

function toggleUser(user: Api.SystemManage.UserSimple) {
  if (selectedIdSet.value.has(user.id)) {
    model.value = model.value.filter(item => item.userId !== user.id);
    return;
  }

  model.value = [...model.value, normalizeUser(user)];
}

function removeUser(userId: string) {
  model.value = model.value.filter(item => item.userId !== userId);
}

function clearSelected() {
  model.value = [];
}

function collectDeptIds(node: Api.SystemManage.DeptSimple): string[] {
  const ids = [String(node.id)];

  if (node.children?.length) {
    for (const child of node.children) {
      ids.push(...collectDeptIds(child));
    }
  }

  return ids;
}

function findDeptNode(list: Api.SystemManage.DeptSimple[], id: string): Api.SystemManage.DeptSimple | null {
  for (const node of list) {
    if (String(node.id) === id) {
      return node;
    }

    if (node.children?.length) {
      const matched = findDeptNode(node.children, id);

      if (matched) {
        return matched;
      }
    }
  }

  return null;
}

function getDeptUsers(node: Api.SystemManage.DeptSimple) {
  const deptIds = new Set(collectDeptIds(node));
  return allUsers.value.filter(user => user.deptId && deptIds.has(user.deptId));
}

function getDeptCheckState(node: Api.SystemManage.DeptSimple): TreeCheckState {
  const users = getDeptUsers(node);

  if (!users.length) {
    return 'none';
  }

  const selectedCountInDept = users.filter(user => selectedIdSet.value.has(user.id)).length;

  if (selectedCountInDept === 0) {
    return 'none';
  }

  if (selectedCountInDept === users.length) {
    return 'all';
  }

  return 'partial';
}

function getDeptCheckStateClass(node: Api.SystemManage.DeptSimple) {
  const state = getDeptCheckState(node);

  return {
    'is-checked': state === 'all',
    'is-partial': state === 'partial'
  };
}

function toggleDeptCheck(node: Api.SystemManage.DeptSimple) {
  const users = getDeptUsers(node);

  if (!users.length) {
    return;
  }

  const state = getDeptCheckState(node);
  const selectedMap = new Map(model.value.map(item => [item.userId, item]));

  if (state === 'all') {
    users.forEach(user => selectedMap.delete(user.id));
  } else {
    users.forEach(user => selectedMap.set(user.id, normalizeUser(user)));
  }

  model.value = Array.from(selectedMap.values());
}

function handleDeptNodeClick(node: Api.SystemManage.DeptSimple) {
  currentDeptId.value = String(node.id);
}

function getDeptMetaText(node: Api.SystemManage.DeptSimple) {
  const count = getDeptUsers(node).length;

  return count > 0 ? `${count} 人` : '';
}

function matchDeptKeyword(node: Api.SystemManage.DeptSimple, keyword: string): boolean {
  if (!keyword) {
    return true;
  }

  if (node.name.toLowerCase().includes(keyword)) {
    return true;
  }

  return Boolean(node.children?.some(child => matchDeptKeyword(child, keyword)));
}

const visibleDeptTree = computed(() => {
  const keyword = treeSearch.value.trim().toLowerCase();

  if (!keyword) {
    return deptTree.value;
  }

  return deptTree.value.filter(node => matchDeptKeyword(node, keyword));
});

function getSelectedName(item: AttendeeItem) {
  return mergedUserMap.value.get(item.userId)?.nickname || item.nickname || item.userId;
}

function getUserDeptText(user: Api.SystemManage.UserSimple) {
  return user.deptName || '--';
}

watch(
  () => props.teamOptions,
  () => {
    syncSourceWithAvailableTabs();

    const validTeamIds = new Set((props.teamOptions ?? []).map(item => item.userId));
    const otherSelected = model.value.filter(item => !validTeamIds.has(item.userId));
    const teamSelected = model.value.filter(item => validTeamIds.has(item.userId));

    model.value = [...teamSelected, ...otherSelected];
  }
);

watch(
  () => sourceTabs.value.map(tab => tab.key).join(','),
  () => {
    syncSourceWithAvailableTabs();
  }
);

onMounted(() => {
  syncSourceWithAvailableTabs().then(() => preloadCurrentSource());
});
</script>

<template>
  <div class="attendee-picker">
    <ElPopover
      :visible="popoverVisible"
      trigger="click"
      placement="bottom-start"
      :width="720"
      popper-class="attendee-picker__popper"
      @update:visible="handleVisibleChange"
    >
      <template #reference>
        <div
          class="attendee-picker__reference"
          :class="{ 'is-focus': popoverVisible }"
          tabindex="0"
          @keydown.enter.prevent="handleVisibleChange(true)"
          @keydown.space.prevent="handleVisibleChange(true)"
        >
          <div v-if="model.length" class="attendee-picker__reference-chips">
            <span v-for="item in referenceSelectedItems" :key="item.userId" class="attendee-picker__reference-chip">
              <IconEpUser class="attendee-picker__reference-chip-icon" />
              <span class="attendee-picker__reference-chip-name">{{ getSelectedName(item) }}</span>
              <button
                type="button"
                class="attendee-picker__reference-chip-remove"
                @click.stop="removeUser(item.userId)"
              >
                ×
              </button>
            </span>
            <span v-if="referenceOverflowCount" class="attendee-picker__reference-count">
              +{{ referenceOverflowCount }}
            </span>
          </div>
          <span v-else class="attendee-picker__placeholder">请选择参会人</span>
          <span class="attendee-picker__arrow" :class="{ 'is-open': popoverVisible }" />
        </div>
      </template>

      <div class="attendee-picker__dropdown">
        <template v-if="sourceTabs.length">
          <div class="attendee-picker__tabs">
            <button
              v-for="tab in sourceTabs"
              :key="tab.key"
              type="button"
              class="attendee-picker__tab"
              :class="{ 'is-active': source === tab.key }"
              @click="switchSource(tab.key)"
            >
              {{ tab.label }}
            </button>
          </div>

          <div class="attendee-picker__body" :class="{ 'is-with-tree': source === 'dept' }">
            <div v-if="source === 'dept'" class="attendee-picker__panel attendee-picker__panel--tree">
              <div class="attendee-picker__panel-head">部门</div>
              <div class="attendee-picker__search">
                <ElInput v-model="treeSearch" size="small" clearable placeholder="搜索部门..." />
              </div>
              <div v-loading="deptTreeLoading" class="attendee-picker__panel-body">
                <ElTree
                  :data="visibleDeptTree"
                  :props="deptTreeProps"
                  node-key="id"
                  :expand-on-click-node="false"
                  :default-expand-all="true"
                  :indent="14"
                  class="attendee-picker__tree"
                  @node-click="handleDeptNodeClick"
                >
                  <template #default="{ data }">
                    <div class="attendee-picker__node" :class="{ 'is-active': currentDeptId === String(data.id) }">
                      <span
                        class="attendee-picker__check"
                        :class="getDeptCheckStateClass(data)"
                        @click.stop="toggleDeptCheck(data)"
                      />
                      <IconEpOfficeBuilding class="attendee-picker__node-icon" />
                      <span class="attendee-picker__node-label">{{ data.name }}</span>
                      <span v-if="getDeptMetaText(data)" class="attendee-picker__node-meta">
                        {{ getDeptMetaText(data) }}
                      </span>
                    </div>
                  </template>
                </ElTree>
              </div>
            </div>

            <div class="attendee-picker__panel attendee-picker__panel--users">
              <div class="attendee-picker__panel-head attendee-picker__panel-head--users">
                <span>
                  候选用户(
                  <span>{{ filteredUsers.length }}</span>
                  人)
                </span>
                <ElCheckbox v-model="hideSelected" size="small">隐藏已选</ElCheckbox>
              </div>
              <div class="attendee-picker__search">
                <ElInput v-model="userSearch" size="small" clearable placeholder="搜索用户名 / 部门..." />
              </div>
              <div v-loading="allUsersLoading" class="attendee-picker__panel-body">
                <div v-if="!filteredUsers.length" class="attendee-picker__empty">暂无匹配用户</div>
                <div
                  v-for="user in filteredUsers"
                  :key="user.id"
                  class="attendee-picker__user-row"
                  @click="toggleUser(user)"
                >
                  <span class="attendee-picker__check" :class="{ 'is-checked': selectedIdSet.has(user.id) }" />
                  <span class="attendee-picker__avatar">{{ user.nickname.slice(0, 1) }}</span>
                  <div class="attendee-picker__user-main">
                    <div class="attendee-picker__user-name">{{ user.nickname }}</div>
                    <div class="attendee-picker__user-meta">{{ getUserDeptText(user) }}</div>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div class="attendee-picker__selected">
            <div class="attendee-picker__selected-head">
              <span>
                已选
                <strong>{{ selectedCount }}</strong>
                人
              </span>
              <button type="button" class="attendee-picker__link" @click="clearSelected">清空</button>
            </div>
            <div v-if="!model.length" class="attendee-picker__selected-empty">请选择参会人</div>
            <div v-else class="attendee-picker__chips">
              <span v-for="item in model" :key="item.userId" class="attendee-picker__chip">
                <IconEpUser class="attendee-picker__chip-icon" />
                <span class="attendee-picker__chip-name">{{ getSelectedName(item) }}</span>
                <button type="button" class="attendee-picker__chip-remove" @click="removeUser(item.userId)">×</button>
              </span>
            </div>
          </div>
        </template>
        <div v-else class="attendee-picker__empty attendee-picker__empty--source">暂无可选人员来源</div>
      </div>
    </ElPopover>
  </div>
</template>

<style scoped>
.attendee-picker {
  width: 100%;
}

:global(.attendee-picker__popper.el-popover) {
  width: min(720px, calc(100vw - 32px)) !important;
}

.attendee-picker__reference {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 32px;
  gap: 8px;
  padding: 1px 30px 1px 11px;
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  background: var(--el-fill-color-blank);
  box-shadow: 0 0 0 0 transparent inset;
  color: var(--el-text-color-primary);
  cursor: pointer;
  font-size: 13px;
  line-height: 30px;
  outline: none;
  position: relative;
  transition:
    border-color var(--el-transition-duration),
    box-shadow var(--el-transition-duration);
}

.attendee-picker__reference:hover,
.attendee-picker__reference.is-focus {
  border-color: var(--el-color-primary);
}

.attendee-picker__reference.is-focus {
  box-shadow: 0 0 0 1px var(--el-color-primary) inset;
}

.attendee-picker__reference-chips {
  display: flex;
  align-items: center;
  min-width: 0;
  flex: 1;
  gap: 6px;
}

.attendee-picker__reference-chip {
  display: inline-flex;
  align-items: center;
  max-width: 124px;
  height: 24px;
  gap: 4px;
  padding: 0 4px 0 7px;
  border: 1px solid var(--el-border-color);
  border-radius: 999px;
  background: var(--el-fill-color-light);
  color: var(--el-text-color-primary);
  line-height: 22px;
}

.attendee-picker__reference-chip-icon {
  flex-shrink: 0;
  color: var(--el-color-primary);
  font-size: 13px;
}

.attendee-picker__reference-chip-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attendee-picker__reference-chip-remove {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--el-text-color-secondary);
  cursor: pointer;
  font-size: 12px;
  line-height: 16px;
}

.attendee-picker__reference-chip-remove:hover {
  background: var(--el-color-danger);
  color: #fff;
}

.attendee-picker__reference-count {
  flex-shrink: 0;
  color: var(--el-color-primary);
  font-size: 12px;
}

.attendee-picker__placeholder {
  color: var(--el-text-color-placeholder);
}

.attendee-picker__arrow {
  position: absolute;
  top: 50%;
  right: 11px;
  width: 7px;
  height: 7px;
  border-right: 1px solid var(--el-text-color-placeholder);
  border-bottom: 1px solid var(--el-text-color-placeholder);
  transform: translateY(-65%) rotate(45deg);
  transition: transform var(--el-transition-duration);
}

.attendee-picker__arrow.is-open {
  transform: translateY(-35%) rotate(225deg);
}

.attendee-picker__dropdown {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.attendee-picker__tabs {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--el-border-color);
}

.attendee-picker__tab {
  margin-bottom: -1px;
  padding: 6px 14px;
  border: none;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--el-text-color-regular);
  cursor: pointer;
  font-size: 12.5px;
}

.attendee-picker__tab.is-active {
  border-bottom-color: var(--el-color-primary);
  color: var(--el-color-primary);
  font-weight: 600;
}

.attendee-picker__body {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
  min-height: 240px;
  height: min(280px, 40vh);
}

.attendee-picker__body.is-with-tree {
  grid-template-columns: 240px 1fr;
}

.attendee-picker__panel {
  display: flex;
  min-width: 0;
  overflow: hidden;
  flex-direction: column;
  border: 1px solid var(--el-border-color);
  border-radius: 8px;
  background: #fff;
}

.attendee-picker__panel-head {
  padding: 6px 10px;
  border-bottom: 1px solid var(--el-border-color);
  background: #fafbfc;
  color: var(--el-text-color-regular);
  font-size: 12px;
}

.attendee-picker__panel-head--users {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.attendee-picker__search {
  padding: 6px 10px;
  border-bottom: 1px solid var(--el-border-color);
}

.attendee-picker__panel-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

.attendee-picker__tree {
  padding: 4px;
  background: transparent;
}

.attendee-picker__tree :deep(.el-tree-node__content) {
  height: 32px;
  padding-right: 8px !important;
  border-radius: 4px;
}

.attendee-picker__tree :deep(.el-tree-node__content:hover) {
  background: var(--el-fill-color-light);
}

.attendee-picker__tree :deep(.el-tree-node__expand-icon) {
  padding: 4px;
  color: var(--el-text-color-placeholder);
  font-size: 14px;
}

.attendee-picker__node {
  display: flex;
  align-items: center;
  min-width: 0;
  height: 100%;
  flex: 1;
  gap: 8px;
  color: var(--el-text-color-primary);
  font-size: 13px;
}

.attendee-picker__node.is-active {
  color: var(--el-color-primary);
  font-weight: 500;
}

.attendee-picker__check {
  position: relative;
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  border: 1px solid var(--el-border-color);
  border-radius: 2px;
  background: var(--el-bg-color);
  cursor: pointer;
}

.attendee-picker__check:hover {
  border-color: var(--el-color-primary);
}

.attendee-picker__check.is-checked,
.attendee-picker__check.is-partial {
  border-color: var(--el-color-primary);
  background: var(--el-color-primary);
}

.attendee-picker__check.is-checked::after {
  position: absolute;
  top: 1px;
  left: 4px;
  width: 3px;
  height: 7px;
  border: solid #fff;
  border-width: 0 1px 1px 0;
  content: '';
  transform: rotate(45deg);
}

.attendee-picker__check.is-partial::after {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 8px;
  height: 2px;
  margin: -1px 0 0 -4px;
  border-radius: 1px;
  background: #fff;
  content: '';
}

.attendee-picker__node-icon {
  flex-shrink: 0;
  color: var(--el-text-color-secondary);
  font-size: 15px;
}

.attendee-picker__node-label {
  min-width: 0;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attendee-picker__node-meta {
  flex-shrink: 0;
  padding-left: 6px;
  color: var(--el-text-color-placeholder);
  font-size: 12px;
}

.attendee-picker__user-row {
  display: flex;
  align-items: center;
  height: 42px;
  gap: 10px;
  padding: 0 10px;
  border-bottom: 1px solid var(--el-border-color-lighter);
  cursor: pointer;
}

.attendee-picker__user-row:hover {
  background: var(--el-fill-color);
}

.attendee-picker__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border-radius: 50%;
  background: linear-gradient(135deg, #c7d2fe, #93c5fd);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
}

.attendee-picker__user-main {
  min-width: 0;
  flex: 1;
  overflow: hidden;
}

.attendee-picker__user-name,
.attendee-picker__user-meta {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attendee-picker__user-name {
  color: var(--el-text-color-primary);
  font-size: 13px;
}

.attendee-picker__user-meta {
  margin-top: 2px;
  color: var(--el-text-color-placeholder);
  font-size: 11.5px;
}

.attendee-picker__empty {
  padding: 40px 0;
  color: var(--el-text-color-placeholder);
  font-size: 12px;
  text-align: center;
}

.attendee-picker__selected {
  padding: 8px 12px;
  border: 1px solid var(--el-border-color);
  border-radius: 6px;
  background: #f8fafc;
}

.attendee-picker__selected-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
  color: var(--el-text-color-regular);
  font-size: 11.5px;
}

.attendee-picker__selected-head strong {
  color: var(--el-color-primary);
  font-size: 12.5px;
}

.attendee-picker__selected-empty {
  display: flex;
  align-items: center;
  min-height: 26px;
  color: var(--el-text-color-placeholder);
  font-size: 11.5px;
}

.attendee-picker__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.attendee-picker__chip {
  display: inline-flex;
  align-items: center;
  max-width: 160px;
  gap: 4px;
  padding: 2px 4px 2px 8px;
  border: 1px solid var(--el-border-color-darker);
  border-radius: 999px;
  background: #fff;
  font-size: 11.5px;
}

.attendee-picker__chip-icon {
  flex-shrink: 0;
  color: var(--el-color-primary);
  font-size: 13px;
}

.attendee-picker__chip-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attendee-picker__chip-remove {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  border: none;
  border-radius: 50%;
  background: var(--el-fill-color);
  color: var(--el-text-color-regular);
  cursor: pointer;
  font-size: 11px;
}

.attendee-picker__chip-remove:hover {
  background: var(--el-color-danger);
  color: #fff;
}

.attendee-picker__link {
  padding: 0;
  border: none;
  background: transparent;
  color: var(--el-color-danger);
  cursor: pointer;
  font-size: 11.5px;
}

.attendee-picker__link:hover {
  text-decoration: underline;
}

@media (width <= 1024px) {
  .attendee-picker__body,
  .attendee-picker__body.is-with-tree {
    grid-template-columns: 1fr;
    height: auto;
  }

  .attendee-picker__panel-body {
    max-height: 240px;
  }
}
</style>
