<template>
  <RouterView v-if="isAuthLayout" />

  <div v-else :class="shellClass">
    <aside class="sidebar">
      <div class="brand">
        <img class="brand-logo" src="/logo.svg" alt="宁波嘉恒智能科技有限公司 logo" />
        <div>
          <h1>嘉恒智能</h1>
        </div>
      </div>

      <nav class="nav-list nav-stage-list">
        <div
          v-for="stage in filteredNavStages"
          :key="stage.key"
          class="nav-stage-group"
          :class="{
            'nav-stage-group-active': isStageActive(stage),
            'nav-stage-group-expanded': isStageExpanded(stage)
          }"
        >
          <button
            type="button"
            class="nav-stage"
            :class="{ 'nav-stage-active': isStageActive(stage), 'nav-stage-has-children': visibleStageChildren(stage).length }"
            :title="`${stage.step} ${stage.label} - ${stage.desc}`"
            @click="handleStageClick(stage)"
          >
            <span class="nav-stage-step" aria-hidden="true">
              <AppIcon :name="stage.icon" />
            </span>
            <div class="nav-stage-body">
              <strong>{{ stage.label }}</strong>
            </div>
            <span v-if="visibleStageChildren(stage).length" class="nav-stage-chevron" aria-hidden="true">
              <svg viewBox="0 0 24 24" role="img">
                <path d="M8 9L12 13L16 9" />
              </svg>
            </span>
          </button>

          <div v-if="visibleStageChildren(stage).length && isStageExpanded(stage) && !sidebarCollapsed" class="nav-submenu">
            <RouterLink
              v-for="child in visibleStageChildren(stage)"
              :key="child.key"
              :to="child.to"
              class="nav-subitem"
              :class="{ 'nav-subitem-active': isChildActive(child) }"
            >
              <span class="nav-subitem-icon" aria-hidden="true">
                <AppIcon :name="child.icon || stage.icon" />
              </span>
              <span>{{ child.label }}</span>
            </RouterLink>
          </div>
        </div>
      </nav>

      <div class="sidebar-footer">
        <div class="status-chip">
          <span class="status-dot"></span>
          采购、嘉恒仓库、生产、发货、财务、售后、系统拓展已接入真实业务流
        </div>
      </div>
    </aside>

    <main class="main-panel">
      <header class="topbar">
        <div class="topbar-left">
          <button class="hamburger-container" type="button" title="折叠菜单" @click="toggleSidebar">
            <span></span>
            <span></span>
            <span></span>
          </button>
          <div class="breadcrumb-container">
            <span>首页</span>
            <span class="breadcrumb-separator">/</span>
            <strong>{{ currentTitle }}</strong>
          </div>
        </div>
        <div class="topbar-right">
          <div
            v-if="activeBroadcast"
            :key="activeBroadcast.broadcast_id"
            class="broadcast-banner"
            :class="`broadcast-${String(activeBroadcast.tone || 'INFO').toLowerCase()}`"
          >
            <span class="broadcast-speaker" aria-hidden="true">
              <svg viewBox="0 0 24 24" role="img">
                <path d="M4 10.5H7.5L16 6.5V17.5L7.5 13.5H4V10.5Z" />
                <path d="M7.5 13.5L9.2 19H12.2L10.4 14.8" />
                <path d="M18.3 9.2L20.5 8" />
                <path d="M18.7 12H21.4" />
                <path d="M18.3 14.8L20.5 16" />
              </svg>
            </span>
            <div class="broadcast-marquee" aria-live="polite">
              <div class="broadcast-marquee-track">
                <strong>{{ activeBroadcast.title }}</strong>
                <span>{{ activeBroadcast.content }}</span>
              </div>
            </div>
          </div>
          <div class="topbar-meta">
            <button class="assistant-bot-button" type="button" title="打开 AI 助手" @click="openAssistantDrawer">
              <span class="assistant-bot-wave">HI</span>
              <span class="assistant-bot-face">
                <span class="assistant-bot-eye"></span>
                <span class="assistant-bot-eye"></span>
              </span>
            </button>
            <div class="user-menu-shell">
              <button class="user-avatar-button" type="button" @click="toggleUserMenu">
                <span class="user-avatar">{{ avatarInitial }}</span>
                <span class="user-avatar-meta">
                  <strong>{{ currentUser?.display_name || "未登录" }}</strong>
                  <small>{{ currentUser?.title || "工业风管理台" }}</small>
                </span>
              </button>
              <div v-if="userMenuOpen" class="user-menu-dropdown">
                <button type="button" @click="openChangePassword">修改密码</button>
                <button v-if="isSystemAdmin" type="button" @click="openResetPassword">重置他人密码</button>
                <button type="button" class="danger-menu-item" @click="logout">退出系统</button>
              </div>
            </div>
          </div>
        </div>
      </header>

      <nav class="tags-view-container" aria-label="已打开页面">
        <span
          v-for="tag in visitedTags"
          :key="tag.fullPath"
          class="tags-view-item"
          :class="{ active: isTagActive(tag) }"
          :title="tag.title"
          @contextmenu.prevent="openTagContextMenu($event, tag)"
        >
          <button class="tags-view-open" type="button" @click="openVisitedTag(tag)">
            <span class="tags-view-title">{{ tag.title }}</span>
          </button>
          <button
            class="tags-view-close"
            aria-label="关闭页签"
            type="button"
            title="关闭"
            @click="closeVisitedTag(tag)"
          >
            ×
          </button>
        </span>
      </nav>

      <Teleport to="body">
        <div
          v-if="tagContextMenu.open"
          class="tags-context-menu"
          :style="{ left: `${tagContextMenu.x}px`, top: `${tagContextMenu.y}px` }"
          role="menu"
        >
          <button type="button" role="menuitem" @click="handleTagContextAction('current')">关闭当前</button>
          <button type="button" role="menuitem" :disabled="!canCloseLeftTags" @click="handleTagContextAction('left')">关闭左侧</button>
          <button type="button" role="menuitem" :disabled="!canCloseRightTags" @click="handleTagContextAction('right')">关闭右侧</button>
          <button type="button" role="menuitem" :disabled="visitedTags.length <= 1" @click="handleTagContextAction('others')">关闭其他</button>
          <button type="button" role="menuitem" class="tags-context-danger" @click="handleTagContextAction('all')">关闭全部</button>
        </div>
      </Teleport>

      <section class="app-main">
        <RouterView />
      </section>
    </main>
  </div>

  <Teleport to="body">
    <div v-if="assistantDrawerOpen" class="workflow-drawer-mask assistant-chat-mask" @click.self="closeAssistantDrawer">
      <aside class="assistant-chat-drawer">
        <header class="assistant-chat-head">
          <div class="assistant-chat-title">
            <span class="assistant-chat-avatar">
              <span class="assistant-bot-face">
                <span class="assistant-bot-eye"></span>
                <span class="assistant-bot-eye"></span>
              </span>
            </span>
            <div>
              <p class="eyebrow">AI 助手</p>
              <h3>嘉恒工艺助手</h3>
              <p>当前为内置占位对话，真实 LLM 可在 08 系统拓展中配置。</p>
            </div>
          </div>
          <button class="ghost-button" type="button" @click="closeAssistantDrawer">关闭</button>
        </header>

        <div class="assistant-chat-body">
          <article
            v-for="message in chatMessages"
            :key="message.id"
            class="assistant-message"
            :class="`assistant-message-${message.role}`"
          >
            <div class="assistant-message-bubble">{{ message.content }}</div>
          </article>
        </div>

        <form class="assistant-chat-input" @submit.prevent="sendAssistantMessage">
          <textarea v-model.trim="chatInput" rows="2" placeholder="输入你想问的 ERP 操作、字段含义、流程问题..."></textarea>
          <button class="primary-button" type="submit">发送</button>
        </form>
      </aside>
    </div>
  </Teleport>

  <Teleport to="body">
    <div v-if="changePasswordOpen" class="workflow-drawer-mask password-modal-mask" @click.self="closePasswordModals">
      <section class="password-modal-card">
        <header class="password-modal-head">
          <div>
            <p class="eyebrow">账号安全</p>
            <h3>修改密码</h3>
            <p>当前账号：{{ currentUser?.username }}</p>
          </div>
          <button class="ghost-button" type="button" @click="closePasswordModals">关闭</button>
        </header>
        <form class="stack-form" @submit.prevent="submitChangePassword">
          <label class="form-field">
            <span>原密码</span>
            <input v-model="changePasswordForm.old_password" type="password" autocomplete="current-password" required />
          </label>
          <label class="form-field">
            <span>新密码</span>
            <input v-model="changePasswordForm.new_password" type="password" autocomplete="new-password" minlength="6" required />
          </label>
          <label class="form-field">
            <span>确认新密码</span>
            <input v-model="changePasswordForm.confirm_password" type="password" autocomplete="new-password" minlength="6" required />
          </label>
          <button class="primary-button" type="submit" :disabled="passwordSubmitting">
            {{ passwordSubmitting ? "提交中..." : "确认修改" }}
          </button>
        </form>
      </section>
    </div>
  </Teleport>

  <Teleport to="body">
    <div v-if="resetPasswordOpen" class="workflow-drawer-mask password-modal-mask" @click.self="closePasswordModals">
      <section class="password-modal-card">
        <header class="password-modal-head">
          <div>
            <p class="eyebrow">管理员操作</p>
            <h3>重置他人密码</h3>
            <p>用于协助其他用户忘记密码时重置登录密码，仅系统管理员可用。</p>
          </div>
          <button class="ghost-button" type="button" @click="closePasswordModals">关闭</button>
        </header>
        <form class="stack-form" @submit.prevent="submitResetPassword">
          <label class="form-field">
            <span>账号</span>
            <select v-model="resetPasswordForm.username" required>
              <option disabled value="">
                {{ resetPasswordUsersLoading ? "正在加载系统账号..." : "请选择需要重置密码的账号" }}
              </option>
              <option v-for="user in resetPasswordUserOptions" :key="user.user_id || user.username" :value="user.username">
                {{ formatResetPasswordUserLabel(user) }}
              </option>
            </select>
          </label>
          <label class="form-field">
            <span>新密码</span>
            <input v-model="resetPasswordForm.new_password" type="password" autocomplete="new-password" minlength="6" required />
          </label>
          <label class="form-field">
            <span>确认新密码</span>
            <input v-model="resetPasswordForm.confirm_password" type="password" autocomplete="new-password" minlength="6" required />
          </label>
          <button class="primary-button" type="submit" :disabled="passwordSubmitting">
            {{ passwordSubmitting ? "提交中..." : "确认重置" }}
          </button>
        </form>
      </section>
    </div>
  </Teleport>

  <GlobalSearchableSelect />
  <NotificationStack />
