<template>
  <el-dialog
    v-model="visible"
    :title="dialogTitle"
    width="80%"
    :show-close="false"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :before-close="handleBeforeClose"
    center
  >
    <el-form>
      <el-form-item class="role-form-item">
        <el-radio-group v-model="radio" class="role-radio-group" @change="handleChangeRole">
          <template v-for="(roles, groupName) in allRoleGroups" :key="groupName">
            <el-card class="role-group-card" shadow="hover">
              <template #header>
                <span class="group-name">{{ groupName }}</span>
              </template>
              <div class="role-group">
                <el-radio-button
                  v-for="item in roles"
                  :key="item.roleCode"
                  :label="item.roleCode"
                  size="small"
                >
                  {{ item.roleName }}
                </el-radio-button>
              </div>
            </el-card>
          </template>
        </el-radio-group>
      </el-form-item>
    </el-form>

    <template v-if="!requireSelectToClose" #footer>
      <el-button @click="handleFooterClose">关 闭</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, computed, toRef } from 'vue'
import { listAllRole } from '/@/api/admin/role'
import { Local, Session } from '/@/utils/storage'
import { useMessage } from '/@/hooks/message'

/** 弹框标题，如「角色切换」「登录角色选择」 */
const props = withDefaults(
  defineProps<{ title?: string; requireSelectToClose?: boolean }>(),
  { title: '角色切换', requireSelectToClose: false }
)
const dialogTitle = computed(() => props.title)

const visible = ref(false)
const radio = ref('')
/** 按分组名分组的角色列表：{ "未分组": [{ roleId, roleName, roleCode, ... }], ... } */
const allRoleGroups = ref<Record<string, any[]>>({})
const requireSelectToClose = toRef(props, 'requireSelectToClose')

const open = () => {
  if (visible.value) return
  visible.value = true
  listAllRole().then((res) => {
    allRoleGroups.value = res.data && typeof res.data === 'object' && !Array.isArray(res.data)
      ? res.data
      : { '未分组': Array.isArray(res.data) ? res.data : [] }
    radio.value = Local.get('roleCode')
  })
}

/** 根据 roleCode 从分组数据中查找角色 */
const findRoleByCode = (code: string) => {
  for (const roles of Object.values(allRoleGroups.value)) {
    if (!Array.isArray(roles)) continue
    const found = roles.find((r: any) => r.roleCode === code)
    if (found) return found
  }
  return null
}

const canClose = () => {
  if (!radio.value) {
    useMessage().warning('请选择一个角色')
    return false
  }
  return true
}

const handleBeforeClose = (done: () => void) => {
  if (requireSelectToClose.value) {
    useMessage().warning('请先选择登录角色')
    return
  }
  if (!canClose()) return
  done()
}

const handleFooterClose = () => {
  if (!canClose()) return
  visible.value = false
}

const handleChangeRole = (label: string) => {
  const obj = findRoleByCode(label)
  if (!obj) return
  Local.set('roleCode', obj.roleCode)
  Local.set('roleName', obj.roleName)
  Local.set('roleId', obj.roleId)
  useMessage().success('操作成功')
  // 清掉 tags 缓存，重载后只保留首页 tag
  Session.remove('tagsViewList')
  // 清除 pinia 持久化的 tagsView 路由，避免重载后先恢复旧角色菜单再被新路由覆盖前就初始化出“不存在的 tag”
  try {
    window.localStorage.removeItem('tagsViewRoutes')
  } catch (_) {}
  setTimeout(() => {
    window.location.hash = '#/home'
    window.location.reload()
  }, 500)
}

defineExpose({
  open
})
</script>

<style scoped lang="scss">
.role-form-item {
  :deep(.el-form-item__content) {
    flex-wrap: wrap;
  }
}
.role-radio-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;

  :deep(.el-radio-button) {
    margin: 0;
  }
  :deep(.el-radio-button__inner) {
    border-radius: 6px !important;
    border: 1px solid var(--el-border-color) !important;
    margin-left: 0 !important;
    line-height: 1.3;
  }
  :deep(.el-radio-button.is-active .el-radio-button__inner) {
    border-color: var(--el-color-primary) !important;
  }
}
.role-group-card {
  width: 100%;
  flex: 0 0 auto;

  :deep(.el-card__header) {
    padding: 6px 12px;
    font-size: 14px;
    font-weight: 600;
    color: var(--el-text-color-primary);
  }
  :deep(.el-card__body) {
    padding: 6px 12px 8px;
  }
}
.role-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
}
.group-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--el-text-color-primary);
}
</style>