<template>
  <div class="home-page" :content-style="contentStyle">
    <n-layout has-sider>
      <n-layout-content class="main-content">
        <div ref="searchRef" class="pt-8 px-12 relative hidden lg:block">
          <n-input-group class="shadow ">
            <n-select class="w-24" size="large" v-model:value="broswer" :options="options"
              @click="cancelSbox"></n-select>
            <n-input class="flex-1" size="large" autofocus v-model:value="searchWord" @blur="cancelSbox"
              placeholder="请输入">
              <template #suffix>
                <n-icon size="large">
                  <icon-search />
                </n-icon>
              </template>
            </n-input>
          </n-input-group>
          <div v-if="searchBox"
            class="absolute left-34 mt-2 z-10 bg-white text-sm text-gray-500  rounded-md shadow-md px-4 py-2 max-w-80">
            <div class="flex p-2 pr-20 truncate rounded-md items-center hover:text-primary cursor-pointer"
              :class="selecedIdx === idx ? 'text-white bg-primary' : ''" v-for="(i, idx) in searchItems" :key="idx"
              @click="goExtra(i.menu_link)" @keyup.enter="goExtra(i.menu_link)"><span v-if="idx">导航：</span>
              {{ i.menu_name }}</div>
          </div>
        </div>
        <!-- 标签组 -->
        <!-- <PerfectScrollbar class="w-full overflow-x-auto"> -->
        <n-scrollbar class="w-full overflow-x-auto" :style="navStyle" trigger="none">
          <div v-if="navlist.length" class="flex gap-6 px-2 mt-6 mb-3 flex-wrap lg:px-12">
            <d-tag class="cursor-pointer truncate" hideBeyondTags v-for="tag in tagList" :checked="tag.checked"
              :color="tag.color" @click="handdleTagClick(tag)">{{ tag.name }}</d-tag>
          </div>
          <!-- </PerfectScrollbar> -->
          <!-- 图片网格展示区域 -->
          <div ref="navcards"
            class="navcard grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-6 gap-5 pt-3 pb-6 px-2 lg:px-12">
            <n-card embedded
              class="bg-[#f1fff180] h-24 shadow-md transition-transform duration-300 box-border hover:-translate-y-1.5"
              v-for="(item, index) in navlist" :key="index" @click="goExtra(item.menu_link)"
              @contextmenu.prevent="handdleContextMenu($event, item)">
              <div class="mt-1 w-full flex flex-col items-center cursor-pointer hover:!text-primary">
                <div :style="{ background: item.color }"
                  class="w-8 h-8 rounded-full text-white flex items-center justify-center" v-if="item.icon_error">
                  {{ item.first }}</div>
                <img class="grid-image w-8 h-8 rounded-full" v-else :src="item.menu_icon"
                  @error="imgErr(index as number)" />
                <div class="mt-2 w-full text-center text-lg truncate">{{ item.menu_name || "" }}</div>
                <em class="absolute rounded-md top-0 left-0 px-2  text-white text-center text-sm"
                  :style="{ background: getItemColor(item) }">{{ item.tag }}</em>
              </div>
            </n-card>
            <n-card embedded
              class="bg-[#ffffff80] h-24 shadow-md transition-transform duration-300 box-border hover:-translate-y-1.5">
              <div @click="addNav" class="w-full h-full flex flex-col items-center justify-center cursor-pointer">
                <div :style="{ background: getRandomDarkColor() }"
                  class="w-8 h-8 rounded-full text-2xl text-white flex items-center justify-center">
                  +
                </div>
                <div class="mt-2 w-full text-center text-lg truncate text-primary">新增导航</div>
              </div>
            </n-card>
          </div>
        </n-scrollbar>
      </n-layout-content>
      <n-layout-sider width="30rem">
        <homeSide></homeSide>
      </n-layout-sider>
    </n-layout>

    <!-- 新增导航弹窗 -->
    <maskX :visible="visible" :setVisible="navCancel">
      <n-form class="w-[500px] bg-white rounded-md p-8 shadow-md" ref="formNav" layout="vertical" :data="navData">
        <div class="text-center text-lg">新增导航</div>
        <n-form-item class="h-8" path="menu_link">
          <n-input @blur="getIcon" v-model:value="navData.menu_link" placeholder="请输入单行链接(必填)" />
        </n-form-item>
        <n-form-item class="h-8 mt-4" path="menu_name">
          <n-input v-model:value="navData.menu_name" placeholder="请输入导航名称(必填)" />
        </n-form-item>
        <n-form-item class="h-8 mt-4" path="tag">
          <n-input v-model:value="navData.tag" placeholder="请自定义一个标签(必填，只取前四字)" />
        </n-form-item>
        <n-form-item class="h-8 mt-4 form-operation-wrap">
          <!-- <div class="flex"> -->
          <n-input v-model:value="navData.menu_icon" placeholder="请输入图标链接" />
          <img class="ml-5" v-if="navData.menu_icon" width="30" height="30" :src="navData.menu_icon" alt="">
          <div v-else class="ml-5 w-[30px] h-[30px]"></div>
          <!-- </div> -->
        </n-form-item>
        <div class="mt-14 flex justify-between">
          <n-button class="w-[48%]" secondary variant="solid" @click="navCancel">取消</n-button>
          <n-button class="w-[48%]" type="primary" variant="solid" @click="navSubmit">确定</n-button>
        </div>
      </n-form>


    </maskX>

    <!-- 音乐插件 -->
    <aplayer></aplayer>

    <!-- 右键菜单 -->
    <contextMenu :show="menuShow" :options="MenuOptions">
      <div class="!p-0 !m-0 bg-white cursor-pointer !rounded-md shadow-md" @mouseenter="removeTimer"
        @mouseleave="hideMenu">
        <div :class="menuS" @click="handdleMenuItem(1)">
          修改名称
        </div>
        <div :class="menuS" @click="handdleMenuItem(2)">
          修改链接
        </div>
        <div :class="menuS" @click="handdleMenuItem(3)">
          修改标签
        </div>
        <div :class="menuS" @click="handdleMenuItem(4)">
          删除导航
        </div>
      </div>
    </contextMenu>

    <!-- 编辑弹窗 -->
    <maskX :visible="editModal" :setVisible="navCancel">
      <div class="w-[500px] bg-white p-8 rounded-md">
        <div class="text-center text-lg mb-8">修改导航内容</div>
        <div class="mb-4">
          原
          <span class="text-primary" v-if="currentClickedItem === 1">导航名称：{{ currentItem?.menu_name }}</span>
          <span class="text-primary" v-if="currentClickedItem === 2">导航链接：{{ currentItem?.menu_link }}</span>
          <span class="text-primary" v-if="currentClickedItem === 3">导航标签：{{ currentItem?.tag }}</span>
        </div>
        <n-input v-model:value="editInput" placeholder="请输入修改内容"></n-input>
        <div class="mt-8 flex justify-between">
          <n-button class="w-[48%]" secondary @click="handdleItemCancel">取消</n-button>
          <n-button class="w-[48%]" type="primary" @click="handdleItemSubmit">确定</n-button>
        </div>
      </div>
    </maskX>

  </div>
