<template>
  <el-container class="layout">
    <el-header class="layout-header">
      <div class="main-title">博客管理后台</div>
      <div class="nav-btns-right">
        <el-button link @click="toggleDarkMode" style="color: #fff; font-size: 18px; margin-right: 12px;">
          <Moon v-if="!isDark" style="width: 18px" />
          <Sunny v-else style="width: 18px" />
        </el-button>
        <el-dropdown @command="dropdownMenuCommand">
          <el-button link type="primary">
            <UserFilled style="width: 18px" />
            {{ realname }}
            <ArrowDown style="width: 18px"/>
          </el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item command="home">返回首页</el-dropdown-item>
              <el-dropdown-item command="changePassword">修改密码</el-dropdown-item>
              <el-dropdown-item command="logout" divided>退出</el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
    </el-header>
    <el-container>
      <el-aside width="200px">
        <el-menu :default-active="defaultActiveMenuKey" :default-openeds="openMenuNames" style="height: 100%;">
          <el-sub-menu v-for="menu in menus" :key="menu.name" :index="menu.name">
            <template #title>
              <component :is="menu.icon" style="width: 18px; margin-right: 5px;"></component>
              <span>{{menu.title}}</span>
            </template>
            <el-menu-item v-for="(subItem,subIndex) in menu.child" :key="subIndex" :index="subItem.path" @click="openMenu(subItem.path)">
              {{subItem.title}}
            </el-menu-item>
          </el-sub-menu>
        </el-menu>
      </el-aside>
      <el-main class="layout-main">
        <div class="layout-tabs">
          <el-tabs type="card" class="nav-tabs" v-model="store.state.activeTab" @tab-change="openMenu" @tab-remove="removeTab">
            <el-tab-pane label="首页" name="/"></el-tab-pane>
            <el-tab-pane v-for="tab in store.state.tabs" :key="tab.name" :label="tab.title" :name="tab.path" closable></el-tab-pane>
          </el-tabs>
        </div>
        <div class="layout-content">
          <router-view class="main-view" v-slot="{ Component }" v-if="mainViewReady">
            <keep-alive :include="keepViews">
              <component :is="Component" />
            </keep-alive>
          </router-view>
        </div>
        <div class="layout-copy">2016-{{currentYear}} &copy; colorfulsweet 上次更新：{{ version }}</div>
      </el-main>
    </el-container>
  </el-container>

  <el-dialog v-model="changePwdModal" title="修改密码" width="420px" @closed="resetPwdForm">
    <el-form ref="changePwdForm" :model="changePwdData" :rules="changePwdRules" :label-width="100">
      <el-form-item label="旧密码" prop="oldPassword">
        <el-input v-model="changePwdData.oldPassword" type="password" show-password />
      </el-form-item>
      <el-form-item label="新密码" prop="newPassword">
        <el-input v-model="changePwdData.newPassword" type="password" show-password />
      </el-form-item>
      <el-form-item label="确认密码" prop="confirmPassword">
        <el-input v-model="changePwdData.confirmPassword" type="password" show-password />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="changePwdModal = false">取消</el-button>
        <el-button type="primary" @click="submitChangePassword" :loading="changePwdLoading">确定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, computed, nextTick } from 'vue'
import { useStore } from 'vuex'
import { useRouter, useRoute } from 'vue-router'
import menus from '../config/menu'
import http from '@/utils/http'
import { ElMessage } from 'element-plus'
import { VForm } from '@/types'

const store = useStore()
const router = useRouter()
const route = useRoute()

const version = process.env.VERSION
const currentYear = new Date().getFullYear()
const defaultActiveMenuKey = ref<string | null>(null)
const openMenuNames = ref<string[]>([])
const mainViewReady = ref(false)

const isDark = ref(false)
function applyDarkMode(dark: boolean) {
  isDark.value = dark
  document.documentElement.classList.toggle('dark', dark)
}
function toggleDarkMode() {
  const next = !isDark.value
  applyDarkMode(next)
  localStorage.setItem('theme_mode', next ? 'dark' : 'light')
}
// 初始化主题
;(() => {
  const saved = localStorage.getItem('theme_mode')
  if (saved) {
    applyDarkMode(saved === 'dark')
  } else {
    const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
    applyDarkMode(prefersDark)
  }
  window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
    if (!localStorage.getItem('theme_mode')) {
      applyDarkMode(e.matches)
    }
  })
})()

const changePwdModal = ref(false)
const changePwdLoading = ref(false)
const changePwdForm = ref<VForm>()
const changePwdData = reactive({
  oldPassword: '',
  newPassword: '',
  confirmPassword: ''
})
const changePwdRules = {
  oldPassword: [
    { required: true, message: '请输入旧密码', trigger: 'blur' }
  ],
  newPassword: [
    { required: true, message: '请输入新密码', trigger: 'blur' },
    { min: 8, max: 16, message: '密码长度8~16位', trigger: 'blur' },
    { pattern: /^(?![\d]+$)(?![a-zA-Z]+$)(?![-=+_.,]+$)[\da-zA-Z-=+_.,]{8,16}$/, message: '密码由字母、数字、特殊字符中的任意两种组成', trigger: 'blur' }
  ],
  confirmPassword: [
    { required: true, message: '请再次输入新密码', trigger: 'blur' },
    { validator: (_rule: object, value: string, callback: Function) => {
        value !== changePwdData.newPassword ? callback(new Error('两次输入的密码不一致')) : callback()
      }, trigger: 'blur'
    }
  ]
}

const realname = computed((): null | string => {
  return store.state.loginInfo.userInfo
    ? store.state.loginInfo.userInfo.realname : null
})
const keepViews = computed((): string[] => {
  return store.state.tabs
    .filter((item: any) => item.name)
    .map((item: any) => item.name)
})

// created
defaultActiveMenuKey.value = route.path
if (defaultActiveMenuKey.value) {
  let result = /^\/(.*)\//.exec(defaultActiveMenuKey.value)
  if (result) {
    openMenuNames.value.push(result[1])
  }
}
if (!store.state.loginInfo.token) {
  router.push('/login')
} else {
  http.post<{token: string}, any>('/api/v2/common/verifyToken', {token: store.state.loginInfo.token}).then(data => {
    store.commit('login', {userInfo: data.userInfo})
    mainViewReady.value = true
  }).catch(() => {
    router.push('/login')
  })
}

function dropdownMenuCommand(command: string): void {
  switch (command) {
    case 'home':
      router.push('/')
      break
    case 'changePassword':
      changePwdModal.value = true
      break
    case 'logout':
      http.post('/api/v2/common/logout').finally(() => {
        store.commit('logout')
        router.push('/login')
      })
      break
  }
}
function submitChangePassword(): void {
  changePwdForm.value?.validate(async (valid: boolean) => {
    if (!valid) return
    changePwdLoading.value = true
    await http.post('/api/v2/system/user/changePassword', changePwdData).finally(() => {
      changePwdLoading.value = false
    })
    changePwdModal.value = false
    ElMessage.success('密码修改成功')
  })
}
function resetPwdForm(): void {
  changePwdData.oldPassword = ''
  changePwdData.newPassword = ''
  changePwdData.confirmPassword = ''
  nextTick(() => changePwdForm.value?.clearValidate())
}
function openMenu(path: string): void {
  router.push(path)
}
function removeTab(path: string): void {
  store.commit('removeTab', path)
  if (store.state.activeTab === path) {
    const { tabs } = store.state
    openMenu(tabs[tabs.length - 1]?.path || '/')
  }
}
</script>