</template>

<script setup>
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
import { RouterLink, RouterView, useRoute, useRouter } from "vue-router";

import AppIcon from "./components/AppIcon.vue";
import GlobalSearchableSelect from "./components/GlobalSearchableSelect.vue";
import NotificationStack from "./components/NotificationStack.vue";
import { useBodyScrollLock } from "./composables/useBodyScrollLock";
import { clearSession, fetchResource, postResource, readSession } from "./services/api";
import { loadSmartOperationReportConfig } from "./services/systemFeatures";
import { setupActionIconButtons } from "./utils/actionIconButtons";
import { notifyError, notifySuccess, useDomNotificationBridge } from "./utils/notifications";

const route = useRoute();
const router = useRouter();
const currentUser = ref(readSession());
const activeBroadcasts = ref([]);
const activeBroadcastIndex = ref(0);
const assistantDrawerOpen = ref(false);
const userMenuOpen = ref(false);
const changePasswordOpen = ref(false);
const resetPasswordOpen = ref(false);
const passwordSubmitting = ref(false);
const resetPasswordUsers = ref([]);
const resetPasswordUsersLoading = ref(false);
const chatInput = ref("");
const sidebarCollapsed = ref(false);
const narrowShell = ref(false);
const expandedStageKeys = ref(new Set());
const visitedTags = ref([]);
const tagContextMenu = ref({ open: false, x: 0, y: 0, tag: null });
const smartOperationReportEnabled = ref(true);
let broadcastTimer = null;
let broadcastRotateTimer = null;
let cleanupActionIconButtons = null;
const chatMessages = ref([
  {
    id: 1,
    role: "assistant",
    content: "你好，我是嘉恒工艺助手。你可以问我系统操作路径、字段含义、业务流程或异常排查。"
  }
]);
const changePasswordForm = ref({
  old_password: "",
  new_password: "",
  confirm_password: ""
});
const resetPasswordForm = ref({
  username: "",
  new_password: "",
  confirm_password: ""
});