</template>

<script setup lang="ts">
import contextMenu from '@/components/contextMenu.vue';
import maskX from '@/components/mask.vue';
import { deepclone, getDictValue } from '@/util/index.ts';
definePage({
  name: 'home',
  meta: {
    title: '首页',
  }
})


// 定义接口类型
interface NavItem {
  nid?: number
  menu_link: string
  menu_name: string
  tag: string
  menu_icon: string
  icon_error?: boolean
  first?: string
  color?: string
}

interface MenuItem {
  menu_name: string
  menu_link: string
  tag: string
}

interface TagItem {
  name: string
  color: string
  checked: boolean
}

// 右键菜单
const menuShow = ref(false)
const MenuOptions = reactive({ x: 0, y: 0 })
const currentItem = ref<NavItem | null>(null)
const menuS = '!m-0 py-3 px-6 text-sm text-gray-700 w-full flex items-center justify-center hover:bg-[#f5f0f0] hover:text-primary'
const currentClickedItem = ref<number>(0)
const editModal = ref<boolean>(false)
const editInput = ref<string>('')
// 新增导航弹窗
const visible = ref<boolean>(false)
const navData = reactive<NavItem>({
  menu_link: '',
  menu_name: '',
  tag: '',
  menu_icon: ''
})
const formNav = ref<any>(null)
const navcards = ref<any>(null)
const searchRef = useTemplateRef("searchRef")

