import {
  Badge,
  Box,
  DialogTitle,
  elevationVariants,
  Flex,
  NavigationLink,
  SidePanel,
  styled,
  Text,
  Tooltip,
  VisuallyHidden,
} from '@traefik-labs/faency'
import { useContext, useEffect, useMemo, useState } from 'react'
import { BsChevronDoubleRight, BsChevronDoubleLeft } from 'react-icons/bs'
import { matchPath, useHref } from 'react-router'
import { useLocation } from 'react-router-dom'
import { useWindowSize } from 'usehooks-ts'

import Container from '../Container'

import { LAPTOP_BP } from '.'

import IconButton from 'components/buttons/IconButton'
import Logo from 'components/icons/Logo'
import { PluginsIcon } from 'components/icons/PluginsIcon'
import TooltipText from 'components/TooltipText'
import { VersionContext } from 'contexts/version'
import useTotals from 'hooks/use-overview-totals'
import ApimDemoNavMenu from 'pages/hub-demo/HubDemoNav'
import { Route, ROUTES } from 'routes'

const NavigationDrawer = styled(Flex, {
  width: '100%',
  maxWidth: '100%',
  height: 64,
  p: 0,
  variants: {
    elevation: elevationVariants,
  },
  defaultVariants: {
    elevation: 1,
  },
})

export const BasicNavigationItem = ({
  route,
  count,
  isSmallScreen,
  isExpanded,
  onSidePanelToggle,
}: {
  route: Route
  count?: number
  isSmallScreen: boolean
  isExpanded: boolean
  onSidePanelToggle: (isOpen: boolean) => void
}) => {
  const { pathname } = useLocation()
  const href = useHref(route.path)

  const isActiveRoute = useMemo(() => {
    const mainPath = matchPath(route.path, pathname)

    if (mainPath) return true

    if (route.activeMatches) {
      return route.activeMatches.some((path) => matchPath(path, pathname))
    }
  }, [pathname, route.activeMatches, route.path])

  if (isSmallScreen && !isExpanded) {
    return (
      <Tooltip content={<Text css={{ color: '$tooltipText' }}>{route.label}</Text>} side="right">
        <Box>
          <NavigationLink active={isActiveRoute} startAdornment={route?.icon} href={href} />
        </Box>
      </Tooltip>
    )
  }

  return (
    <NavigationLink
      onClick={isSmallScreen ? () => onSidePanelToggle(false) : undefined}
      active={isActiveRoute}
      startAdornment={route?.icon}
      css={{ whiteSpace: 'nowrap' }}
      href={href}
    >
      {route.label}
      {!!count && (
        <Badge variant={isActiveRoute ? 'green' : undefined} css={{ ml: '$2' }}>
          {count}
        </Badge>
      )}
    </NavigationLink>
  )
}

export const SideBarPanel = ({
  isOpen,
  onOpenChange,
}: {
  isOpen: boolean
  onOpenChange: (isOpen: boolean) => void
}) => {
  const windowSize = useWindowSize()

  return (
    <SidePanel
      open={isOpen && windowSize.width <= LAPTOP_BP}
      onOpenChange={onOpenChange}
      side="left"
      css={{ width: 264, p: 0 }}
      description="Expanded side navigation"
      noCloseIcon
    >
      <VisuallyHidden>
        <DialogTitle>side navigation</DialogTitle>
      </VisuallyHidden>
      <SideNav isExpanded={isOpen} onSidePanelToggle={() => onOpenChange(false)} />
    </SidePanel>
  )
}