const activeTagContextIndex = computed(() =>
  visitedTags.value.findIndex((item) => item.fullPath === tagContextMenu.value.tag?.fullPath)
);
const canCloseLeftTags = computed(() => activeTagContextIndex.value > 0);
const canCloseRightTags = computed(() => activeTagContextIndex.value >= 0 && activeTagContextIndex.value < visitedTags.value.length - 1);
const resetPasswordUserOptions = computed(() =>
  [...resetPasswordUsers.value].sort((left, right) => {
    const leftStatus = left?.status === "ACTIVE" ? 0 : 1;
    const rightStatus = right?.status === "ACTIVE" ? 0 : 1;
    if (leftStatus !== rightStatus) {
      return leftStatus - rightStatus;
    }
    return String(left?.username || "").localeCompare(String(right?.username || ""), "zh-Hans-CN");
  })
);

useDomNotificationBridge();
useBodyScrollLock(computed(() => assistantDrawerOpen.value || changePasswordOpen.value || resetPasswordOpen.value));

const navStages = [
  {
    key: "dashboard",
    step: "01",
    label: "经营总览",
    desc: "先看原材料、成品库存、生产和成本全局态势。",
    tail: "总览",
    icon: "dashboard",
    iconPaths: [
      "M4 19H20",
      "M6 16V10",
      "M11 16V6",
      "M16 16V12",
      "M5 5H19"
    ],
    to: { name: "dashboard" },
    routeNames: ["dashboard"],
    permissionsAny: ["MENU_DASHBOARD"]
  },
  {
    key: "master-data",
    step: "02",
    label: "基础资料",
    desc: "供应商名录、原材料名录、客户名录、产品需规清单和员工资料。",
    tail: "底座",
    icon: "masterData",
    iconPaths: [
      "M4 6H20",
      "M4 12H20",
      "M4 18H20",
      "M8 4V8",
      "M15 10V14",
      "M11 16V20"
    ],
    to: { name: "master-data-workspace" },
    routeNames: [
      "master-data-workspace",
      "supplier-management",
      "supplier-material-lite",
      "customer-management",
      "product-spec-lite",
      "product-management",
      "material-management",
      "bom-management",
      "process-route-management",
      "employee-management"
    ],
    permissionsAny: [
      "MENU_PRODUCT_MANAGEMENT",
      "MENU_SUPPLIER_MANAGEMENT",
      "MENU_MATERIAL_MANAGEMENT",
      "MENU_BOM_MANAGEMENT",
      "MENU_ROUTE_MANAGEMENT",
      "MENU_EMPLOYEE_MANAGEMENT",
      "MENU_SALES_PLANNING"
    ],
    children: [
      {
        key: "supplier-management",
        label: "供应商名录",
        icon: "supplier",
        to: { name: "supplier-management" },
        routeNames: ["supplier-management"],
        permission: "MENU_SUPPLIER_MANAGEMENT",
        iconPaths: [
          "M5 5H19V19H5V5Z",
          "M8 9H16",
          "M8 13H16",
          "M8 17H13"
        ]
      },
      {
        key: "supplier-material-lite",
        label: "原材料名录",
        icon: "material",
        to: { name: "supplier-material-lite" },
        routeNames: ["supplier-material-lite"],
        permissionsAny: ["MENU_SUPPLIER_MANAGEMENT", "MENU_MATERIAL_MANAGEMENT"],
        iconPaths: [
          "M6 8A3 3 0 1 0 6 14A3 3 0 0 0 6 8Z",
          "M3 20C3 17.8 4.4 16 6 16C7.6 16 9 17.8 9 20",
          "M13 6H21V12H13V6Z",
          "M13 16H21"
        ]
      },
      {
        key: "customer-management",
        label: "客户名录",
        icon: "customer",
        to: { name: "customer-management" },
        routeNames: ["customer-management"],
        permission: "MENU_SALES_PLANNING",
        iconPaths: [
          "M12 5A4 4 0 1 0 12 13A4 4 0 0 0 12 5Z",
          "M5 21C5 17.7 8 15 12 15C16 15 19 17.7 19 21",
          "M17 8H21",
          "M17 12H21"
        ]
      },
      {
        key: "product-spec-lite",
        label: "产品需规清单",
        icon: "productSpec",
        to: { name: "product-spec-lite" },
        routeNames: ["product-spec-lite"],
        permissionsAny: ["MENU_PRODUCT_MANAGEMENT", "MENU_BOM_MANAGEMENT", "MENU_ROUTE_MANAGEMENT"],
        iconPaths: [
          "M5 4H19V20H5V4Z",
          "M8 8H16",
          "M8 12H16",
          "M8 16H13"
        ]
      },
      {
        key: "employee-management",
        label: "员工管理",
        icon: "employee",
        to: { name: "employee-management" },
        routeNames: ["employee-management"],
        permission: "MENU_EMPLOYEE_MANAGEMENT",
        iconPaths: [
          "M12 5A4 4 0 1 0 12 13A4 4 0 0 0 12 5Z",
          "M5 21C5 17.7 8 15 12 15C16 15 19 17.7 19 21"
        ]
      }
    ]
  },
  {
    key: "sales-planning",
    step: "03",
    label: "订单与计划",
    desc: "销售订单和发货履约追踪。",
    tail: "接单",
    icon: "order",
    iconPaths: [
      "M7 4H17L20 7V20H4V4H7Z",
      "M17 4V8H20",
      "M8 11H16",
      "M8 15H14"
    ],
    to: { name: "sales-planning" },
    routeNames: ["sales-planning", "order-list"],
    permissionsAny: ["MENU_SALES_PLANNING"],
    children: [
      {
        key: "order-list",
        label: "销售订单列表",
        icon: "ledger",
        to: { name: "order-list" },
        routeNames: ["order-list"],
        permission: "MENU_SALES_PLANNING",
        iconPaths: [
          "M6 4H18V20H6V4Z",
          "M9 8H15",
          "M9 12H15",
          "M9 16H13"
        ]
      }
    ]
  },
  {
    key: "procurement",
    step: "04",
    label: "采购与库存",
    desc: "采购、自家料入库、质量检验和嘉恒仓库。",
    tail: "采购",
    icon: "warehouse",
    iconPaths: [
      "M4 7L12 3L20 7L12 11L4 7Z",
      "M4 7V16L12 21L20 16V7",
      "M12 11V21"
    ],
    to: { name: "procurement-workspace" },
    routeNames: [
      "procurement-workspace",
      "purchase-orders",
      "purchase-receipts",
      "quality-inspection",
      "inventory-ledger"
    ],
    permissionsAny: [
      "MENU_PURCHASE_ORDER",
      "MENU_PURCHASE_RECEIPT",
      "MENU_QUALITY_INSPECTION",
      "MENU_INVENTORY_LEDGER"
    ],
    children: [
      {
        key: "purchase-orders",
        label: "采购订单",
        icon: "purchaseOrder",
        to: { name: "purchase-orders" },
        routeNames: ["purchase-orders"],
        permission: "MENU_PURCHASE_ORDER",
        iconPaths: [
          "M6 4H16L19 7V20H6V4Z",
          "M16 4V8H19",
          "M8 11H13",
          "M8 15H12",
          "M14 16L16 18L20 13"
        ]
      },
      {
        key: "purchase-receipts",
        label: "到货入库",
        icon: "receipt",
        to: { name: "purchase-receipts" },
        routeNames: ["purchase-receipts"],
        permission: "MENU_PURCHASE_RECEIPT",
        iconPaths: [
          "M4 9L12 5L20 9L12 13L4 9Z",
          "M4 13V17L12 21L20 17V13",
          "M12 3V11",
          "M9 8L12 11L15 8"
        ]
      },
      {
        key: "quality-inspection",
        label: "质量检验",
        icon: "quality",
        to: { name: "quality-inspection" },
        routeNames: ["quality-inspection"],
        permission: "MENU_QUALITY_INSPECTION",
        iconPaths: [
          "M5 12L10 17L20 7",
          "M4 4H20V20H4V4Z"
        ]
      },
      {
        key: "inventory-ledger",
        label: "嘉恒仓库",
        icon: "warehouse",
        to: { name: "inventory-ledger" },
        routeNames: ["inventory-ledger"],
        permission: "MENU_INVENTORY_LEDGER",
        iconPaths: [
          "M4 8L12 4L20 8L12 12L4 8Z",
          "M4 12L12 16L20 12",
          "M4 16L12 20L20 16"
        ]
      }
    ]
  },
  {
    key: "production",
    step: "05",
    label: "生产执行",
    desc: "生产台账和小程序报工。",
    tail: "车间",
    icon: "production",
    iconPaths: [
      "M12 8A4 4 0 1 1 12 16A4 4 0 0 1 12 8Z",
      "M12 2V5",
      "M12 19V22",
      "M4.9 4.9L7 7",
      "M17 17L19.1 19.1",
      "M2 12H5",
      "M19 12H22",
      "M4.9 19.1L7 17",
      "M17 7L19.1 4.9"
    ],
    to: { name: "production-workspace" },
    routeNames: [
      "production-workspace",
      "production-ledger",
      "work-order-ledger",
      "operation-reports"
    ],
    permissionsAny: [
      "MENU_WORK_ORDER",
      "MENU_OPERATION_REPORT"
    ],
    children: [
      {
        key: "production-ledger",
        label: "生产台账",
        icon: "workOrder",
        to: { name: "production-ledger" },
        routeNames: ["production-ledger", "work-order-ledger"],
        permission: "MENU_WORK_ORDER",
        iconPaths: [
          "M7 4H17V20H7V4Z",
          "M9 4V2H15V4",
          "M10 9H14",
          "M10 13H13",
          "M15.5 15.5A2 2 0 1 0 15.5 19.5A2 2 0 0 0 15.5 15.5Z"
        ]
      },
      {
        key: "operation-reports",
        label: "工序报工",
        icon: "operationReport",
        to: { name: "operation-reports" },
        routeNames: ["operation-reports"],
        permission: "MENU_OPERATION_REPORT",
        iconPaths: [
          "M5 5H19V19H5V5Z",
          "M8 9H12",
          "M8 13H12",
          "M15 9L18 12L15 15",
          "M14 17H18"
        ]
      }
    ]
  },
  {
    key: "delivery",
    step: "06",
    label: "发货概览",
    desc: "发运、退货、返工和报废放在同一交付闭环。",
    tail: "交付",
    icon: "delivery",
    iconPaths: [
      "M3 7H14V17H3V7Z",
      "M14 10H18L21 13V17H14V10Z",
      "M7 20A2 2 0 1 0 7 16A2 2 0 0 0 7 20Z",
      "M17 20A2 2 0 1 0 17 16A2 2 0 0 0 17 20Z"
    ],
    to: { name: "delivery-workspace" },
    routeNames: ["delivery-workspace", "delivery-management"],
    permissionsAny: ["MENU_DELIVERY_MANAGEMENT"],
    children: [
      {
        key: "delivery-management",
        label: "发货台账",
        icon: "delivery",
        to: { name: "delivery-management" },
        routeNames: ["delivery-management"],
        permission: "MENU_DELIVERY_MANAGEMENT",
        iconPaths: [
          "M5 5H13",
          "M5 9H11",
          "M5 13H10",
          "M14 6H18L20 8V18H14V6Z",
          "M14 18L10 21L6 18"
        ]
      }
    ]
  },
  {
    key: "finance",
    step: "07",
    label: "财务分析",
    desc: "按时间刷新冲压产品材料成本核算、费用归集和利润结果。",
    tail: "财务",
    icon: "finance",
    iconPaths: [
      "M5 19V5",
      "M5 19H20",
      "M8 15L11 12L14 14L19 8",
      "M16 8H19V11"
    ],
    to: { name: "finance-reports" },
    routeNames: ["finance-reports"],
    permissionsAny: ["MENU_FINANCE_REPORT"]
  },
  {
    key: "system-management",
    step: "08",
    label: "系统管理",
    desc: "系统权限、广播通知、AI 助手和后续平台扩展统一管理。",
    tail: "系统",
    icon: "system",
    iconPaths: [
      "M5 12H19",
      "M12 5V19",
      "M7 7L17 17",
      "M17 7L7 17"
    ],
    to: { name: "system-management" },
    routeNames: ["system-management", "system-permissions", "system-extension"],
    permissionsAny: ["MENU_SYSTEM_PERMISSION", "MENU_SYSTEM_EXTENSION"],
    children: [
      {
        key: "system-permissions",
        label: "系统权限管理",
        icon: "permissions",
        to: { name: "system-permissions" },
        routeNames: ["system-permissions"],
        permission: "MENU_SYSTEM_PERMISSION",
        iconPaths: [
          "M12 4A4 4 0 1 0 12 12A4 4 0 0 0 12 4Z",
          "M5 21C5 17.7 8 15 12 15C16 15 19 17.7 19 21",
          "M17 5H21V9"
        ]
      },
      {
        key: "system-extension",
        label: "系统拓展",
        icon: "extension",
        to: { name: "system-extension" },
        routeNames: ["system-extension"],
        permission: "MENU_SYSTEM_EXTENSION",
        iconPaths: [
          "M7 4H13V8H17V14H13V20H7V14H3V8H7V4Z",
          "M9 6V2",
          "M11 6V2",
          "M9 22V18",
          "M11 22V18"
        ]
      }
    ]
  },
];

