<template>
  <Dialog v-model="dialogVisible" title="分配用户" width="780">
    <el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="80px">
      <el-form-item label="角色名称">
        <el-tag>{{ formData.name }}</el-tag>
      </el-form-item>
      <el-form-item label="角色标识">
        <el-tag>{{ formData.code }}</el-tag>
      </el-form-item>
      <el-form-item label="选择用户" class="transfer-form-item">
        <div class="transfer-wrapper">
          <el-transfer
            v-model="selectedUserIdList"
            :titles="['未选用户', '已选用户']"
            filterable
            filter-placeholder="搜索用户"
            :data="userList"
            :props="{ label: 'nickname', key: 'id' }"
          />
        </div>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
      <el-button @click="dialogVisible = false">取 消</el-button>
    </template>
  </Dialog>
</template>
<script lang="ts" setup>
import * as RoleApi from '@/api/system/role'
import * as UserApi from '@/api/system/user'

defineOptions({ name: 'SystemRoleAssignUserForm' })

const message = useMessage()

const dialogVisible = ref(false)
const formLoading = ref(false)
const formData = reactive({
  roleId: undefined as number | undefined,
  name: '',
  code: ''
})
const formRef = ref()

// 所有用户列表（transfer 数据源）
const userList = ref<any[]>([])
// 已选中的用户 ID 列表
const selectedUserIdList = ref<string[]>([])
// 打开弹窗时的原始已选用户 ID（用于计算新增/移除）
const originalUserIds = ref<string[]>([])

/** 打开弹窗 */
const open = async (row: RoleApi.RoleVO) => {
  dialogVisible.value = true
  resetForm()
  formData.roleId = row.id
  formData.name = row.name
  formData.code = row.code
  formLoading.value = true
  try {
    // 并行加载所有用户和已分配用户 ID
    const [allUsers, existingUserIds] = await Promise.all([
      UserApi.getSimpleUserList(),
      RoleApi.getRoleUserIdList(row.id)
    ])
    // 统一将 id 转为字符串，避免 el-transfer 因类型不一致（number vs string）导致无法移除
    userList.value = allUsers.map((item) => ({
      ...item,
      id: String(item.id),
      nickname: `${item.nickname}${item.employeeNo ? `(${item.employeeNo})` : ''}`
    }))
    const userIdSet = new Set(userList.value.map((u) => u.id))
    selectedUserIdList.value = (existingUserIds || []).map(String).filter((id) => userIdSet.has(id))
    // 保存原始已选用户 ID，用于提交时计算新增/移除
    originalUserIds.value = [...selectedUserIdList.value]
  } finally {
    formLoading.value = false
  }
}
defineExpose({ open })

/** 提交表单 */
const emit = defineEmits(['success'])
const submitForm = async () => {
  if (!formData.roleId) {
    message.error('角色信息异常')
    return
  }
  formLoading.value = true
  try {
    // 计算新增用户（当前选中但原来不在）
    const currentSet = new Set(selectedUserIdList.value)
    const originalSet = new Set(originalUserIds.value)
    const addUserIds = selectedUserIdList.value.filter((id) => !originalSet.has(id))
    // 计算移除用户（原来在但当前未选中）
    const removeUserIds = originalUserIds.value.filter((id) => !currentSet.has(id))

    if (addUserIds.length === 0 && removeUserIds.length === 0) {
      message.warning('未做任何更改')
      return
    }
    await RoleApi.assignRoleUsers({
      roleId: String(formData.roleId),
      userIds: addUserIds.length > 0 ? addUserIds : undefined,
      removeUserIds: removeUserIds.length > 0 ? removeUserIds : undefined
    })
    message.success('分配用户成功')
    dialogVisible.value = false
    emit('success')
  } finally {
    formLoading.value = false
  }
}

/** 重置 */
const resetForm = () => {
  userList.value = []
  selectedUserIdList.value = []
  originalUserIds.value = []
}
</script>

<style lang="scss" scoped>
.transfer-form-item {
  margin-bottom: 0;
}

.transfer-wrapper {
  width: 100%;
  height: 420px;
}

:deep() {
  .el-transfer {
    display: flex;
    align-items: stretch;
    height: 100%;
  }

  .el-transfer-panel {
    flex: 1;
    border: 1px solid var(--el-border-color-light);
    border-radius: 4px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }

  .el-transfer-panel__header {
    background: var(--el-fill-color-light);
    border-bottom: 1px solid var(--el-border-color-lighter);
    padding: 0 12px;
    height: 40px;
    line-height: 40px;

    .el-checkbox__label {
      font-size: 13px;
      font-weight: 500;
      color: var(--el-text-color-regular);
    }
  }

  .el-transfer-panel__body {
    flex: 1;
    overflow: hidden;

    .el-transfer-panel__list {
      height: 100%;
      padding: 4px 0;
    }
  }

  .el-transfer-panel__filter {
    padding: 8px 12px;

    .el-input__wrapper {
      border-radius: 4px;
    }
  }

  .el-transfer-panel__item {
    padding: 0 12px;
    height: 32px;
    line-height: 32px;
    transition: background-color 0.2s;

    &:hover {
      background-color: var(--el-fill-color-light);
    }
  }

  .el-transfer__buttons {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 0 16px;
    flex-shrink: 0;

    .el-transfer__button {
      width: 32px;
      height: 32px;
      border-radius: 50%;
      padding: 0;
      display: flex;
      align-items: center;
      justify-content: center;

      &:nth-child(2) {
        margin: 0;
      }
    }
  }
}
</style>
