<template>
  <q-layout view="hHh lpr fFf" class="user-shell user-center-shell">
    <q-header class="user-center-header">
      <q-toolbar class="user-center-topbar">
        <q-btn flat round dense icon="menu" @click="toggleDrawer">
          <q-tooltip>导航</q-tooltip>
        </q-btn>

        <button class="user-center-brand" type="button" @click="goHome">
          <span class="auth-logo">
            <q-icon name="shield" size="25px" />
          </span>
          <span>
            <strong>Dpz.Core 用户中心</strong>
            <small>Identity Workspace</small>
          </span>
        </button>

        <q-space />

        <div class="user-route-pill">
          <q-icon :name="route.meta.icon" />
          <span>{{ route.meta.title }}</span>
        </div>

        <q-btn flat round icon="logout" @click="signOut">
          <q-tooltip>退出登录</q-tooltip>
        </q-btn>
        <q-btn
          round
          flat
          :icon="$q.dark.isActive ? 'light_mode' : 'dark_mode'"
          @click="$q.dark.toggle()"
        >
          <q-tooltip>{{
            $q.dark.isActive ? "浅色模式" : "深色模式"
          }}</q-tooltip>
        </q-btn>
      </q-toolbar>
    </q-header>

    <q-drawer
      v-model="drawer"
      show-if-above
      :width="drawerWidth"
      :mini="miniState"
      :mini-width="64"
      class="user-center-drawer"
      @click.capture="handleDrawerClick"
    >
      <div class="user-drawer-panel">
        <div class="user-profile-tile">
          <q-avatar size="54px">
            <img v-if="currentUser.avatar" :src="currentUser.avatar" alt="" />
            <q-icon v-else name="person" size="34px" />
          </q-avatar>
          <div>
            <strong>{{
              currentUser.name || currentUser.id || "Dpz.Core 用户"
            }}</strong>
            <small>{{ currentUser.id || "Identity verified" }}</small>
          </div>
        </div>

        <div class="user-center-nav">
          <section
            v-for="group in menuGroups"
            :key="group.key"
            class="user-center-nav-group"
          >
            <div class="user-center-nav-group__title">
              <span>{{ group.label }}</span>
              <small>{{ group.items.length }}</small>
            </div>
            <q-list class="user-center-nav-list">
              <q-item
                v-for="item in group.items"
                :key="item.key"
                clickable
                :active="activeNavKey === item.key"
                class="user-center-nav__item"
                :data-accent="item.accent"
                @click="navigate(item.hash)"
              >
                <q-item-section avatar>
                  <q-icon :name="item.icon" />
                </q-item-section>
                <q-item-section>
                  <q-item-label>{{ item.label }}</q-item-label>
                  <q-item-label caption>{{ item.subtitle }}</q-item-label>
                </q-item-section>
              </q-item>
            </q-list>
          </section>
        </div>
      </div>
    </q-drawer>

    <q-page-container>
      <q-page class="user-center-page-shell">
        <div class="user-decor" aria-hidden="true">
          <div class="user-grid" />
          <div class="user-scan" />
          <div class="user-beam user-beam--a" />
          <div class="user-beam user-beam--b" />
        </div>
        <div class="user-center-container">
          <router-view v-slot="{ Component, route: viewRoute }">
            <component
              :is="Component"
              :key="viewRoute.matched[0]?.name"
              v-bind="currentComponentProps"
              @profile-updated="handleProfileUpdated"
            />
          </router-view>
        </div>
      </q-page>
    </q-page-container>
  </q-layout>
</template>

<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
import { useQuasar } from "quasar";
import { useRoute, useRouter } from "vue-router";
import type { UserCenterPayload } from "../models/AuthModels";
import { PageContext } from "../services/PageContext";
import { userMenu } from "./user/userMenu";

const $q = useQuasar();
$q.dark.set("auto");
const context = PageContext.read<UserCenterPayload>();
const currentUser = ref({
  ...(context.user ?? { id: "", name: "", avatar: "" }),
});
const drawer = ref(false);
const miniState = ref(false);
let drawerToggleLocked = false;
const route = useRoute();
const router = useRouter();

const activeNavKey = computed(
  () => String(route.meta.key ?? route.name),
);
const drawerWidth = computed(() => ($q.screen.gt.lg ? 276 : 248));
const menuGroups = computed(() => [
  {
    key: "account",
    label: "身份与安全",
    items: userMenu.filter((item) => item.group === "account"),
  },
  {
    key: "content",
    label: "内容资产",
    items: userMenu.filter((item) => item.group === "content"),
  },
]);
const currentComponentProps = computed(() =>
  route.meta.key === "articles"
    ? { articleHost: context.payload?.webHost }
    : {},
);

watch(
  () => route.meta.title,
  (title) => {
    document.title = `${title ?? "工作台"} - Dpz.Core 用户中心`;
  },
  { immediate: true },
);

onMounted(() => {
  document.body.classList.add("user-center-body");
});

onBeforeUnmount(() => {
  document.body.classList.remove("user-center-body");
});

function navigate(hash: string) {
  void router.push(hash.replace(/^#/, ""));
  if ($q.screen.lt.md) {
    drawer.value = false;
  }
}

function goHome() {
  window.location.href = "/";
}

function signOut() {
  $q.dialog({
    title: "退出登录",
    message: "确认退出当前认证中心会话?",
    cancel: true,
    persistent: true,
  }).onOk(() => {
    window.location.href = "/sign-out";
  });
}

function handleProfileUpdated(profile: {
  displayName: string;
  avatar?: string;
}) {
  currentUser.value = {
    ...currentUser.value,
    name: profile.displayName,
    avatar: profile.avatar ?? currentUser.value.avatar,
  };
}

function toggleDrawer(event: Event) {
  event.preventDefault();
  event.stopPropagation();
  if (drawerToggleLocked) {
    return;
  }

  drawerToggleLocked = true;
  if ($q.screen.gt.md) {
    miniState.value = !miniState.value;
  } else {
    drawer.value = !drawer.value;
  }
  window.setTimeout(() => {
    drawerToggleLocked = false;
  }, 120);
}

function handleDrawerClick() {
  if ($q.screen.lt.md || !miniState.value || drawerToggleLocked) {
    return;
  }

  drawerToggleLocked = true;
  miniState.value = false;
  window.setTimeout(() => {
    drawerToggleLocked = false;
  }, 120);
}
</script>
评论加载中...