<script setup lang="ts">
import {onMounted, ref, computed, defineAsyncComponent, type Component} from 'vue'
import {ElConfigProvider, ElMessage, ElMessageBox} from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
// 图标已移至对应组件
import 'element-plus/dist/index.css'
import {authApi} from './api/auth'
import {deviceApi, type DeviceItem, type DeviceQuota} from './api/device'
// 面板按需加载，互不影响且可缓存

const LoginDialog = defineAsyncComponent(() => import('./components/auth/LoginDialog.vue'))
const RegisterDialog = defineAsyncComponent(() => import('./components/auth/RegisterDialog.vue'))
const NavigationBar = defineAsyncComponent(() => import('./components/layout/NavigationBar.vue'))
const RakutenDashboard = defineAsyncComponent(() => import('./components/rakuten/RakutenDashboard.vue'))
const AmazonDashboard = defineAsyncComponent(() => import('./components/amazon/AmazonDashboard.vue'))
const ZebraDashboard = defineAsyncComponent(() => import('./components/zebra/ZebraDashboard.vue'))

const dashboardsMap: Record<string, Component> = {
  rakuten: RakutenDashboard,
  amazon: AmazonDashboard,
  zebra: ZebraDashboard,
}

const activeDashboard = computed<Component | null>(() => {
  if (!isAuthenticated.value) return null
  return dashboardsMap[activeMenu.value] || null
})

const isDefaultPanel = computed(() => ['rakuten', 'amazon', 'zebra'].includes(activeMenu.value))
const showHomeSplash = computed(() => !isAuthenticated.value && isDefaultPanel.value)
const showPlaceholder = computed(() => !showHomeSplash.value && !activeDashboard.value)

// 导航历史栈
const navigationHistory = ref<string[]>(['rakuten'])
const currentHistoryIndex = ref(0)

// 应用状态
const activeMenu = ref('rakuten')
const isAuthenticated = ref(false)
const showAuthDialog = ref(false)
const showRegDialog = ref(false)
const zhCnLocale = zhCn
const currentUsername = ref('')
const showDeviceDialog = ref(false)
const deviceLoading = ref(false)
const devices = ref<DeviceItem[]>([])
const deviceQuota = ref<DeviceQuota>({limit: 0, used: 0})
const userPermissions = ref<string>('')

// 菜单配置 - 复刻ERP客户端格式
const menuConfig = [
  {key: 'rakuten', name: 'Rakuten', index: 'rakuten', icon: 'R'},
  {key: 'amazon', name: 'Amazon', index: 'amazon', icon: 'A'},
  {key: 'zebra', name: 'Zebra', index: 'zebra', icon: 'Z'},
  {key: 'shopee', name: 'Shopee', index: 'shopee', icon: 'S'},
]

// 权限检查 - 复刻ERP客户端逻辑
function hasPermission(module: string) {
  // 默认显示的基础菜单（未登录时也显示）
  const defaultModules = ['rakuten', 'amazon', 'zebra']

  if (!isAuthenticated.value) {
    return defaultModules.includes(module)
  }

  const permissions = userPermissions.value
  if (!permissions) {
    return defaultModules.includes(module) // 没有权限信息时显示默认菜单
  }

  // 简化权限检查：直接检查模块名是否在权限字符串中
  return permissions.includes(module)
}

const visibleMenus = computed(() => menuConfig.filter(item => hasPermission(item.key)))

const canGoBack = computed(() => currentHistoryIndex.value > 0)
const canGoForward = computed(() => currentHistoryIndex.value < navigationHistory.value.length - 1)

function showContent() {
  const loading = document.getElementById('loading')
  if (loading) {
    loading.style.opacity = '0'
    setTimeout(() => {
      loading.style.display = 'none'
    }, 100)
  }
  const app = document.getElementById('app-root')
  if (app) app.style.opacity = '1'
}

function addToHistory(menu: string) {
  if (navigationHistory.value[currentHistoryIndex.value] !== menu) {
    navigationHistory.value = navigationHistory.value.slice(0, currentHistoryIndex.value + 1)
    navigationHistory.value.push(menu)
    currentHistoryIndex.value = navigationHistory.value.length - 1
  }
}

function goBack() {
  if (canGoBack.value) {
    currentHistoryIndex.value--
    activeMenu.value = navigationHistory.value[currentHistoryIndex.value]
  }
}

function goForward() {
  if (canGoForward.value) {
    currentHistoryIndex.value++
    activeMenu.value = navigationHistory.value[currentHistoryIndex.value]
  }
}

function reloadPage() {
  window.location.reload()
}

