"use client"

import {
  AppShell,
  Box,
  Burger,
  Divider,
  Flex,
  Menu,
  NavLink,
  ScrollArea,
  Space,
  Stack,
  Text,
  Tooltip,
  UnstyledButton,
  useComputedColorScheme,
  useMantineColorScheme,
} from "@mantine/core"
import Avvvatars from "avvvatars-react"

import { useDisclosure, useMediaQuery } from "@mantine/hooks"
import { IconLogout, IconMoon, IconSun } from "@tabler/icons-react"
import cx from "clsx"
import { Suspense, useEffect, useMemo, useState } from "react"
import actionToggleClasses from "./ActionToggle.module.css"
import headerLinkClasses from "./HeaderLink.module.css"

import { useUserStore } from "@/app/store/user"
import { usePathname, useRouter } from "next/navigation"
import { usePermissionStore } from "../label/store/auth"
import { deleteCookie } from "../login/api"
import { MenuItem, withoutLayoutRoutes } from "./common"
import { ClientIcon } from "./components/ClientIcon"
import { LinksGroup } from "./components/NavbarLinks"
import { useAppLayoutStore } from "./store"

const COMPOUND_SURNAMES = new Set([
  "欧阳",
  "太史",
  "端木",
  "上官",
  "司马",
  "东方",
  "独孤",
  "南宫",
  "万俟",
  "闻人",
  "夏侯",
  "诸葛",
  "尉迟",
  "公羊",
  "赫连",
  "澹台",
  "皇甫",
  "宗政",
  "濮阳",
  "公冶",
  "太叔",
  "申屠",
  "公孙",
  "慕容",
  "仲孙",
  "钟离",
  "长孙",
  "宇文",
  "司徒",
  "鲜于",
  "司空",
  "闾丘",
  "子车",
  "亓官",
  "司寇",
  "巫马",
  "公西",
  "颛孙",
  "壤驷",
  "公良",
  "漆雕",
  "乐正",
  "宰父",
  "谷梁",
  "拓跋",
  "轩辕",
  "令狐",
  "段干",
  "百里",
  "呼延",
  "东郭",
  "南门",
  "羊舌",
  "微生",
  "梁丘",
  "左丘",
  "东门",
  "西门",
  "南荣",
  "第五",
])

function isChineseName(value: string) {
  return /[\u4e00-\u9fff]/.test(value)
}

function getAvatarDisplayValue(rawValue?: string | null) {
  const value = rawValue?.trim() ?? ""

  if (!value) return "-"

  if (isChineseName(value)) {
    const normalized = value.replace(/[\s·•･・]/g, "")
    if (normalized.length <= 1) return normalized

    const surnameLength =
      normalized.length >= 3 && COMPOUND_SURNAMES.has(normalized.slice(0, 2))
        ? 2
        : 1
    const givenName = normalized.slice(surnameLength)

    if (!givenName) return normalized.slice(-1)
    if (givenName.length <= 2) return givenName
    return givenName.slice(-2)
  }

  const tokens = value.split(/[\s-_]+/).filter(Boolean)
  if (tokens.length >= 2) {
    return `${tokens[0][0] ?? ""}${tokens[tokens.length - 1][0] ?? ""}`
      .trim()
      .toUpperCase()
  }

  return value.slice(0, 2).toUpperCase()
}

