import {
  ActionIcon,
  Badge,
  Box,
  Combobox,
  Group,
  Highlight,
  Input,
  Menu,
  ScrollArea,
  Stack,
  Typography
} from '@tidbcloud/uikit'
import { useDisclosure } from '@tidbcloud/uikit/hooks'
import {
  IconArrowRight,
  IconBuilding05,
  IconCheck,
  IconChevronDown,
  IconChevronRight,
  IconFolder,
  IconSearchMd
} from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useMemo, useState } from 'react'

import { ORG_TYPE } from 'dbaas/features/Organization'
import { CentralUserProfileOrg, CentralUserProfileProject } from 'dbaas/services/account/interface'
import useStores from 'dbaas/stores/useStores'
import { eventTracking } from 'dbaas/utils/tracking'

import { useOrgSwitch, useProjectSwitch } from './useNavigationSwitch'
import { useNavStatus } from './useNavStatus'

export const OrgProjectPanel = ({
  onClickNextLayer,
  onNavigation
}: {
  onClickNextLayer: (org: CentralUserProfileOrg, project: CentralUserProfileProject) => void
  onNavigation: (projectId: string) => void
}) => {
  const [search, setSearch] = useState('')

  return (
    <Box h={354}>
      <Stack gap={4}>
        <Input
          pr={8}
          size="sm"
          placeholder="Find organization or project..."
          leftSection={<IconSearchMd size={16} c="gray.9" />}
          value={search}
          onChange={(e) => setSearch(e.currentTarget.value)}
          onClick={() => {
            eventTracking('Click search organization or project', {
              source: 'Global Side Navbar Switcher'
            })
          }}
        />
        <ScrollArea.Autosize type="scroll" mah={430} scrollbarSize="var(--combobox-padding)" offsetScrollbars="y">
          <OrgProjectList search={search.trim()} onClickNextLayer={onClickNextLayer} onNavigation={onNavigation} />
        </ScrollArea.Autosize>
      </Stack>
    </Box>
  )
}

const OrgProjectList = observer(
  ({
    search,
    onClickNextLayer,
    onNavigation
  }: {
    search: string
    onClickNextLayer: (org: CentralUserProfileOrg, project: CentralUserProfileProject) => void
    onNavigation: (projectId: string) => void
  }) => {
    const {
      store: { userProfile, allProjects }
    } = useStores()
    const projects = useMemo(() => {
      if (!search) {
        return allProjects
      }
      return allProjects.filter((p) => p.name.toLowerCase().includes(search.toLowerCase()))
    }, [search, allProjects])
    const orgs = useMemo(() => {
      const projectsOrgMap = projects.reduce(
        (prev, cur) => {
          if (!prev[cur.org_id]) {
            prev[cur.org_id] = true
          }
          return prev
        },
        {} as { [k: string]: boolean }
      )
      return userProfile.orgs.filter((o) => projectsOrgMap[o.id] || o.name.toLowerCase().includes(search.toLowerCase()))
    }, [userProfile.orgs, projects, search])

    return (
      <Menu>
        {!orgs.length && (
          <Typography variant="body-lg" c="carbon.7" px={12}>
            No organization
          </Typography>
        )}
        {orgs.map((org) => {
          return (
            <OrgProjectListItem
              key={org.id}
              projects={projects}
              org={org}
              search={search}
              onClickNextLayer={onClickNextLayer}
              onNavigation={onNavigation}
            />
          )
        })}
      </Menu>
    )
  }
)

