<script lang="ts" setup>
/**
 * 工作台首页：按角色 layout 动态装载模块
 * 行结构（自上而下）：
 *   第一行：有驾驶舱（platform_overview/todo_center）时 = 左合并卡（卡底内嵌单行公告轮播）+ 右快捷入口（等高、内部滚动）；
 *           无驾驶舱时 = 公告轮播条全宽一行 + 快捷入口全宽一行
 *   第二行：日程日历（左 6）+ 日程待办（右 4），两列等高，待办列表内部滚动
 *   之后：角色 KPI 摘要（按 sort 依次渲染）
 * 布局由 workbench/layout 下发（xk_role_workbench_widget 按角色配置），未配置的模块不渲染
 */
import type { WorkbenchLayoutItem } from './api';

import { computed, onMounted, ref } from 'vue';

import { getWorkbenchLayoutApi } from './api';
import NoticeTicker from './components/NoticeTicker.vue';
import WidgetAdminHub from './components/WidgetAdminHub.vue';
import WorkspaceHeader from './components/WorkspaceHeader.vue';
import { KPI_WIDGET_CODES, WIDGET_COMPONENT_MAP } from './config/widgets';

/** 角色布局（后端已按 sort 排序并过滤非法 code） */
const layout = ref<WorkbenchLayoutItem[]>([]);
const loaded = ref(false);

/** 有效模块：仅保留前端已注册的组件 */
const validItems = computed(() =>
  layout.value.filter((item) => WIDGET_COMPONENT_MAP[item.widget_code]),
);

/** 平台总览项（超管/系统管理员） */
const overviewItem = computed(() =>
  validItems.value.find((item) => item.widget_code === 'platform_overview'),
);

/** 待办中心项（超管/系统管理员） */
const todoItem = computed(() =>
  validItems.value.find((item) => item.widget_code === 'todo_center'),
);

/**
 * 是否渲染顶部管理驾驶舱行：布局含总览或待办任一即启用
 * 为什么合并渲染：总览+待办同属「今日经营快照」，合并成一张卡放左列信息密度更高
 */
const hasAdminHub = computed(() => !!overviewItem.value || !!todoItem.value);

/** 快捷入口：有驾驶舱时放第一行右列（与驾驶舱等高、内部滚动），否则全宽一行 */
const quickNavItem = computed(() =>
  validItems.value.find((item) => item.widget_code === 'quick_nav'),
);

/** 日程待办：第二行右列（与日历等高，列表内部滚动） */
const calendarTodoItem = computed(() =>
  validItems.value.find((item) => item.widget_code === 'calendar_todo'),
);

/** 日程日历：第二行左列（CalendarPanel 紧凑模式，6/4 分中的 6） */
const workCalendarItem = computed(() =>
  validItems.value.find((item) => item.widget_code === 'work_calendar'),
);

/** KPI 摘要区（中部，按 sort 依次渲染；总览/待办已合并进顶部驾驶舱，需排除） */
const kpiItems = computed(() =>
  validItems.value.filter(
    (item) =>
      KPI_WIDGET_CODES.has(item.widget_code) &&
      item.widget_code !== 'platform_overview' &&
      item.widget_code !== 'todo_center',
  ),
);

/** 公告：单行轮播条（有驾驶舱时内嵌其卡底，无驾驶舱时独立全宽一行） */
const noticeItem = computed(() =>
  validItems.value.find((item) => item.widget_code === 'notice'),
);

/**
 * 拉取角色布局；失败时兜底展示快捷入口 + 公告（保证工作台不白屏）
 */
async function fetchLayout() {
  try {
    const res = await getWorkbenchLayoutApi();
    layout.value = Array.isArray(res) ? res : [];
  } catch {
    layout.value = [
      { id: 0, widget_code: 'quick_nav', title: '快捷入口', sort: 10, config: null },
      { id: 0, widget_code: 'notice', title: '最新动态', sort: 90, config: null },
    ];
  } finally {
    loaded.value = true;
  }
}

onMounted(fetchLayout);
</script>