const isAuthLayout = computed(() => route.meta.layout === "auth");
const currentTitle = computed(() => route.meta.title || "嘉恒智能五金 ERP");
const shellClass = computed(() => ({
  shell: true,
  "admin-shell": true,
  "app-shell": true,
  "sidebar-collapsed": sidebarCollapsed.value,
  "app-shell-collapsed": sidebarCollapsed.value,
  "app-shell-narrow": narrowShell.value
}));
const activeBroadcast = computed(() => {
  if (!activeBroadcasts.value.length) {
    return null;
  }
  return activeBroadcasts.value[activeBroadcastIndex.value % activeBroadcasts.value.length];
});
const avatarInitial = computed(() => {
  const name = currentUser.value?.display_name || currentUser.value?.username || "JH";
  return String(name).trim().slice(0, 1).toUpperCase() || "J";
});
const isSystemAdmin = computed(() => {
  const roleCodes = currentUser.value?.role_codes || [];
  const permissionCodes = currentUser.value?.permission_codes || [];
  return (
    roleCodes.includes("ADMIN") ||
    permissionCodes.includes("MENU_SYSTEM_PERMISSION") ||
    permissionCodes.includes("MENU_SYSTEM_EXTENSION")
  );
});

function hasSystemAdminFallback(permission, roleCodes = currentUser.value?.role_codes || []) {
  return String(permission || "").startsWith("MENU_SYSTEM_") && roleCodes.includes("ADMIN");
}