const OrgProjectListItem = observer(
  ({
    projects,
    org,
    search,
    onClickNextLayer,
    onNavigation
  }: {
    projects: CentralUserProfileProject[]
    org: CentralUserProfileOrg
    search: string
    onClickNextLayer: (org: CentralUserProfileOrg, project: CentralUserProfileProject) => void
    onNavigation: (projectId: string) => void
  }) => {
    const {
      store: {
        lastVisitLocation: { orgId, projectId }
      }
    } = useStores()
    const { isInOrgPages } = useNavStatus()
    const isOrgSelected = orgId === org.id
    const [opened, { toggle }] = useDisclosure(isOrgSelected)
    const visibleProjects = useMemo(() => {
      return projects.filter((p) => p.org_id === org.id)
    }, [projects, org.id])
    const orgSwitch = useOrgSwitch()
    const projectSwitch = useProjectSwitch()
    const isOtherOrgSwitch = orgId !== org.id

    return (
      <>
        <Combobox.Option
          key={org.id}
          value={org.id}
          onClick={async () => {
            eventTracking('Organization Changed', {
              source: 'Global Side Navbar Switcher',
              isOtherOrgSwitch
            })
            onNavigation(org.id)
            orgSwitch(org)
          }}
          sx={{
            wordBreak: 'break-all'
          }}
        >
          <Group gap="xs" justify="space-between" wrap="nowrap">
            <Group gap={8} wrap="nowrap">
              <ActionIcon
                variant="subtle"
                color="gray"
                size="md"
                my={-8}
                mx={-4}
                onClick={async (e) => {
                  e.stopPropagation()
                  toggle()
                  if (opened) {
                    eventTracking('Collapse org', {
                      source: 'Global Side Navbar Switcher'
                    })
                  } else {
                    eventTracking('Expand org', {
                      source: 'Global Side Navbar Switcher'
                    })
                  }
                }}
              >
                {opened ? <IconChevronDown /> : <IconChevronRight />}
              </ActionIcon>
              <Group sx={{ flexShrink: 0 }}>
                <IconBuilding05 size={16} />
              </Group>
              <Highlight highlight={search}>{org.name || `Org (ID: ${org.id})`}</Highlight>
              {org.org_type === ORG_TYPE.ENTERPRISE && (
                <Badge sx={{ pointerEvents: 'none', flexShrink: 0 }}>Ent.</Badge>
              )}
            </Group>
            <Group>{isOrgSelected && <IconCheck c="peacock.7" />}</Group>
          </Group>
        </Combobox.Option>
        {opened &&
          (visibleProjects.length ? (
            visibleProjects.map((project) => {
              const isProjectSelected = projectId === project.id && !isInOrgPages
              return (
                <Group key={project.id} gap={4} justify="space-between" wrap="nowrap">
                  <Combobox.Option
                    pl={62}
                    key={project.id}
                    value={project.id}
                    onClick={async (e) => {
                      e.stopPropagation()
                      eventTracking('Project Changed', {
                        source: 'Global Side Navbar Switcher',
                        isOtherOrgSwitch
                      })
                      onNavigation(project.id)
                      projectSwitch(org, project)
                    }}
                    sx={{
                      flexGrow: 1,
                      wordBreak: 'break-all'
                    }}
                  >
                    <Group gap="xs" justify="space-between" wrap="nowrap">
                      <Group gap="xs" wrap="nowrap">
                        <Group sx={{ flexShrink: 0 }}>
                          <IconFolder size={16} />
                        </Group>
                        <Highlight highlight={search}>{project.name || `Project (ID: ${project.id})`}</Highlight>
                      </Group>

                      <Group gap={8} wrap="nowrap">
                        {isProjectSelected && <IconCheck c="peacock.7" />}
                      </Group>
                    </Group>
                  </Combobox.Option>

                  <ActionIcon
                    variant="subtle"
                    color="carbon"
                    size="md"
                    my={-8}
                    w={33.7}
                    h={33.7}
                    sx={{
                      flexShrink: 0
                    }}
                    onClick={async (e) => {
                      e.stopPropagation()
                      onClickNextLayer(org, project)
                      eventTracking('Click go to cluster panel', {
                        source: 'Global Side Navbar Switcher'
                      })
                    }}
                  >
                    <IconArrowRight />
                  </ActionIcon>
                </Group>
              )
            })
          ) : (
            <Typography variant="body-lg" c="carbon.7" px={12} pl={62}>
              No project
            </Typography>
          ))}
      </>
    )
  }
)