function handleMenuSelect(key: string) {
  // 检查是否需要认证
  const authRequiredMenus = ['rakuten', 'amazon', 'zebra', 'shopee']
  if (!isAuthenticated.value && authRequiredMenus.includes(key)) {
    showAuthDialog.value = true
    return
  }

  activeMenu.value = key
  addToHistory(key)
}

async function handleLoginSuccess(data: { token: string; permissions?: string }) {
  isAuthenticated.value = true
  showAuthDialog.value = false

  try {
    // 保存token到本地数据库
    await authApi.saveToken(data.token)

    const username = getUsernameFromToken(data.token)
    currentUsername.value = username
    userPermissions.value = data?.permissions || ''
    await deviceApi.register({username})

    // 建立SSE连接
    SSEManager.connect()
  } catch (e) {
    // 设备注册失败不影响登录流程，静默处理
    console.warn('设备注册失败:', e)
  }
}

async function logout() {
  await authApi.deleteTokenCache()
  // 清理前端状态
  isAuthenticated.value = false
  currentUsername.value = ''
  userPermissions.value = ''
  showAuthDialog.value = true
  showDeviceDialog.value = false

  // 关闭SSE连接
  SSEManager.disconnect()
}

async function handleUserClick() {
  if (!isAuthenticated.value) {
    showAuthDialog.value = true
    return
  }
  try {
    await ElMessageBox.confirm('确认退出登录？', '提示', {
      type: 'warning',
      confirmButtonText: '退出',
      cancelButtonText: '取消'
    })
    await logout()
    ElMessage.success('已退出登录')
  } catch {
  }
}

function showRegisterDialog() {
  showAuthDialog.value = false
  showRegDialog.value = true
}

function handleRegisterSuccess() {
  showRegDialog.value = false
  showAuthDialog.value = true
}

function backToLogin() {
  showRegDialog.value = false
  showAuthDialog.value = true
}

async function checkAuth() {
  const authRequiredMenus = ['rakuten', 'amazon', 'zebra', 'shopee']

  try {
    await authApi.sessionBootstrap().catch(() => undefined)
    const token = await authApi.getToken()
    if (token) {
      const response = await authApi.verifyToken(token)
      if (response?.success) {
        isAuthenticated.value = true
        currentUsername.value = getUsernameFromToken(token) || ''
        SSEManager.connect()
        return
      }
      await authApi.deleteTokenCache()
    }
  } catch {
    // 忽略
  }

  if (authRequiredMenus.includes(activeMenu.value)) {
    showAuthDialog.value = true
  }
}

async function getClientIdFromToken(token?: string) {
  try {
    let t = token
    if (!t) {
      t = await authApi.getToken()
    }
    if (!t) return ''

    const payload = JSON.parse(atob(t.split('.')[1] || ''))
    return payload.clientId || ''
  } catch {
    return ''
  }
}

function getUsernameFromToken(token: string) {
  try {
    const payload = JSON.parse(atob(token.split('.')[1] || ''))
    return payload.username || ''
  } catch {
    return ''
  }
}

// SSE管理器
const SSEManager = {
  connection: null as EventSource | null,
  async connect() {
    if (this.connection) return

    try {
      const token = await authApi.getToken()
      if (!token) return

      const clientId = await getClientIdFromToken(token)
      if (!clientId) return

      let sseUrl = 'http://192.168.1.89:8080/monitor/account/events'
      try {
        const resp = await fetch('/api/config/server')
        if (resp.ok) {
          const config = await resp.json()
          sseUrl = config.sseUrl || sseUrl
        }
      } catch {
      }

      const src = new EventSource(`${sseUrl}?clientId=${clientId}&token=${token}`)
      this.connection = src
      src.onopen = () => console.log('SSE连接已建立')
      src.onmessage = (e) => this.handleMessage(e)
      src.onerror = () => this.handleError()
    } catch (e: any) {
      console.warn('SSE连接失败:', e?.message || e)
    }
  },

  handleMessage(e: MessageEvent) {
    try {
      console.log('SSE消息:', e.data)

      const payload = JSON.parse(e.data)
      switch (payload.type) {
        case 'ready':
          console.log('SSE连接已就绪')
          break
        case 'DEVICE_REMOVED':
          logout()
          ElMessage.warning('您的设备已被移除，请重新登录')
          break
        case 'FORCE_LOGOUT':
          logout()
          ElMessage.warning('会话已失效，请重新登录')
          break
        case 'PERMISSIONS_UPDATED':
          checkAuth()
          break
      }
    } catch (err) {
      console.error('SSE消息处理失败:', err, '原始数据:', e.data)
    }
  },

  handleError() {
    this.disconnect()
    setTimeout(() => this.connect(), 3000)
  },

  disconnect() {
    if (this.connection) {
      try {
        this.connection.close()
      } catch {
      }
      this.connection = null
    }
  },
}