const filteredNavStages = computed(() => {
  return navStages.filter((stage) => {
    if (stage.children?.length) {
      return visibleStageChildren(stage).length > 0;
    }
    return hasPermission(stage);
  });
});

function isStageActive(stage) {
  return stage.routeNames.includes(String(route.name || ""));
}

function hasPermission(item) {
  const permissionCodes = currentUser.value?.permission_codes || [];
  const roleCodes = currentUser.value?.role_codes || [];
  if (item.permission) {
    return permissionCodes.includes(item.permission) || hasSystemAdminFallback(item.permission, roleCodes);
  }
  if (item.permissionsAny?.length) {
    return item.permissionsAny.some((permission) => permissionCodes.includes(permission) || hasSystemAdminFallback(permission, roleCodes));
  }
  return true;
}

function visibleStageChildren(stage) {
  return (stage.children || []).filter((child) => {
    if (child.key === "operation-reports" && !smartOperationReportEnabled.value) {
      return false;
    }
    return hasPermission(child);
  });
}

function getStageTarget(stage) {
  return visibleStageChildren(stage)[0]?.to || stage.to;
}

function setStageExpanded(stageKey, expanded) {
  const nextKeys = new Set(expandedStageKeys.value);
  if (expanded) {
    nextKeys.add(stageKey);
  } else {
    nextKeys.delete(stageKey);
  }
  expandedStageKeys.value = nextKeys;
}