export const SideNav = ({
  isExpanded,
  onSidePanelToggle,
  isResponsive = false,
}: {
  isExpanded: boolean
  onSidePanelToggle: () => void
  isResponsive?: boolean
}) => {
  const windowSize = useWindowSize()
  const { version } = useContext(VersionContext)

  const { http, tcp, udp, certificates } = useTotals()

  const [isSmallScreen, setIsSmallScreen] = useState(false)

  useEffect(() => {
    setIsSmallScreen(windowSize.width <= LAPTOP_BP)
  }, [isExpanded, windowSize.width])

  const isSmallAndResponsive = useMemo(() => isSmallScreen && isResponsive, [isResponsive, isSmallScreen])

  const totalValueByPath = useMemo<{ [key: string]: number }>(
    () => ({
      '/http/routers': http?.routers,
      '/http/services': http?.services,
      '/http/middlewares': http?.middlewares as number,
      '/tcp/routers': tcp?.routers,
      '/tcp/services': tcp?.services,
      '/tcp/middlewares': tcp?.middlewares as number,
      '/udp/routers': udp?.routers,
      '/udp/services': udp?.services,
      '/certificates': certificates,
    }),
    [http, tcp, udp, certificates],
  )

  return (
    <NavigationDrawer
      data-collapsed={isExpanded && isSmallAndResponsive}
      css={{
        width: 264,
        height: '100vh',
        position: 'fixed',
        [`@media (max-width:${LAPTOP_BP}px)`]: isResponsive
          ? {
              width: 64,
              'a > div:nth-child(1)': {
                marginLeft: 0,
                paddingRight: 0,
              },
            }
          : undefined,
        transition: '150ms cubic-bezier(0.22, 1, 0.36, 1)',
        '&[data-collapsed="true"]': {
          marginLeft: -32,
        },
      }}
    >
      <IconButton
        ghost
        icon={isExpanded ? <BsChevronDoubleLeft size={16} /> : <BsChevronDoubleRight size={16} />}
        onClick={onSidePanelToggle}
        css={{
          display: 'none',
          position: 'absolute',
          top: 3,
          right: isExpanded ? 12 : 4,
          color: '$hiContrast',
          [`@media (max-width:${LAPTOP_BP}px)`]: { display: 'inherit' },
          p: '$1',
          '&:before, &:after': { borderRadius: '10px' },
          height: 16,
        }}
      />
      <Container
        css={{
          overflow: 'auto',
          p: '$3',
          m: 0,
          flexDirection: 'column',
          [`@media (max-width:${LAPTOP_BP}px)`]: isResponsive ? { p: '$2' } : undefined,
        }}
        data-testid="nav-container"
      >
        <Flex
          as="a"
          gap={2}
          css={{
            color: '$primary',
            mt: '$3',
            mb: '$6',
            textDecoration: 'none',
            height: 'fit-content',
            pl: '$3',
            [`@media (max-width:${LAPTOP_BP}px)`]: isResponsive
              ? { mt: '$4', px: 0, justifyContent: 'center' }
              : undefined,
          }}
          href={useHref('/')}
          data-testid="proxy-main-nav"
        >
          <Logo height={isSmallAndResponsive ? 36 : 56} isSmallScreen={isSmallAndResponsive} />
          {!!version && !isSmallAndResponsive && (
            <TooltipText text={version} css={{ maxWidth: 50, fontWeight: '$semiBold' }} isTruncated />
          )}
        </Flex>
        {ROUTES.map((section, index) => (
          <Flex
            key={`nav-section-${index}`}
            direction="column"
            gap="1"
            css={{
              '&:not(:last-child)': {
                borderTop: section.sectionLabel ? '1px solid $colors$tableRowBorder' : undefined,
                mb: '$3',
                pt: section.sectionLabel ? '$3' : undefined,
              },
            }}
          >
            {section.sectionLabel && (
              <Text
                css={{
                  fontWeight: 600,
                  color: '$grayBlue9',
                  mb: '$2',
                  textTransform: 'uppercase',
                  letterSpacing: 0.2,
                  ml: 15,
                  [`@media (max-width:${LAPTOP_BP}px)`]: isResponsive ? { display: 'none' } : undefined,
                }}
              >
                {section.sectionLabel}
              </Text>
            )}
            {section.items.map((item, idx) => (
              <BasicNavigationItem
                key={`nav-section-${index}-${idx}`}
                route={item}
                count={totalValueByPath[item.path]}
                isSmallScreen={isSmallScreen}
                isExpanded={isExpanded}
                onSidePanelToggle={onSidePanelToggle}
              />
            ))}
          </Flex>
        ))}
        <Flex direction="column" css={{ borderTop: '1px solid $colors$tableRowBorder', borderRadius: 0, py: '$3' }}>
          <NavigationLink
            startAdornment={<PluginsIcon />}
            css={{
              mt: '$3',
              whiteSpace: 'nowrap',
            }}
            href="https://plugins.traefik.io/"
            target="_blank"
          >
            {!isSmallScreen || isExpanded ? 'Plugins' : ''}
          </NavigationLink>
        </Flex>

        <ApimDemoNavMenu
          isResponsive={isResponsive}
          isSmallScreen={isSmallScreen}
          isExpanded={isExpanded}
          onSidePanelToggle={onSidePanelToggle}
        />
      </Container>
    </NavigationDrawer>
  )
}