// 首页逻辑
const nav: any = $store.nav.useNavStore()
const contentStyle: any = ref({})
const navStyle: any = ref({})
const searchWord: any = ref('')
const broswer: any = ref('bing')
const searchItems: any = ref([])
const selecedIdx = ref(0)
const searchBox = ref(false)
const options = ref([
  {
    label: '必应',
    value: 'bing',
    url: 'https://cn.bing.com/search?q='
  },
  {
    label: '百度',
    value: 'baidu',
    url: 'https://www.baidu.com/s?wd='
  },
  {
    label: '谷歌',
    value: 'google',
    url: 'https://www.google.com/search?q='
  },
  {
    label: '翻译',
    value: 'trans',
    url: 'https://translate.volcengine.com?text='
  },

])


const navlist = ref<NavItem[]>([])
let cloneNavlist: NavItem[] = []
const tagList = ref<TagItem[]>([
  {
    name: '全部',
    color: '',
    checked: true
  }
])


const usrLog = $store.log.useLogStore()
let timer: any = null

// 输入搜索内容时监听searchWord在navlist中模糊搜索
watch(searchWord, () => {
  handleInput()
})

function cancelSbox() {
  setTimeout(() => {
    searchBox.value = false
    searchItems.value = []
    selecedIdx.value = 0
  }, 200)
}

function handleInput() {
  if (!searchWord.value) {
    searchItems.value = []
    searchBox.value = false
    selecedIdx.value = 0
    return
  }
  searchBox.value = true
  selecedIdx.value = 0
  const keyword = searchWord.value.toLowerCase()
  searchItems.value = navlist.value.filter((item) =>
    item.menu_name.toLowerCase().includes(keyword) ||
    item.menu_link.toLowerCase().includes(keyword) ||
    item.tag.toLowerCase().includes(keyword)
  )
  // 在searchItems第一个位置插入一条原本搜索
  searchItems.value.unshift({
    menu_name: `在${getDictValue(options.value, "value", broswer.value, "label")}中搜索"${searchWord.value}"`,
    menu_link: getDictValue(options.value, "value", broswer.value, "url") + searchWord.value,
    tag: ''
  })
}

function handleKeyup(e: KeyboardEvent) {
  if (!searchBox.value) return
  // 向下箭头
  if (e.key == "ArrowDown") {
    if (selecedIdx.value < searchItems.value.length - 1) {
      selecedIdx.value += 1
    } else {
      selecedIdx.value = 0
    }
  }
  // 向上箭头
  else if (e.key == "ArrowUp") {
    if (selecedIdx.value > 0) {
      selecedIdx.value -= 1
    } else {
      selecedIdx.value = searchItems.value.length - 1
    }
  }
  // 回车键
  else if (e.key == "Enter") {
    if (searchItems.value.length > 0) {
      const selectedItem = searchItems.value[selecedIdx.value]
      window.open(selectedItem.menu_link, "_BLANK")
      searchBox.value = false
      selecedIdx.value = 0
    }
  }
}



// 2秒后自动隐藏菜单
const hideMenu = () => {
  if (timer) clearTimeout(timer)
  timer = setTimeout(() => {
    menuShow.value = false
  }, 2000)
}

const removeTimer = () => {
  if (timer) {
    clearTimeout(timer)
    timer = null
  }
}

function handleMenuItem(type: number) {
  menuShow.value = false
  currentClickedItem.value = type
  if (type === 4) {
    // 删除导航
    if (!currentItem.value) return
    $modal({
      title: '删除导航',
      content: `确定要删除【${currentItem.value.menu_name}】吗？删除后不可恢复哦~`,
      cancelText: '取消',
      submitText: '删除',
      handdleSubmit: async () => {
        const res = await $http.nav.deleteNav(currentItem.value?.nid)
        if (res.code === 200) {
          $msg.success('删除成功')
          getNavList()
        }
      }
    })
    return
  }
  editModal.value = true
}

function handleItemCancel() {
  editModal.value = false
  editInput.value = ''
}

async function handleItemSubmit() {
  if (!editInput.value) {
    $msg.error('请输入修改内容')
    return
  }
  let updateData: Partial<NavItem> = {}
  if (currentClickedItem.value === 1) {
    updateData.menu_name = editInput.value
  } else if (currentClickedItem.value === 2) {
    updateData.menu_link = editInput.value
  } else if (currentClickedItem.value === 3) {
    updateData.tag = editInput.value.slice(0, 4)
  }
  const res = await $http.nav.editNav(currentItem.value!.nid!, updateData)
  if (res.code === 200) {
    $msg.success('修改成功')
    editModal.value = false
    editInput.value = ''
    getNavList()
  }
}

