import { Box, Button, Combobox, Stack, Tooltip, Typography, useCombobox } from '@tidbcloud/uikit'
import { useHover } from '@tidbcloud/uikit/hooks'
import { IconBuilding05, IconFolder, IconServer02 } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useMemo, useState } from 'react'
import { useLocation } from 'react-router-dom'

import { useListLoginUserRoles } from 'dbaas/services'
import { useGetUserProfileV2 } from 'dbaas/services/account'
import useStores from 'dbaas/stores/useStores'
import { eventTracking } from 'dbaas/utils/tracking'

import { middleEllipsis, MiddleEllipsisText } from '../components/MiddleEllipsisText'

import { ClusterPanel } from './ClusterPanel'
import { OrgProjectPanel } from './OrgProjectPanel'
import { useCurrentTiDB } from './useCurrentTiDB'
import { useNavStatus } from './useNavStatus'

const NAME_MAX_WIDTH = 135

export const NavSwitcherNextGen = observer(() => {
  const { ref, hovered } = useHover()
  const combobox = useCombobox()
  const {
    store: {
      userProfile: { orgs, projects },
      lastVisitLocation: { orgId, projectId }
    }
  } = useStores()
  const { isLoading: isUserProfileLoading } = useGetUserProfileV2({ query: { enabled: false } })
  const { isLoading: isUserRoleLoading } = useListLoginUserRoles(undefined, {
    query: {
      enabled: false
    }
  })
  const { isInOrgPages, isInClusterPages, isInProjectPages } = useNavStatus()
  const org = orgs.find((o) => o.id === orgId)
  const project = useMemo(() => {
    if (!projectId || !orgId) return null
    return projects.find((p) => p.id === projectId && p.org_id === orgId)
  }, [projects, projectId, orgId])
  const isOrgLoading = isUserProfileLoading || isUserRoleLoading
  const { data: tidb, isLoading: isTidbLoading } = useCurrentTiDB()
  const isClusterLoading = isTidbLoading && isInClusterPages
  const isLoading = isOrgLoading || isClusterLoading
  const inputValue = useMemo(() => {
    if (isLoading) {
      return 'Loading...'
    }
    const orgName = org?.name || org?.id
    const clusterName = tidb?.displayName || tidb?.tidbId
    const projectName = project?.name || project?.id
    if (isInOrgPages) {
      return orgName || ''
    }
    if (isInProjectPages) {
      return projectName || orgName || ''
    }
    if (isInClusterPages) {
      return clusterName || orgName || ''
    }
    return ''
  }, [isInOrgPages, isInProjectPages, isInClusterPages, org, project, tidb, isLoading])
  const truncatedValue = useMemo(() => middleEllipsis(inputValue, NAME_MAX_WIDTH, '700 14px moderat'), [inputValue])
  const leftIcon = useMemo(() => {
    if (isInOrgPages) {
      return <IconBuilding05 size={16} />
    }
    if (isInProjectPages) {
      return <IconFolder size={16} />
    }
    if (isInClusterPages) {
      return <IconServer02 size={16} />
    }
    return null
  }, [isInOrgPages, isInProjectPages, isInClusterPages])

  return (
    <Box px={16} py={6} mx={-16} my={-6}>
      <Tooltip
        label={inputValue}
        maw={600}
        position="top-start"
        offset={2}
        arrowOffset={100}
        openDelay={400}
        disabled={inputValue === truncatedValue || combobox.dropdownOpened || !hovered}
      >
        <Box>
          <Combobox
            store={combobox}
            __staticSelector="Select"
            width="max-content"
            withinPortal
            onOptionSubmit={() => {}}
            position="bottom-start"
            dropdownPadding={8}
            keepMounted={false}
            withArrow={false}
          >
            <Combobox.Target targetType="button">
              <Button
                ref={ref}
                w="100%"
                variant="default"
                aria-label="Organization/Project/Cluster Navigation"
                data-mp-event="Organization/Project/Cluster nav clicked"
                data-mp-source="Global Side Navbar"
                size="md"
                justify="space-between"
                loading={isLoading}
                leftSection={leftIcon}
                rightSection={<Combobox.Chevron size="md" />}
                onClick={() => {
                  combobox.toggleDropdown()
                }}
                styles={(theme) => ({
                  root: {
                    paddingLeft: `${8}px !important`,
                    paddingRight: `${8}px !important`,
                    backgroundColor: `${theme.colors.carbon[1]} !important`,
                    '&:active': {
                      transform: 'none'
                    }
                  },
                  section: {
                    '& > svg': {
                      color: `${theme.colors.carbon[8]} !important`
                    },
                    '&:where([data-position="left"])': {
                      marginInlineEnd: 8
                    },
                    '&:where([data-position="right"])': {
                      marginInlineStart: 8
                    }
                  },
                  label: {
                    flexGrow: 1,
                    textAlign: 'left'
                  }
                })}
              >
                <Typography
                  sx={{
                    fontWeight: 700,
                    fontSize: 14
                  }}
                >
                  <MiddleEllipsisText text={inputValue} width={NAME_MAX_WIDTH} />
                </Typography>
              </Button>
            </Combobox.Target>
            <Combobox.Dropdown autoFocus>
              <NavSwitcherPanel onNavigation={() => combobox.closeDropdown()} />
            </Combobox.Dropdown>
          </Combobox>
        </Box>
      </Tooltip>
    </Box>
  )
})

enum Layer {
  Org = 'org',
  Cluster = 'cluster'
}

const NavSwitcherPanel = observer(({ onNavigation }: { onNavigation: () => void }) => {
  const {
    store: { tenantData }
  } = useStores()
  const location = useLocation()
  const [org, setOrg] = useState(tenantData)
  const isInClusterPages = /^\/tidbs\/\d+.*/.test(location.pathname)
  const [layer, setLayer] = useState(isInClusterPages ? Layer.Cluster : Layer.Org)

  const isInOrgLayer = layer === Layer.Org

  return (
    <Box w={350} h={467}>
      <Stack gap={4}>
        {isInOrgLayer ? (
          <OrgProjectPanel
            onClickNextLayer={(org, _project) => {
              setOrg(org as any)
              setLayer(Layer.Cluster)
            }}
            onNavigation={onNavigation}
          />
        ) : (
          <ClusterPanel
            org={org as any}
            onBack={() => {
              setLayer(Layer.Org)
              eventTracking('Click go to org/project panel', {
                source: 'Global Side Navbar Switcher NextGen'
              })
            }}
            onNavigation={onNavigation}
          />
        )}
      </Stack>
    </Box>
  )
})