function isStageExpanded(stage) {
  return expandedStageKeys.value.has(stage.key);
}

function syncActiveStageExpansion() {
  const activeStage = filteredNavStages.value.find((stage) => isStageActive(stage) && visibleStageChildren(stage).length);
  if (activeStage) {
    setStageExpanded(activeStage.key, true);
  }
}

function handleStageClick(stage) {
  const children = visibleStageChildren(stage);
  if (!children.length) {
    expandedStageKeys.value = new Set();
    if (!isStageActive(stage)) {
      router.push(stage.to);
    }
    return;
  }

  if (isStageExpanded(stage)) {
    setStageExpanded(stage.key, false);
    return;
  }

  expandedStageKeys.value = new Set([stage.key]);
  if (!isStageActive(stage)) {
    router.push(children[0].to);
  }
}

function isChildActive(child) {
  const routeName = String(route.name || "");
  return child.routeNames?.includes(routeName) || routeName === child.to?.name;
}

function buildRouteTag(targetRoute = route) {
  if (!targetRoute?.name || targetRoute.meta?.layout === "auth") {
    return null;
  }
  return {
    name: targetRoute.name,
    path: targetRoute.path,
    fullPath: targetRoute.fullPath || targetRoute.path,
    title: targetRoute.meta?.title || "未命名页面"
  };
}