<template>
  <div class="workspace-page">
    <div class="workspace-page__inner">
      <div class="workspace-page__section" style="--delay: 0">
        <WorkspaceHeader />
      </div>

      <template v-if="loaded">
        <!-- 第一行（有驾驶舱）：左合并卡（卡底内嵌公告轮播条）+ 右快捷入口（等高、内部滚动） -->
        <div v-if="hasAdminHub" class="workspace-page__section" style="--delay: 1">
          <div class="workspace-hero" :class="{ full: !quickNavItem }">
            <div class="workspace-hero__main">
              <WidgetAdminHub
                :overview-title="overviewItem?.title || '平台总览'"
                :todo-title="todoItem?.title || '待办中心'"
              >
                <template v-if="noticeItem" #notice>
                  <NoticeTicker />
                </template>
              </WidgetAdminHub>
            </div>
            <div v-if="quickNavItem" class="workspace-hero__side">
              <component
                :is="WIDGET_COMPONENT_MAP[quickNavItem.widget_code]"
                :title="quickNavItem.title"
              />
            </div>
          </div>
        </div>

        <!-- 无驾驶舱：公告轮播条全宽一行 + 快捷入口全宽一行 -->
        <template v-else>
          <div v-if="noticeItem" class="workspace-page__section" style="--delay: 1">
            <NoticeTicker standalone />
          </div>
          <div v-if="quickNavItem" class="workspace-page__section" style="--delay: 1">
            <component
              :is="WIDGET_COMPONENT_MAP[quickNavItem.widget_code]"
              :title="quickNavItem.title"
            />
          </div>
        </template>

        <!-- 第二行：日程日历（左 6）+ 日程待办（右 4）等高；缺一方时另一方全宽 -->
        <div
          v-if="workCalendarItem || calendarTodoItem"
          class="workspace-page__section"
          style="--delay: 2"
        >
          <div
            class="workspace-calrow"
            :class="{ 'has-side': workCalendarItem && calendarTodoItem }"
          >
            <div v-if="workCalendarItem" class="workspace-calrow__main">
              <component
                :is="WIDGET_COMPONENT_MAP[workCalendarItem.widget_code]"
                :title="workCalendarItem.title"
              />
            </div>
            <div v-if="calendarTodoItem" class="workspace-calrow__side">
              <component
                :is="WIDGET_COMPONENT_MAP[calendarTodoItem.widget_code]"
                :title="calendarTodoItem.title"
              />
            </div>
          </div>
        </div>

        <!-- 角色 KPI 摘要 -->
        <div
          v-for="(item, index) in kpiItems"
          :key="item.widget_code"
          :style="{ '--delay': index + 3 }"
          class="workspace-page__section"
        >
          <component
            :is="WIDGET_COMPONENT_MAP[item.widget_code]"
            :title="item.title"
          />
        </div>
      </template>
    </div>
  </div>
</template>

<style scoped>
.workspace-page {
  padding: 20px;
}

/* 居中限宽：大屏下不至于被拉太宽，更显精致 */
.workspace-page__inner {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 1400px;
  margin: 0 auto;
}

/* 顶部驾驶舱行：左合并卡（58%）+ 右快捷入口（42%），窄屏退化为上下堆叠 */
.workspace-hero {
  display: grid;
  grid-template-columns: minmax(0, 58fr) minmax(0, 42fr);
  gap: 16px;
  align-items: stretch;
}

/* 未配置快捷入口时驾驶舱独占整行 */
.workspace-hero.full {
  grid-template-columns: 1fr;
}

.workspace-hero__main,
.workspace-hero__side {
  min-width: 0;
}

/* 行高完全由左侧驾驶舱决定：快捷入口绝对定位填充，不参与行高计算（钉住项多时只内部滚动，不把首行撑高） */
.workspace-hero__side {
  position: relative;
}

/* 快捷入口改纵向弹性布局：头部固定，内容区吃掉剩余高度并内部滚动（与驾驶舱等高的关键） */
.workspace-hero__side :deep(.quick-entry) {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
}

/* 42% 列宽下瓷砖按格宽自适应列数；align-content 顶对齐避免行间被拉开 */
.workspace-hero__side :deep(.quick-entry__grid) {
  flex: 1;
  grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  align-content: start;
  min-height: 0;
  overflow-y: auto;
}

/* 搜索结果同样吃满剩余高度滚动（解除组件内 320px 限高） */
.workspace-hero__side :deep(.quick-entry__results) {
  flex: 1;
  min-height: 0;
  max-height: none;
  overflow-y: auto;
}

@media (max-width: 1024px) {
  .workspace-hero {
    grid-template-columns: 1fr;
  }

  /* 堆叠后取消绝对定位（否则高度塌陷），瓷砖内容自然撑高不滚动 */
  .workspace-hero__side :deep(.quick-entry) {
    position: static;
  }

  .workspace-hero__side :deep(.quick-entry__grid) {
    overflow-y: visible;
  }
}

/* 第二行：日程日历（80%）+ 日程待办（20%）等高；行高由日历内容决定 */
.workspace-calrow {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  align-items: stretch;
}

.workspace-calrow.has-side {
  grid-template-columns: minmax(0, 8fr) minmax(0, 2fr);
}

.workspace-calrow__main,
.workspace-calrow__side {
  min-width: 0;
}

/* 行高完全由日历决定：待办卡绝对定位填充，不参与行高计算（待办再多也只在卡内滚动） */
.workspace-calrow__side {
  position: relative;
}

.workspace-calrow__side :deep(.calendar-todo-widget) {
  position: absolute;
  inset: 0;
}

@media (max-width: 1024px) {
  .workspace-calrow.has-side {
    grid-template-columns: 1fr;
  }

  /* 堆叠后取消绝对定位（否则高度塌陷），列表限高由组件内媒体查询接管 */
  .workspace-calrow__side :deep(.calendar-todo-widget) {
    position: static;
  }
}

/* 区块交错入场：轻微上移淡入，节奏 60ms/块 */
.workspace-page__section {
  animation: ws-fade-up 0.4s cubic-bezier(0.4, 0, 0.2, 1) both;
  animation-delay: calc(var(--delay, 0) * 60ms);
}

@keyframes ws-fade-up {
  from {
    opacity: 0;
    transform: translateY(8px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .workspace-page__section {
    animation: none;
  }
}
</style>
