import { OverflowTooltip } from '@tidb-cloud/ui-components/components/Text'
import { Accordion, Box, Flex, Input, Text } from '@tidbcloud/uikit'
import { IconSystemEndpoint } from '@tidbcloud/uikit/icons'
import { useMemo } from 'react'

import { patchEndpoint } from 'dbaas/services/dataservice'

import { useDataApiContext, AutoSaveStateEnum } from '../context'
import EditPointActionList from '../EditPointActionList'
import { filterEmojis, methodColor, useTestEndpoint } from '../helpers'
import { EndPoint, DataApp } from '../types'

import { useStyles } from './index.styles'

interface EndpointItemProps {
  app: DataApp
  expandVal: string[]
}

const EndpointItem: React.FC<React.PropsWithChildren<EndpointItemProps>> = ({ app, expandVal }) => {
  const {
    orgId,
    projectId,
    editEndpoint,
    setEditEndpoint,
    editApp,
    setEditApp,
    openedEndpList,
    setOpenedEndpList,
    renamedEndpoint,
    setRenamedEndpoint,
    editEndpointRef,
    setScrollEle,
    setAutoSaveState,
    sqlTextRef,
    setIsAutoSaveClose,
    appList,
    setAppList,
    appListRef
  } = useDataApiContext()
  const nameReg = /^[A-Za-z0-9 \_\-\/\[\]]*$/
  const { saveEndpointFromLastModified } = useTestEndpoint()
  const { classes } = useStyles()

  const updateEndPoint = async (endpoint: EndPoint, name: string) => {
    setIsAutoSaveClose(true)
    try {
      const res = await patchEndpoint(orgId, projectId, `${endpoint.dataappp_id}`, `${endpoint.id}`, {
        name
      })

      if (res.code === 200) {
        // update endpoint
        const apps = appList.slice()
        const app = apps.find((app) => `${app.id}` === `${endpoint.dataappp_id}`)
        if (app) {
          const endp = (app.endpoints || []).find((endp) => `${endp.id}` === `${endpoint.id}`)
          if (endp) {
            endp.name = name
            endp.vid = res.endpoint?.vid || ''
            setAppList(apps)
            appListRef.current = apps
          }

          if (editEndpoint?.id === endpoint.id) {
            const curEndp = {
              ...editEndpointRef.current,
              name,
              vid: res.endpoint?.vid || ''
            } as EndPoint
            setEditEndpoint(curEndp)
            editEndpointRef.current = curEndp
          }
        }

        // update tabs
        const list = openedEndpList.slice()
        const renameTabItem = list.find((item) => item.id === endpoint.id)
        if (renameTabItem) {
          renameTabItem.name = name
          setOpenedEndpList(list)
        }
      }
      setIsAutoSaveClose(false)
    } catch (_e) {
      setIsAutoSaveClose(false)
    }
  }

  const endpNameChange = (endp: EndPoint, name: string) => {
    if (!(name || '').trim()) {
      setRenamedEndpoint(null)
      return
    }

    updateEndPoint(endp, name)
    setRenamedEndpoint(null)
  }

  const isRenderEndpointList = useMemo(() => {
    return (
      !!app.endpoints?.length &&
      (app.endpoints[0].dataappp_id === editEndpoint?.dataappp_id ||
        `${app.endpoints[0].dataappp_id}` === `${editApp?.id}` ||
        expandVal.includes(`${app.endpoints[0].dataappp_id}`))
    )
  }, [app, expandVal, editApp, editEndpoint])

  return (
    <>
      {isRenderEndpointList && (
        <Accordion.Panel>
          {app.endpoints?.map((endpoint) => (
            <Box key={endpoint.id} data-guide={`endpoint-${endpoint.id}`}>
              <Flex
                justify="space-between"
                align="center"
                className={classes.accordionItem}
                sx={(theme) => ({
                  padding: '0 1px 0 4px',
                  fontSize: 13,
                  lineHeight: '28px',
                  cursor: 'pointer',
                  borderRadius: '4px',
                  marginBottom: '2px',
                  whiteSpace: 'nowrap',
                  backgroundColor: editEndpoint?.id === endpoint.id ? theme.colors.carbon[3] : theme.white,
                  '&:hover': {
                    backgroundColor: theme.colors.carbon[3]
                  }
                })}
                key={endpoint.id}
              >
                {endpoint?.id === renamedEndpoint?.id ? (
                  <Input
                    autoFocus
                    defaultValue={endpoint?.name}
                    maxLength={32}
                    styles={() => ({
                      wrapper: {
                        width: '100%'
                      },
                      input: {
                        height: '28px',
                        minHeight: '28px',
                        lineHeight: '28px',
                        borderRadius: '4px'
                      }
                    })}
                    onBlur={(e: any) => endpNameChange(endpoint, filterEmojis(e.target.value))}
                    onKeyDown={(e: any) => {
                      const val = filterEmojis(e.target.value)
                      if (e.code === 'Enter') {
                        endpNameChange(endpoint as any, val)
                      } else if (!nameReg.test(e.key)) {
                        e.preventDefault()
                      }
                    }}
                  />
                ) : (
                  <Box
                    component="div"
                    sx={() => ({
                      maxWidth: '100%',
                      overflow: 'hidden',
                      textOverflow: 'ellipsis',
                      flex: 1,
                      display: 'flex',
                      alignItems: 'center'
                    })}
                    onClick={(e: any) => {
                      e.preventDefault()
                      e.stopPropagation()

                      if (editEndpointRef.current?.id === endpoint.id) {
                        return
                      }

                      saveEndpointFromLastModified(editEndpointRef.current, sqlTextRef.current)

                      if (!openedEndpList.some((item) => item.id === endpoint.id)) {
                        setOpenedEndpList(openedEndpList.concat(endpoint))
                      }

                      setEditApp(null)
                      setEditEndpoint(endpoint)
                      editEndpointRef.current = endpoint
                      setScrollEle(endpoint)
                      setAutoSaveState(AutoSaveStateEnum.Saved)
                    }}
                  >
                    <Box
                      component="span"
                      sx={(theme) => ({
                        display: 'inline-block',
                        width: '8px',
                        height: '8px',
                        marginRight: '8px',
                        borderRadius: '50%',
                        flexShrink: 0,
                        backgroundColor: endpoint.is_online
                          ? endpoint.has_modified
                            ? theme.colors.green[4]
                            : theme.colors.green[7]
                          : theme.colors.carbon[5]
                      })}
                    />
                    <Text
                      component="span"
                      c={methodColor(endpoint.method)}
                      sx={() => ({
                        display: 'inline-block',
                        width: '36px',
                        marginRight: '4px',
                        flexShrink: 0
                      })}
                    >
                      {endpoint.method === 'DELETE' ? 'DEL' : endpoint.method || 'GET'}
                    </Text>
                    {endpoint.type === 'system-data' && (
                      <Box
                        component={IconSystemEndpoint}
                        size={14}
                        mr={4}
                        w={16}
                        h={16}
                        sx={(t) => ({
                          backgroundColor: t.colors.carbon[5],
                          borderRadius: 4,
                          lineHeight: '20px',
                          textAlign: 'center'
                        })}
                      />
                    )}
                    <OverflowTooltip
                      minWidth={200}
                      withArrow
                      className={classes.EndpointName}
                      label={
                        <Box
                          sx={{
                            wordBreak: 'break-all'
                          }}
                        >
                          {endpoint.name}
                        </Box>
                      }
                    >
                      <Box
                        sx={{
                          overflow: 'hidden',
                          textOverflow: 'ellipsis'
                        }}
                      >
                        {endpoint.name}
                      </Box>
                    </OverflowTooltip>
                  </Box>
                )}
                {app.app_type !== 'chat2query' && endpoint?.id !== renamedEndpoint?.id && (
                  <EditPointActionList
                    onRename={() => {
                      setRenamedEndpoint(endpoint)
                    }}
                    endpoint={endpoint}
                    source="sideMenu"
                  />
                )}
              </Flex>
            </Box>
          ))}
        </Accordion.Panel>
      )}
    </>
  )
}

export default EndpointItem