async function openDeviceManager() {
  if (!isAuthenticated.value) {
    showAuthDialog.value = true
    return
  }
  showDeviceDialog.value = true
  await fetchDeviceData()
}

async function fetchDeviceData() {
  if (!currentUsername.value) {
    ElMessage.warning('未获取到用户名，请重新登录')
    return
  }
  try {
    deviceLoading.value = true
    const [quota, list] = await Promise.all([
      deviceApi.getQuota(currentUsername.value),
      deviceApi.list(currentUsername.value),
    ])
    deviceQuota.value = quota || {limit: 0, used: 0}
    const clientId = await getClientIdFromToken()
    devices.value = (list || []).map(d => ({...d, isCurrent: d.deviceId === clientId})) as any
  } catch (e: any) {
    ElMessage.error(e?.message || '获取设备列表失败')
  } finally {
    deviceLoading.value = false
  }
}

async function confirmRemoveDevice(row: DeviceItem & { isCurrent?: boolean }) {
  try {
    await ElMessageBox.confirm('确定要移除该设备吗？', '你确定要移除设备吗?', {
      confirmButtonText: '确定移除',
      cancelButtonText: '取消',
      type: 'warning'
    })

    await deviceApi.remove({deviceId: row.deviceId})
    devices.value = devices.value.filter(d => d.deviceId !== row.deviceId)
    deviceQuota.value.used = Math.max(0, (deviceQuota.value.used || 0) - 1)

    // 如果是本机设备被移除，执行logout
    const clientId = await getClientIdFromToken()
    if (row.deviceId === clientId) {
      await logout()
    }

    ElMessage.success('已移除设备')
  } catch (e: any) {
    ElMessage.error('移除设备失败: ' + ((e as any)?.message || '未知错误'))
  }
}

onMounted(async () => {
  showContent()
  await checkAuth()

})
</script>

<template>
  <el-config-provider :locale="zhCnLocale">
    <div id="app-root" class="root">
      <div class="loading-container" id="loading">
        <div class="loading-spinner"></div>
      </div>

      <div class="erp-container">
        <div class="sidebar">
          <div class="user-avatar">
            <img src="/icon/icon.png" alt="logo"/>
          </div>
          <div class="menu-group-title">电商平台</div>
          <ul class="menu">
            <li
                v-for="item in visibleMenus"
                :key="item.key"
                class="menu-item"
                :class="{ active: activeMenu === item.key }"
                @click="handleMenuSelect(item.key)"
            >
              <span class="menu-text"><span class="menu-icon" :data-k="item.key">{{ item.icon }}</span>{{
                  item.name
                }}</span>
            </li>
          </ul>

        </div>

        <div class="main-content">
          <NavigationBar
              :can-go-back="canGoBack"
              :can-go-forward="canGoForward"
              :active-menu="activeMenu"
              @go-back="goBack"
              @go-forward="goForward"
              @reload="reloadPage"
              @user-click="handleUserClick"
              @open-device="openDeviceManager"/>
          <div class="content-body">
            <div
                class="dashboard-home"
                v-if="showHomeSplash">
              <div class="icon-container">
                <img src="/image/111.png" alt="ERP Logo" class="main-icon"/>
              </div>
            </div>
            <keep-alive v-if="activeDashboard">
              <component :is="activeDashboard" :key="activeMenu"/>
            </keep-alive>
            <div v-if="showPlaceholder" class="placeholder">
              <div class="placeholder-card">
                <div class="placeholder-title">{{ activeMenu.toUpperCase() }} 面板</div>
                <div class="placeholder-desc">功能开发中...</div>
              </div>
            </div>
          </div>

          <!-- 认证组件 -->
          <LoginDialog
              v-model="showAuthDialog"
              @login-success="handleLoginSuccess"
              @show-register="showRegisterDialog"/>

          <RegisterDialog
              v-model="showRegDialog"
              @register-success="handleRegisterSuccess"
              @back-to-login="backToLogin"/>

          <!-- 设备管理弹框 -->
          <el-dialog
              v-model="showDeviceDialog"
              width="560px"
              :close-on-click-modal="false"
              align-center
              class="device-dialog">
            <template #header>
              <div class="device-dialog-header">
                <img src="/icon/img.png" alt="devices" class="device-illustration"/>
                <div class="device-title">设备管理 <span class="device-count">({{ deviceQuota.used || 0 }}/{{ deviceQuota.limit || 0 }})</span></div>
                <div class="device-subtitle">当前账号可以授权绑定 {{ deviceQuota.limit }} 台设备</div>
              </div>
            </template>
            <el-table :data="devices" size="small" :loading="deviceLoading" style="width:100%" stripe>
              <el-table-column label="设备名" min-width="180">
                <template #default="scope">
                  <span>{{ scope.row.name || scope.row.deviceId }}</span>
                  <el-tag v-if="scope.row.isCurrent" size="small" type="success" style="margin-left:6px;">本机</el-tag>
                </template>
              </el-table-column>
              <el-table-column label="状态" width="90">
                <template #default="scope">
                  <el-tag :type="scope.row.status==='online' ? 'success' : 'info'" size="small">
                    {{ scope.row.status === 'online' ? '已登录' : '已登出' }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="最近" min-width="130">
                <template #default="scope">
                  <span>{{ scope.row.lastActiveAt || '-' }}</span>
                </template>
              </el-table-column>
              <el-table-column label="操作" width="100">
                <template #default="scope">
                  <el-button type="text" size="small" style="color:#F56C6C" @click="confirmRemoveDevice(scope.row)">
                    移除设备
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
            <template #footer>
              <el-button @click="showDeviceDialog=false">关闭</el-button>
            </template>
          </el-dialog>
        </div>
      </div>
    </div>
  </el-config-provider>
</template>

<style scoped>

.root {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  background-color: #f5f5f5;
  opacity: 0;
  transition: opacity 0.1s ease;
}

.loading-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  width: 100%;
  position: fixed;
  top: 0;
  left: 0;
  background-color: #f5f5f5;
  z-index: 9999;
  transition: opacity 0.1s ease;
}

