import { createContext, memo, useContext } from "react"
import styled from "@emotion/styled"
import { css, cx } from "@emotion/css"
import { ControlledMenu, MenuItem } from "@szhsin/react-menu"
import { useTranslation } from "react-i18next"
import { useQuery } from "@apollo/client"
import { useEvent } from "@aet/hooks"
import { Pill } from "~/shared/styled"
import { setActiveFileId } from "~/options/store/actions"
import { getTabs, useDispatch, useSelector } from "~/options/store"
import { useDropdownMenu } from "~/options/hooks/useDropdownMenu"
import { EditorTabQuery, useTabsCloser } from "./utils"
import { isGlobalStyle } from "~/shared"
import { TabCloseButton } from "./CloseDot"

const TabButton = memo((props: TabProps) => {
  const { fileId } = props
  const { t } = useTranslation()
  const { menu, onMouse: onMenu } = useTabMenu(props)
  const dispatch = useDispatch()

  const isActive = useSelector(s => s.activeFileId === fileId)
  const isPreviewFile = useSelector(s => s.previewFileId === fileId)

  const { data } = useQuery(EditorTabQuery, {
    fetchPolicy: "cache-first",
    variables: { id: fileId },
  })

  const file = data?.file

  const name = isGlobalStyle(file) ? t("file.nameGlobalStyle") : file?.name

  return (
    <StyledTabButton
      type="button"
      key={fileId}
      className={cx({
        active: isActive,
        inactive: !isActive,
        ephemeral: isPreviewFile,
      })}
      title={name}
      onContextMenu={onMenu}
      lang={file?.nameLanguage || undefined}
      onClick={useEvent(e => {
        e.stopPropagation()
        dispatch(setActiveFileId(fileId))
      })}
      tabIndex={0}
    >
      <span>{name ?? "..."}</span>
      {file && <TabCloseButton fileId={file.id} fileName={file.name} />}
      {menu}
    </StyledTabButton>
  )
})

const EditorTabsContext = createContext<ReturnType<typeof useTabsCloser>>(undefined!)

export const EditorTabs: React.FC = memo(() => {
  const tabs = useSelector(getTabs)
  const closers = useTabsCloser(tabs)

  return (
    <EditorTabsContext.Provider value={closers}>
      <TabContainer>
        {tabs.map((file, i, { length }) => (
          <TabButton
            fileId={file.id}
            key={file.id}
            canCloseOthers={tabs.length > 1}
            canCloseRight={i < length - 1}
          />
        ))}
      </TabContainer>
    </EditorTabsContext.Provider>
  )
})

interface TabProps {
  fileId: string
  canCloseOthers: boolean
  canCloseRight: boolean
}

function useTabMenu({ fileId, canCloseOthers, canCloseRight }: TabProps) {
  const { t } = useTranslation()
  const ctx = useContext(EditorTabsContext)
  const { menuProps, onMouse } = useDropdownMenu(css`
    .szh-menu__item {
      padding-right: 5px;
    }
  `)

  const menu =
    menuProps.state === "open" ? (
      <ControlledMenu
        {...menuProps}
        className={cx(
          menuProps.className as string,
          canCloseRight &&
            css`
              .szh-menu--state-open {
                min-width: 220px;
              }
            `,
        )}
      >
        <MenuItem onClick={() => ctx.onCloseTab(fileId)}>{t("tabs.verbClose")}</MenuItem>
        {canCloseOthers && (
          <MenuItem onClick={() => ctx.onCloseOthers(fileId)}>
            {t("tabs.verbCloseOthers")}
          </MenuItem>
        )}
        {canCloseRight && (
          <MenuItem onClick={() => ctx.onCloseRight(fileId)}>
            {t("tabs.verbCloseRight")}
          </MenuItem>
        )}
        <MenuItem onClick={() => ctx.onCloseAll()}>{t("tabs.verbCloseAll")}</MenuItem>
      </ControlledMenu>
    ) : null

  return { menu, onMouse }
}

const TabContainer = styled.div`
  display: flex;
  gap: 5px;
  margin-left: 10px;
  margin-top: 5px;
`

const StyledTabButton = styled(Pill)`
  cursor: default;
  padding-right: 7px;
  user-select: none;
  &.inactive {
    border-color: transparent;
    background: none;
  }
  &.ephemeral {
    font-style: italic;
    &:lang(zh),
    &:lang(ja),
    &:lang(ko) {
      font-style: normal;
    }
  }
`