async function getNavList() {
  const userinfo = $cookies.get("userinfo")
  if (!userinfo) {
    navlist.value = []
    return
  }
  const res = await $http.nav.getNavList()
  if (!res.data) return

  // 合并两个循环，提高性能
  res.data.forEach((i: any) => {
    i.icon_error = false
    i.first = i.menu_name?.at(0) || ''
    i.color = getRandomDarkColor()

    // 同时处理标签列表
    if (!tagList.value.find((t) => t.name === i.tag)) {
      tagList.value.push({
        name: i.tag.substring(0, 4),
        color: getRandomDarkColor(30, 128),
        checked: false
      })
    }
  });

  navlist.value = res.data
  cloneNavlist = deepclone(res.data)
}

function getItemColor(item: NavItem) {
  const tag = tagList.value.find((t) => t.name === item.tag)
  return tag ? tag.color : getRandomDarkColor(30, 128)
}


function handdleTagClick(tag: any) {
  tag.checked = !tag.checked
  if (tag.name == '全部') {
    // 全部标签被点击，重置其他标签状态
    tagList.value.forEach((t: any) => {
      if (t.name !== '全部') {
        t.checked = false
      }
    })
    // navlist.value = cloneNavlist
    navlist.value = cloneNavlist
    return
  } else {
    // 其他标签被点击，取消“全部”标签状态
    const allTag = tagList.value.find((t: any) => t.name == '全部')
    if (allTag) allTag.checked = false
  }

  const selectedTags = tagList.value.filter((t: any) => t.checked && t.name !== '全部').map((t: any) => t.name)

  if (selectedTags.length === 0) {
    // 如果没有选中任何标签，默认选中“全部”
    const allTag = tagList.value.find((t: any) => t.name == '全部')
    if (allTag) allTag.checked = true
    // 数据从cloneNavlist中过滤
    navlist.value = cloneNavlist
    return
  }
  console.log('>>> --> handdleTagClick --> selectedTags:', selectedTags)
  // 根据选中的标签过滤导航列表
  navlist.value = cloneNavlist.filter((item: any) => selectedTags.includes(item.tag))
}


function imgErr(index: number) {
  navlist.value[index].icon_error = true
}

function goExtra(link: string) {
  window.open(link, "_BLANK")
}

function search() {
  const res = getDictValue(options.value, "value", broswer.value, "url")
  if (res) {
    window.open(res + searchWord.value, "_BLANK")
  }
}

const getRandomDarkColor = (min: number = 30, max: number = 128): string => {
  // 确保最大值不超过255且最小值不小于0
  min = Math.max(0, min);
  max = Math.min(255, max);

  // 确保最大值大于最小值
  if (max <= min) {
    max = min + 30;
  }

  // 生成随机RGB值 (深色)
  const r = Math.floor(Math.random() * (max - min + 1)) + min;
  const g = Math.floor(Math.random() * (max - min + 1)) + min;
  const b = Math.floor(Math.random() * (max - min + 1)) + min;

  // 转换为十六进制
  const toHex = (c: number) => {
    const hex = c.toString(16);
    return hex.length === 1 ? '0' + hex : hex;
  };

  return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}

function addNav() {
  if (!$cookies.get("token")) {
    $msg.error("请先登录");
    return
  }
  visible.value = true
}

async function getIcon() {
  console.log(11111);

  if (!navData.menu_link) return
  const res = await $http.mix.getIcon({
    url: navData.menu_link
  })
  console.log('>>> --> getIcon --> res:', res)
  if (res.code == 200) {
    navData.menu_icon = res.data.url
  }
}

function resetNav() {
  navData.menu_link = ''
  navData.menu_name = ''
  navData.tag = ''
  navData.menu_icon = ''
}
function navCancel() {
  visible.value = false
  resetNav()
}

async function navSubmit() {
  console.log('>>> --> navSubmit --> navData:', navData)
  if (!navData.menu_link || !navData.menu_name || !navData.tag) {
    $msg.error('请输入链接、标签和名称')
    return
  }
  navData.tag = navData.tag.slice(0, 4)
  const res = await $http.nav.addNav(navData)
  console.log('>>> --> navSubmit --> res:', res)

  if (res.code == 200) {
    $msg.success('添加成功')
    visible.value = false
    getNavList()
  }
  // 清空navData
  resetNav()
}
// 处理右键菜单
function handdleContextMenu(event: MouseEvent, item: any) {
  menuShow.value = true; // 先隐藏菜单以重置位置
  MenuOptions.x = event.clientX;
  MenuOptions.y = event.clientY;
  currentItem.value = item; // 存储当前右键点击的项
}





