import { useChartColors } from '@tidb-cloud-uikit/theme/Chart'
import { Menu, Button, Tooltip, Box, Typography, Flex } from '@tidbcloud/uikit'
import { createStyles } from '@tidbcloud/uikit/emotion'
import { IconChevronDown, IconMinus } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useCallback, useMemo, useState, MouseEvent } from 'react'

import { eventTracking } from 'dbaas/utils/tracking'

import { ChartStore } from '../../ChartStore'
import { fieldTypeAggregationMapping } from '../../const'
import {
  Field,
  ChartFormData,
  ColumnUsesEnum,
  Column,
  AggregationEnum,
  FieldTypeEnum,
  ColumnLevelEnum
} from '../../type'
import { duplicateColumnCheck } from '../../util'
import { removeColumnCommand, updateAggregationCommand, updateColumnFieldCommand, updateUsesCommand } from '../Command'

import { AggregationSelector } from './AggregationSelector'
import { ChartSelector } from './ChartSelector'

interface PropsType {
  column: Column
  formData: ChartFormData
  fields: Field[]
  index: number
  level: ColumnLevelEnum
  store: ChartStore
}

const useStyles = createStyles((theme) => ({
  item: {
    width: '100%',
    padding: '10px 0'
  },
  title: {
    fontWeight: 600,
    margin: '0 0 5px 20px',
    color: theme.colors.carbon[9]
  }
}))

export const ColumnPicker: React.FC<React.PropsWithChildren<PropsType>> = observer(
  ({ column, formData, fields, index, level, store }) => {
    const [opened, setOpened] = useState<boolean>(false)

    const [tooltipShow, setTooltipShow] = useState<boolean>(false)

    const currentColumnFormData = formData.columnData[level]

    const { classes } = useStyles()

    const { chartColorsOpacity08 } = useChartColors()

    const fieldEmpty = useMemo(() => {
      return column.field === null
    }, [column.field])

    const aggregationDisplay = useMemo(() => {
      return !fieldEmpty && currentColumnFormData?.withAggregation
    }, [fieldEmpty, column])

    const maxHeight = useMemo(() => {
      return document.body.clientHeight - 100
    }, [])

    const closeMenu = useCallback(() => {
      setOpened(false)
    }, [])

    const handleMouseOver = useCallback((e: MouseEvent<HTMLButtonElement>) => {
      setTooltipShow(e.currentTarget.clientWidth < e.currentTarget.scrollWidth)
    }, [])

    const handleMouseLeave = useCallback((_e: MouseEvent<HTMLButtonElement>) => {
      setTooltipShow(false)
    }, [])

    const target = (
      <Menu.Target>
        <Tooltip label={column.field} opened={tooltipShow} withArrow>
          <Button variant={opened ? 'outline' : 'default'} px={8} size="sm" data-mp-event="mp--1691461017640">
            <Box
              component="span"
              maw={70}
              py={1}
              style={{ overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis', fontWeight: 400 }}
              onMouseOver={handleMouseOver}
              onMouseLeave={handleMouseLeave}
            >
              {column.field}
            </Box>

            <IconChevronDown size={14} />
          </Button>
        </Tooltip>
      </Menu.Target>
    )

    const fieldSelect = (
      <Box
        className={classes.item}
        sx={{
          flex: 1,
          overflowY: 'auto'
        }}
      >
        <Typography variant="action-sm" c="carbon.9" mb={5} ml={20}>
          Column
        </Typography>
        <ChartSelector
          value={column.field}
          data={fields.map((v) => ({
            value: v.name,
            label: v.name,
            icon: v.icon,
            disabled: column.field !== v.name && duplicateColumnCheck(formData, v.name)
          }))}
          onChange={(v) => {
            eventTracking('Chat2Chart Switch Column Field', {
              from: column.field,
              to: v
            })
            const field = fields.filter((f) => f.name === v)[0]
            updateColumnFieldCommand(v, field.type, column)
            store.generateData()
            closeMenu()
          }}
        />
      </Box>
    )

    const useAsSelect = (
      <Box py="xs">
        <Typography variant="action-sm" c="carbon.9" mb={5} ml={20}>
          Use As
        </Typography>
        <ChartSelector
          value={column.uses}
          data={Object.entries(formData.columnData).map(([k, v]) => ({
            value: v.uses,
            label: v.uses,
            level: k,
            icon: v.icon
          }))}
          onChange={(v, data) => {
            if (v) {
              eventTracking('Chat2Chart Switch Column Uses', {
                from: column.uses,
                to: v
              })
              updateUsesCommand(v as ColumnUsesEnum, data.level as ColumnLevelEnum, level, column, formData)
              store.generateData()
            }
            closeMenu()
          }}
        ></ChartSelector>
      </Box>
    )

    const aggregationSelect = (
      <Box py="xs">
        <Typography variant="action-sm" c="carbon.9" mb={5} ml={20}>
          Aggregation
        </Typography>
        <AggregationSelector
          value={column.aggregation}
          data={fieldTypeAggregationMapping[column.fieldType || FieldTypeEnum.String].map((v) => ({
            value: v,
            label: v,
            disabled:
              v === AggregationEnum.None && [FieldTypeEnum.Date, FieldTypeEnum.String].includes(column.fieldType)
          }))}
          onChange={(v) => {
            eventTracking('Chat2Chart Switch Aggregation', {
              from: column.aggregation,
              to: v
            })
            updateAggregationCommand(v as AggregationEnum, column)
            store.generateData()
            closeMenu()
          }}
        />
      </Box>
    )

    const removeColumn = (
      <Flex
        align="center"
        py={5}
        my={5}
        pl={20}
        gap="xs"
        sx={(theme) => ({
          cursor: 'pointer',
          borderRadius: theme.defaultRadius,
          fontWeight: 600,
          color: theme.colors.carbon[8],
          ':hover': { background: theme.colors.carbon[3] }
        })}
        onClick={() => {
          eventTracking('Chat2Chart Remove Column', {
            value: column.field
          })
          removeColumnCommand(column, level, formData)
          store.generateData()
          closeMenu()
        }}
      >
        <IconMinus size={16} />
        <span>Remove Column</span>
      </Flex>
    )

    const useAsDisplay = currentColumnFormData ? (
      currentColumnFormData.onlyOne ? (
        <Box sx={(theme) => ({ color: theme.colors.carbon[8] })}>{column.uses}</Box>
      ) : (
        <Box
          component={currentColumnFormData.icon as any}
          w={16}
          h={16}
          miw={16}
          color={chartColorsOpacity08[index % 7]}
        />
      )
    ) : null

    return (
      <Menu
        transitionProps={{ transition: 'pop' }}
        position="left-end"
        opened={opened}
        withArrow
        arrowPosition="center"
        onChange={setOpened}
      >
        <Flex align="center" mb={8}>
          {useAsDisplay}
          <Box h={1} mx={5} sx={(theme) => ({ flex: 1, borderBottom: `1px solid ${theme.colors.carbon[5]}` })}></Box>
          {target}
        </Flex>

        <Menu.Dropdown>
          <Flex w={220} my={-4} mx={4} direction="column" style={{ maxHeight, overflowY: 'auto', overflowX: 'hidden' }}>
            {fieldSelect}
            <Menu.Divider />
            {!fieldEmpty && [useAsSelect, <Menu.Divider />]}
            {aggregationDisplay && [aggregationSelect, <Menu.Divider />]}
            {!fieldEmpty && removeColumn}
          </Flex>
        </Menu.Dropdown>
      </Menu>
    )
  }
)