function addVisitedTag(targetRoute = route) {
  const tag = buildRouteTag(targetRoute);
  if (!tag) {
    return;
  }
  const existingIndex = visitedTags.value.findIndex((item) => item.name === tag.name);
  if (existingIndex >= 0) {
    const nextTags = [...visitedTags.value];
    nextTags.splice(existingIndex, 1, tag);
    visitedTags.value = nextTags;
    return;
  }
  visitedTags.value = [...visitedTags.value, tag];
}

function isTagActive(tag) {
  return tag.name === route.name || tag.fullPath === route.fullPath;
}

function openVisitedTag(tag) {
  closeTagContextMenu();
  if (isTagActive(tag)) {
    return;
  }
  router.push(tag.fullPath || { name: tag.name });
}

function getDefaultAccessibleRoute() {
  const firstStage = filteredNavStages.value[0];
  return firstStage ? getStageTarget(firstStage) : { name: "dashboard" };
}

function closeVisitedTag(tag) {
  closeTagContextMenu();
  const closedIndex = visitedTags.value.findIndex((item) => item.fullPath === tag.fullPath);
  if (closedIndex < 0) {
    return;
  }
  const wasActive = isTagActive(tag);
  const nextTags = visitedTags.value.filter((item) => item.fullPath !== tag.fullPath);
  visitedTags.value = nextTags;

  if (!wasActive) {
    return;
  }

  const fallbackTag = nextTags[Math.max(closedIndex - 1, 0)] || nextTags[nextTags.length - 1];
  if (fallbackTag) {
    router.push(fallbackTag.fullPath || { name: fallbackTag.name });
    return;
  }
  router.push(getDefaultAccessibleRoute());
}

function getTagRouteTarget(tag) {
  return tag?.fullPath || (tag?.name ? { name: tag.name } : getDefaultAccessibleRoute());
}

function updateVisitedTags(nextTags, fallbackTag) {
  visitedTags.value = nextTags;
  const currentStillOpen = nextTags.some((item) => isTagActive(item));
  if (currentStillOpen) {
    return;
  }
  router.push(getTagRouteTarget(fallbackTag || nextTags[nextTags.length - 1]));
}

function openTagContextMenu(event, tag) {
  const menuWidth = 148;
  const menuHeight = 188;
  tagContextMenu.value = {
    open: true,
    x: Math.max(8, Math.min(event.clientX, window.innerWidth - menuWidth - 8)),
    y: Math.max(8, Math.min(event.clientY, window.innerHeight - menuHeight - 8)),
    tag
  };
}

function closeTagContextMenu() {
  if (!tagContextMenu.value.open) {
    return;
  }
  tagContextMenu.value = { open: false, x: 0, y: 0, tag: null };
}

function handleTagContextAction(action) {
  const targetTag = tagContextMenu.value.tag;
  const targetIndex = visitedTags.value.findIndex((item) => item.fullPath === targetTag?.fullPath);
  closeTagContextMenu();
  if (action === "all") {
    updateVisitedTags([], null);
    return;
  }
  if (!targetTag || targetIndex < 0) {
    return;
  }
  if (action === "current") {
    closeVisitedTag(targetTag);
    return;
  }
  if (action === "left") {
    updateVisitedTags(visitedTags.value.slice(targetIndex), targetTag);
    return;
  }
  if (action === "right") {
    updateVisitedTags(visitedTags.value.slice(0, targetIndex + 1), targetTag);
    return;
  }
  if (action === "others") {
    updateVisitedTags([targetTag], targetTag);
  }
}

function handleGlobalKeydown(event) {
  if (event.key === "Escape") {
    closeTagContextMenu();
  }
}

function updateShellViewportState() {
  narrowShell.value = window.innerWidth < 1024;
  if (narrowShell.value) {
    sidebarCollapsed.value = true;
  }
}

watch(
  () => route.fullPath,
  () => {
    currentUser.value = readSession();
    userMenuOpen.value = false;
    closeTagContextMenu();
    syncActiveStageExpansion();
    addVisitedTag(route);
    void loadActiveBroadcast();
  },
  { immediate: true }
);

onMounted(() => {
  cleanupActionIconButtons = setupActionIconButtons();
  updateShellViewportState();
  window.addEventListener("resize", updateShellViewportState);
  window.addEventListener("click", closeTagContextMenu);
  window.addEventListener("keydown", handleGlobalKeydown);
  void loadActiveBroadcast();
  void loadSmartOperationFeature();
  broadcastTimer = window.setInterval(() => {
    void loadActiveBroadcast();
  }, 30000);
  broadcastRotateTimer = window.setInterval(() => {
    rotateBroadcast();
  }, 18000);
});

onUnmounted(() => {
  window.removeEventListener("resize", updateShellViewportState);
  window.removeEventListener("click", closeTagContextMenu);
  window.removeEventListener("keydown", handleGlobalKeydown);
  if (broadcastTimer) {
    window.clearInterval(broadcastTimer);
    broadcastTimer = null;
  }
  if (broadcastRotateTimer) {
    window.clearInterval(broadcastRotateTimer);
    broadcastRotateTimer = null;
  }
  cleanupActionIconButtons?.();
  cleanupActionIconButtons = null;
});