// 监听store的登录状态
watch(() => usrLog.isLogin, (newVal: any) => {
  console.log('********** --> watch --> newVal:', newVal)
  if (newVal) {
    getNavList()
  } else {
    navlist.value = []
  }
})
function handdleKeyup(e: any) {
  if (!searchBox.value) return
  // console.log('>>> --> haddleDown --> idx:', e.keyCode)
  // 向下箭头
  if (e.keyCode == 40) {
    if (selecedIdx.value < searchItems.value.length - 1) {
      selecedIdx.value += 1
    } else {
      selecedIdx.value = 0
    }
  }
  // 向上箭头
  else if (e.keyCode == 38) {
    if (selecedIdx.value > 0) {
      selecedIdx.value -= 1
    } else {
      selecedIdx.value = searchItems.value.length - 1
    }
  }
  // 回车键
  else if (e.keyCode == 13) {
    if (searchItems.value.length > 0) {
      const selectedItem = searchItems.value[selecedIdx.value]
      window.open(selectedItem.menu_link, "_BLANK")
      searchBox.value = false
      selecedIdx.value = 0
    }
  }
}
function handdleItemCancel() {
  editModal.value = false
  editInput.value = ''
}

async function handdleItemSubmit() {
  if (!editInput.value) {
    $msg.error('请输入修改内容')
    return
  }
  let updateData: any = {}
  if (currentClickedItem.value == 1) {
    updateData.menu_name = editInput.value
  } else if (currentClickedItem.value == 2) {
    updateData.menu_link = editInput.value
  } else if (currentClickedItem.value == 3) {
    updateData.tag = editInput.value.slice(0, 4)
  }
  const res = await $http.nav.editNav(currentItem.value?.nid, updateData)
  console.log('>>> --> handdleItemSubmit --> res:', res)
  if (res.code == 200) {
    $msg.success('修改成功')
    editModal.value = false
    editInput.value = ''
    getNavList()
  }
}
function handdleMenuItem(type: number) {
  menuShow.value = false
  currentClickedItem.value = type
  if (type == 4) {
    // 删除导航
    if (!currentItem.value) return
    $modal({
      title: '删除导航',
      content: `确定要删除【${currentItem.value.menu_name}】吗？删除后不可恢复哦~`,
      cancelText: '取消',
      submitText: '删除',
      handdleSubmit: async () => {
        const res = await $http.nav.deleteNav(currentItem.value?.nid)
        console.log('>>> --> handdleMenuItem --> res:', res)
        if (res.code == 200) {
          $msg.success('删除成功')
          getNavList()
        }
      }
    })
    return
  }
  editModal.value = true
}
const navHeight: any = ref(0)
onMounted(() => {
  contentStyle.value = {
    height: `${window.innerHeight - nav.navH}px)`
  }
  console.log('>>> --> onMounted --> navcards.value.getBoundingClientRect().y:', navcards.value.getBoundingClientRect().y)
  navHeight.value = window.innerHeight - navcards.value.getBoundingClientRect().y
  navStyle.value = {
    // height: `calc(100vh - ${navcards.value.getBoundingClientRect().y}px - ${nav.navH}px)`,
    height: `${window.innerHeight - navcards.value.getBoundingClientRect().y}px`
  }
  tagList.value = [
    {
      name: '全部',
      color: getRandomDarkColor(30, 128),
      checked: true
    }
  ]
  getNavList()
  window.addEventListener('resize', () => {
    // 获取屏幕高度
    const screenHeight = window.innerHeight;

    contentStyle.value = {
      height: `${screenHeight - nav.navH}px)`
    }
    // searchRef的y
    const searchHeight: number = searchRef.value?.getBoundingClientRect().y || 0
    // searchRef的高度
    const searchH: number = searchRef.value?.getBoundingClientRect().height || 0
    navStyle.value = {
      height: `${window.innerHeight - (searchHeight + searchH)}px`
    }
  });
  // 处理键盘按键抬起事件，触发搜索框的键盘导航逻辑
  window.addEventListener('keyup', (e: Event) => {
    handdleKeyup(e)
  });
})
</script>

<style scoped lang="less">
/* layer: default */

.navcard {
  display: grid;

}

:deep(.devui-input-slot__prepend) {
  width: 90px;
}
</style>