.loading-spinner {
  width: 50px;
  height: 50px;
  border: 5px solid #e6e6e6;
  border-top: 5px solid #409EFF;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.erp-container {
  display: flex;
  height: 100vh;
}

.sidebar {
  width: 180px;
  min-width: 180px;
  flex-shrink: 0;
  background: #ffffff;
  border-right: 1px solid #e8eaec;
  padding: 16px 12px;
  box-sizing: border-box;
}

.platform-icons {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 12px;
}

.picon {
  width: 28px;
  height: 28px;
  object-fit: contain;
}

.user-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px 0;
  border-bottom: 1px solid #e8eaec;
  margin: 0 0 12px 0;
}

.user-avatar img {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  object-fit: contain;
  background: #ffffff;
}

.menu-group-title {
  font-size: 12px;
  color: #909399;
  margin: 8px 6px 10px;
  text-align: left; /* “电商平台”四个字靠左 */
}

.menu {
  list-style: none;
  padding: 0;
  margin: 0;
}

.menu-item {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  border-radius: 8px;
  cursor: pointer;
  color: #333333;
  margin-bottom: 4px;
}

.menu-item:hover {
  background: #f5f7fa;
}

.menu-item.active {
  background: #ecf5ff !important;
  color: #409EFF !important;
}

.menu-text {
  font-size: 14px;
}

.menu-text {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.menu-icon {
  display: inline-flex;
  width: 18px;
  height: 18px;
  border-radius: 4px;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: #fff;
}

.menu-icon[data-k="rakuten"] {
  background: #BF0000;
}

.menu-icon[data-k="amazon"] {
  background: #FF9900;
  color: #1A1A1A;
}

.menu-icon[data-k="zebra"] {
  background: #34495e;
}

.menu-icon[data-k="shopee"] {
  background: #EE4D2D;
}

.main-content {
  flex: 1;
  min-width: 0;
  position: relative;
  display: flex;
  flex-direction: column;
}

/* 导航栏和认证相关样式已移至对应组件 */

.content-body {
  position: relative;
  flex: 1;
  background: #fff;
  min-height: 0;
  overflow: hidden;
}

.dashboard-home {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #ffffff;
  z-index: 100;
}

.icon-container {
  display: flex;
  justify-content: center;
}

.main-icon {
  width: 400px;
  height: 400px;
  border-radius: 20px;
  object-fit: contain;
}

.placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fff;
}

.placeholder-card {
  background: #ffffff;
  border: 1px solid #e8eaec;
  border-radius: 12px;
  padding: 24px 28px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
  color: #2c3e50;
}

.placeholder-title {
  font-size: 18px;
  font-weight: 600;
  margin-bottom: 8px;
}

.placeholder-desc {
  font-size: 13px;
  color: #606266;
}
.device-dialog-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 12px 0 4px 0;
  margin-left: 40px;
}
.device-dialog :deep(.el-dialog__header) {
  text-align: center;
}
.device-dialog :deep(.el-dialog__body) { padding-top: 0; }
.device-illustration {
  width: 180px;
  height: auto;
  object-fit: contain;
  margin-bottom: 8px;
}
.device-title {
  font-size: 18px;
  font-weight: 600;
  color: #303133;
  margin-bottom: 6px;
}
.device-count { color: #909399; font-weight: 500; }
.device-subtitle { font-size: 12px; color: #909399; }
</style>
