import type { NavIcon } from './nav-link'
import { cn } from '@langgenius/dify-ui/cn'
import { useHover, useKeyPress } from 'ahooks'
import * as React from 'react'
import { useCallback, useEffect, useState } from 'react'
import { useShallow } from 'zustand/react/shallow'
import { useStore as useAppStore } from '@/app/components/app/store'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { usePathname } from '@/next/navigation'
import Divider from '../base/divider'
import { getKeyboardKeyCodeBySystem } from '../workflow/utils'
import AppInfo from './app-info'
import AppSidebarDropdown from './app-sidebar-dropdown'
import DatasetInfo from './dataset-info'
import DatasetSidebarDropdown from './dataset-sidebar-dropdown'
import NavLink from './nav-link'
import ToggleButton from './toggle-button'

const isShortcutFromInputArea = (target: EventTarget | null) => {
  if (!(target instanceof HTMLElement))
    return false

  return target.tagName === 'INPUT'
    || target.tagName === 'TEXTAREA'
    || target.isContentEditable
}

type IAppDetailNavProps = {
  iconType?: 'app' | 'dataset'
  navigation: Array<{
    name: string
    href: string
    icon: NavIcon
    selectedIcon: NavIcon
    disabled?: boolean
  }>
  extraInfo?: (modeState: string) => React.ReactNode
  renderHeader?: (modeState: string) => React.ReactNode
  renderNavigation?: (modeState: string) => React.ReactNode
}

const AppDetailNav = ({
  navigation,
  extraInfo,
  iconType = 'app',
  renderHeader,
  renderNavigation,
}: IAppDetailNavProps) => {
  const { appSidebarExpand, setAppSidebarExpand } = useAppStore(useShallow(state => ({
    appSidebarExpand: state.appSidebarExpand,
    setAppSidebarExpand: state.setAppSidebarExpand,
  })))
  const sidebarRef = React.useRef<HTMLDivElement>(null)
  const media = useBreakpoints()
  const isMobile = media === MediaType.mobile
  const expand = appSidebarExpand === 'expand'

  const handleToggle = useCallback(() => {
    setAppSidebarExpand(appSidebarExpand === 'expand' ? 'collapse' : 'expand')
  }, [appSidebarExpand, setAppSidebarExpand])

  const isHoveringSidebar = useHover(sidebarRef)

  // Check if the current path is a workflow canvas & fullscreen
  const pathname = usePathname()
  const inWorkflowCanvas = pathname.endsWith('/workflow')
  const isPipelineCanvas = pathname.endsWith('/pipeline')
  const workflowCanvasMaximize = localStorage.getItem('workflow-canvas-maximize') === 'true'
  const [hideHeader, setHideHeader] = useState(workflowCanvasMaximize)
  const { eventEmitter } = useEventEmitterContextContext()

  eventEmitter?.useSubscription((v: any) => {
    if (v?.type === 'workflow-canvas-maximize')
      setHideHeader(v.payload)
  })

  useEffect(() => {
    if (appSidebarExpand) {
      localStorage.setItem('app-detail-collapse-or-expand', appSidebarExpand)
      setAppSidebarExpand(appSidebarExpand)
    }
  }, [appSidebarExpand, setAppSidebarExpand])

  useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.b`, (e) => {
    if (isShortcutFromInputArea(e.target))
      return

    e.preventDefault()
    handleToggle()
  }, { exactMatch: true, useCapture: true })

  if (inWorkflowCanvas && hideHeader) {
    return (
      <div className="flex w-0 shrink-0">
        <AppSidebarDropdown navigation={navigation} />
      </div>
    )
  }

  if (isPipelineCanvas && hideHeader) {
    return (
      <div className="flex w-0 shrink-0">
        <DatasetSidebarDropdown navigation={navigation} />
      </div>
    )
  }

  return (
    <div
      ref={sidebarRef}
      className={cn(
        'flex shrink-0 flex-col border-r border-divider-burn bg-background-default-subtle transition-all',
        expand ? 'w-[216px]' : 'w-14',
      )}
    >
      <div
        className={cn(
          'shrink-0',
          expand ? 'p-2' : 'p-1',
        )}
      >
        {renderHeader?.(appSidebarExpand)}
        {!renderHeader && iconType === 'app' && (
          <AppInfo expand={expand} />
        )}
        {!renderHeader && iconType !== 'app' && (
          <DatasetInfo expand={expand} />
        )}
      </div>
      <div className="relative px-4 py-2">
        <Divider
          type="horizontal"
          bgStyle={expand ? 'gradient' : 'solid'}
          className={cn(
            'my-0 h-px',
            expand
              ? 'bg-linear-to-r from-divider-subtle to-background-gradient-mask-transparent'
              : 'bg-divider-subtle',
          )}
        />
        {!isMobile && isHoveringSidebar && (
          <ToggleButton
            className="absolute top-[-3.5px] -right-3 z-20"
            expand={expand}
            handleToggle={handleToggle}
          />
        )}
      </div>
      <nav
        className={cn(
          'flex grow flex-col gap-y-0.5',
          expand ? 'px-3 py-2' : 'p-3',
        )}
      >
        {renderNavigation?.(appSidebarExpand)}
        {!renderNavigation && navigation.map((item, index) => {
          return (
            <NavLink
              key={index}
              mode={appSidebarExpand}
              iconMap={{ selected: item.selectedIcon, normal: item.icon }}
              name={item.name}
              href={item.href}
              disabled={!!item.disabled}
            />
          )
        })}
      </nav>
      {iconType !== 'app' && extraInfo && extraInfo(appSidebarExpand)}
    </div>
  )
}

export default React.memo(AppDetailNav)