export default function AppLayout({
  menu,
  children,
}: {
  menu: MenuItem[]
  children: React.ReactNode
}) {
  const [mobileOpened, { toggle: toggleMobile }] = useDisclosure()

  const { updateIsOpen } = useAppLayoutStore.getState()
  const { isOpen } = useAppLayoutStore()

  const [isClient, setIsClient] = useState(false)
  useEffect(() => {
    setIsClient(true)
  }, [])

  const { setColorScheme } = useMantineColorScheme()
  const computedColorScheme = useComputedColorScheme("light", {
    getInitialValueInEffect: true,
  })

  const pathname = usePathname()

  const withoutLayout = useMemo(
    () => withoutLayoutRoutes.includes(pathname),
    [pathname]
  )

  const router = useRouter()

  const activeHeaderMenu = useMemo(() => {
    return menu?.find((child) => pathname.startsWith(`/${child.url}`))
  }, [pathname, menu])

  const { menuDefaultRouter } = useAppLayoutStore.getState()

  const headItems = menu.map((item) => (
    <a
      key={item.url}
      href={`#`}
      className={headerLinkClasses.link}
      data-active={activeHeaderMenu?.url === item.url || undefined}
      onClick={(e) => {
        e.preventDefault()
        if (activeHeaderMenu?.url === item.url) return
        let toPathname = menuDefaultRouter[`/${item.url}`] || `/${item.url}`
        window.location.href = toPathname
        // router.replace(toPathname)
      }}>
      <ClientIcon icon={item.icon} style={{ width: "1rem", height: "1rem" }} />
      {item.title}
    </a>
  ))

  /**
   * 递归渲染 MenuItem
   */
  const renderMenuItem = (
    item: MenuItem,
    routerUrl?: string
  ): React.ReactNode => {
    if (item.items && item.items.length > 0) {
      // 有子菜单，递归渲染
      return (
        <Menu.Sub key={item.url}>
          <Menu.Sub.Target>
            <Menu.Sub.Item>{item.title}</Menu.Sub.Item>
          </Menu.Sub.Target>
          <Menu.Sub.Dropdown>
            {item.items.map((sub) =>
              renderMenuItem(sub, `${routerUrl}/${item.url}`)
            )}
          </Menu.Sub.Dropdown>
        </Menu.Sub>
      )
    } else {
      // 没有子菜单，普通 Menu.Item

      return (
        <Menu.Item key={item.url} p={0}>
          <NavLink
            noWrap={true}
            onClick={() => {
              router.push(`/${routerUrl}/${item.url}`)
            }}
            active={pathname === `/${routerUrl}/${item.url}`}
            leftSection={
              item.icon && (
                <ClientIcon
                  icon={item.icon}
                  style={{ width: "1rem", height: "1rem" }}
                />
              )
            }
            label={item.title}></NavLink>
        </Menu.Item>
      )
    }
  }

  const handleLogout = async () => {
    useUserStore.getState().removeUserInfo()
    usePermissionStore.getState().logout()
    process.env.NEXT_PUBLIC_OUTPUT_TYPE === "standalone" &&
      (await deleteCookie())
    router.push("/login")
    window.location.reload()
  }
  const matches = useMediaQuery("(min-width: 48em)")
  const userName = usePermissionStore((s) => s.user_name)
  const avatarDisplayValue = useMemo(
    () => getAvatarDisplayValue(userName),
    [userName]
  )

  return isClient ? (
    withoutLayout ? (
      <Suspense fallback={<></>}>{children}</Suspense>
    ) : (
      <AppShell
        header={{ height: 55 }}
        navbar={{
          width: isOpen ? 200 : 40,
          breakpoint: "sm",
          collapsed: { mobile: !mobileOpened },
        }}>
        <AppShell.Header>
          <Flex h="100%" px="md" align="center">
            <Burger
              opened={mobileOpened}
              onClick={toggleMobile}
              hiddenFrom="sm"
              size="sm"
            />
            <Flex flex={1} gap={0} h="100%" align="center">
              <Box w={184} visibleFrom="sm">
                标注平台
              </Box>
              <Space w={"1rem"} hiddenFrom="sm" />
              {headItems}
            </Flex>
            <Flex justify="center" align="center" w={"max-content"}>
              <UnstyledButton
                display="none"
                onClick={() =>
                  setColorScheme(
                    computedColorScheme === "light" ? "dark" : "light"
                  )
                }
                aria-label="Toggle color scheme">
                <IconSun
                  className={cx(
                    actionToggleClasses.icon,
                    actionToggleClasses.light
                  )}
                  stroke={1.5}
                />
                <IconMoon
                  className={cx(
                    actionToggleClasses.icon,
                    actionToggleClasses.dark
                  )}
                  stroke={1.5}
                />
              </UnstyledButton>
              <Divider orientation="vertical" mx={"0.5rem"} display="none" />
              <Menu shadow="md" width={220}>
                <Menu.Target>
                  <UnstyledButton>
                    <Avvvatars
                      value={userName || "-"}
                      displayValue={avatarDisplayValue}
                    />
                  </UnstyledButton>
                </Menu.Target>
                <Menu.Dropdown>
                  <Menu.Label>用户信息</Menu.Label>
                  <Box px="sm" py={4}>
                    <Text size="sm" fw={500} style={{ wordBreak: "break-all" }}>
                      {userName || "-"}
                    </Text>
                  </Box>
                  <Menu.Divider />
                  <Menu.Label>操作</Menu.Label>
                  <Menu.Item
                    leftSection={<IconLogout size={14} />}
                    onClick={handleLogout}>
                    退出登录
                  </Menu.Item>
                </Menu.Dropdown>
              </Menu>
            </Flex>
          </Flex>
        </AppShell.Header>
        <AppShell.Navbar style={{ transition: "width 0.2s ease" }}>
          <Stack justify="start" gap={4} flex={1}>
            <ScrollArea h="calc(100vh - 95px)">
              {activeHeaderMenu?.items?.map((item) => {
                if (item.items?.length) {
                  if (matches) {
                    if (isOpen) {
                      return (
                        <LinksGroup
                          key={item.url}
                          item={item}
                          toggleMobile={toggleMobile}
                          routerUrl={activeHeaderMenu.url}
                          initiallyOpened={true}
                        />
                      )
                    } else {
                      return (
                        <Menu
                          width={"auto"}
                          key={item.url + "desktop"}
                          position="right-start"
                          trigger="hover"
                          openDelay={100}
                          closeDelay={200}>
                          <Menu.Target>
                            <NavLink
                              noWrap={true}
                              leftSection={
                                item.icon && (
                                  <ClientIcon
                                    icon={item.icon}
                                    style={{ width: "1rem", height: "1rem" }}
                                  />
                                )
                              }
                              label={item.title}
                            />
                          </Menu.Target>
                          <Menu.Dropdown>
                            {item.items?.map((sub) =>
                              renderMenuItem(
                                sub,
                                `${activeHeaderMenu.url}/${item.url}`
                              )
                            )}
                          </Menu.Dropdown>
                        </Menu>
                      )
                    }
                  } else {
                    return (
                      <Box key={item.url + "mobile"} hiddenFrom="sm">
                        <LinksGroup
                          item={item}
                          toggleMobile={toggleMobile}
                          routerUrl={activeHeaderMenu.url}
                          initiallyOpened={true}
                        />
                      </Box>
                    )
                  }
                } else {
                  return (
                    <Tooltip
                      key={item.url}
                      events={{
                        hover: !isOpen && !mobileOpened,
                        focus: false,
                        touch: false,
                      }}
                      label={item.title || ""}
                      position="right"
                      openDelay={100}
                      closeDelay={200}
                      transitionProps={{ duration: 100 }}>
                      <NavLink
                        // href={`/${activeHeaderMenu.url}/${item.url}`}
                        onClick={() => {
                          toggleMobile()
                          router.push(`/${activeHeaderMenu.url}/${item.url}`)
                        }}
                        noWrap={true}
                        active={pathname.startsWith(
                          `/${activeHeaderMenu.url}/${item.url}`
                        )}
                        leftSection={
                          <ClientIcon
                            icon={item.icon}
                            style={{ width: "1rem", height: "1rem" }}
                          />
                        }
                        label={item.title}
                      />
                    </Tooltip>
                  )
                }
              })}
            </ScrollArea>
          </Stack>
          <Stack justify="center" gap={0}>
            <Flex
              justify={isOpen ? "flex-end" : "center"}
              align="center"
              mb={"sm"}>
              <Burger
                opened={false}
                onClick={() => updateIsOpen(!isOpen)}
                size="sm"
                visibleFrom="sm"
                mr={isOpen ? "sm" : undefined}
              />
            </Flex>
          </Stack>
        </AppShell.Navbar>
        <AppShell.Main
          bg={computedColorScheme === "light" ? "gray.0" : "gray.8"}>
          <Suspense fallback={<></>}>{children}</Suspense>
        </AppShell.Main>
      </AppShell>
    )
  ) : null
}