async function loadActiveBroadcast() {
  if (!currentUser.value) {
    activeBroadcasts.value = [];
    activeBroadcastIndex.value = 0;
    return;
  }
  try {
    const rows = await fetchResource("/system-extension/active-broadcasts", []);
    activeBroadcasts.value = Array.isArray(rows) ? rows : [];
    if (activeBroadcastIndex.value >= activeBroadcasts.value.length) {
      activeBroadcastIndex.value = 0;
    }
  } catch (error) {
    activeBroadcasts.value = [];
    activeBroadcastIndex.value = 0;
  }
}

async function loadSmartOperationFeature() {
  if (!currentUser.value) {
    smartOperationReportEnabled.value = true;
    return;
  }
  try {
    const config = await loadSmartOperationReportConfig(true);
    smartOperationReportEnabled.value = config.enabled !== false;
    syncActiveStageExpansion();
  } catch (error) {
    smartOperationReportEnabled.value = true;
  }
}

function openAssistantDrawer() {
  assistantDrawerOpen.value = true;
}

function closeAssistantDrawer() {
  assistantDrawerOpen.value = false;
}

function toggleUserMenu() {
  userMenuOpen.value = !userMenuOpen.value;
}

function resetPasswordForms() {
  changePasswordForm.value = {
    old_password: "",
    new_password: "",
    confirm_password: ""
  };
  resetPasswordForm.value = {
    username: "",
    new_password: "",
    confirm_password: ""
  };
}

function openChangePassword() {
  userMenuOpen.value = false;
  resetPasswordForms();
  changePasswordOpen.value = true;
}

function openResetPassword() {
  userMenuOpen.value = false;
  resetPasswordForms();
  resetPasswordOpen.value = true;
  void loadResetPasswordUsers();
}

function closePasswordModals() {
  changePasswordOpen.value = false;
  resetPasswordOpen.value = false;
  resetPasswordForms();
}

function toggleSidebar() {
  sidebarCollapsed.value = !sidebarCollapsed.value;
}

function rotateBroadcast() {
  if (activeBroadcasts.value.length <= 1) {
    return;
  }
  activeBroadcastIndex.value = (activeBroadcastIndex.value + 1) % activeBroadcasts.value.length;
}

async function loadResetPasswordUsers() {
  resetPasswordUsersLoading.value = true;
  try {
    const rows = await fetchResource("/system-permissions/users", []);
    resetPasswordUsers.value = Array.isArray(rows) ? rows : [];
  } finally {
    resetPasswordUsersLoading.value = false;
  }
}

function formatResetPasswordUserLabel(user) {
  const roleText = Array.isArray(user?.role_names) && user.role_names.length ? user.role_names.join("、") : "未分配角色";
  const statusText = user?.status === "ACTIVE" ? "启用" : "停用";
  return [
    user?.username || "未设置账号",
    user?.employee_name || "未关联人员",
    roleText,
    statusText
  ].join(" · ");
}

function sendAssistantMessage() {
  if (!chatInput.value) {
    return;
  }
  const userText = chatInput.value;
  chatMessages.value.push({
    id: Date.now(),
    role: "user",
    content: userText
  });
  chatInput.value = "";
  chatMessages.value.push({
    id: Date.now() + 1,
    role: "assistant",
    content: "我已收到。当前聊天窗口已就绪，后续在 08 系统拓展配置 LLM API 后，可以把这里切换为真实模型回复。现在我可以先作为操作入口，帮助你记录和梳理 ERP 问题。"
  });
}

async function submitChangePassword() {
  if (changePasswordForm.value.new_password !== changePasswordForm.value.confirm_password) {
    notifyError("两次输入的新密码不一致");
    return;
  }
  passwordSubmitting.value = true;
  try {
    const result = await postResource("/auth/password/change", {
      old_password: changePasswordForm.value.old_password,
      new_password: changePasswordForm.value.new_password
    });
    notifySuccess(result.message || "密码已修改");
    closePasswordModals();
  } catch (error) {
    notifyError(error.message || "密码修改失败");
  } finally {
    passwordSubmitting.value = false;
  }
}

async function submitResetPassword() {
  if (resetPasswordForm.value.new_password !== resetPasswordForm.value.confirm_password) {
    notifyError("两次输入的新密码不一致");
    return;
  }
  passwordSubmitting.value = true;
  try {
    const result = await postResource("/auth/password/reset", {
      username: resetPasswordForm.value.username,
      new_password: resetPasswordForm.value.new_password
    });
    notifySuccess(result.message || "密码已重置");
    closePasswordModals();
  } catch (error) {
    notifyError(error.message || "密码重置失败");
  } finally {
    passwordSubmitting.value = false;
  }
}

function logout() {
  clearSession();
  currentUser.value = null;
  activeBroadcasts.value = [];
  activeBroadcastIndex.value = 0;
  router.push({ name: "login" });
}
</script>
