import { Button, Group, Flex, Box, Text, ActionIcon, Loader } from '@tidbcloud/uikit'
import { IconXClose, IconAiExplore01 } from '@tidbcloud/uikit/icons'
import { clsx } from 'clsx'
import { debounce } from 'lodash-es'
import { observer } from 'mobx-react'
import { useEffect, useMemo, useRef, useState } from 'react'
import { useHistory } from 'react-router-dom'

import { HeroComponent } from 'dbaas/components/Measurement'
import AIAggModal from 'dbaas/screens/SqlEditorV2/Editor/AIAggModal'
import { getDataApps } from 'dbaas/services/dataservice'
import useStores from 'dbaas/stores/useStores'

import { useHelpCenterContext } from '../HelpCenter/context'

import { AutoSaveState } from './AutoSaveState'
import Chat2queryEndpoint from './Chat2queryEndpoint'
import EndpointConflictBar from './common/EndpointConflictBar'
import EndpointDeleteModal from './common/EndpointDeleteModal'
import EndpointMessageBar from './common/EndpointMessageBar'
// import SampleDataDetail from './common/SampleDataDetail'
import { AutoSaveStateEnum, useDataApiContext } from './context'
import CreateApp from './CreateApp'
import DataAppDetail from './DataAppDetail'
import Editor from './Editor'
import EditPointActionList from './EditPointActionList'
import Deploy from './EditPointActionList/Deploy'
import { Guide } from './Guide'
import { methodColor, useTestEndpoint, showErrorMsg } from './helpers'
import { useTabsStyles } from './layout.styles'
import MessageLogs from './MessageLogs'
import Panel from './Panel'
import SideMenu from './SideMenu'
import { EndPoint, DataApp } from './types'

const DataService = observer(() => {
  const sqlRef = useRef<HTMLDivElement>(null)
  const sqlContentRef = useRef<HTMLDivElement>(null)
  const [maxHeight, setMaxHeight] = useState(0)
  const isMaxRef = useRef(false)
  const [isRun, setIsRun] = useState(false)
  const {
    store: { activeProjectId, tenantData }
  } = useStores()
  const {
    setEditApp,
    editApp,
    setEditEndpoint,
    editEndpoint,
    editEndpointRef,
    openedEndpList,
    setOpenedEndpList,
    appList,
    setAppList,
    appListRef,
    detailLoading,
    AISetting,
    setAISetting,
    editorSettingLoading,
    scrollEle,
    testRes,
    setAutoSaveState,
    sqlTextRef
  } = useDataApiContext()
  const [loading, setLoading] = useState(true)
  const [isInit, setIsInit] = useState(true)
  const [isAggVisible, setIsAggVisible] = useState(false)
  const { testEndpoint, saveEndpointFromLastModified } = useTestEndpoint()
  const params = new URLSearchParams(window.location.search)
  const isChat2query = params.get('chat2query')
  const history = useHistory()
  const { dataServiceGuideStep, setNoDataAppTooltipShow } = useHelpCenterContext()
  const { classes } = useTabsStyles()

  useEffect(() => {
    getList()

    window.addEventListener('resize', debounce(resize), false)

    return () => {
      window.removeEventListener('resize', resize, false)
    }
  }, [])

  const getList = async () => {
    try {
      const res = await getDataApps(tenantData.id, activeProjectId)

      const list = (res?.data || []) as any as DataApp[]
      setAppList(list)
      appListRef.current = list
      if (isChat2query === '1') {
        initChat2query(list)
      } else {
        initEditP(list)
      }

      setLoading(false)
      // show tooltip for helpcenter when no app exist
      setNoDataAppTooltipShow(list.length === 0)
    } catch (e) {
      setLoading(false)
      showErrorMsg(e, true)
    }
  }

  const initChat2query = (appList: DataApp[]) => {
    const app = appList.find((app) => app.app_type === 'chat2query')
    if (app && app.endpoints?.length) {
      setEditEndpoint(app.endpoints[0])
      editEndpointRef.current = app.endpoints[0]
      setEditApp(null)
      setOpenedEndpList([app.endpoints[0]])
      history.replace('/project/data-service')
    } else {
      initEditP(appList)
    }
  }

  const initEditP = (list: DataApp[]) => {
    const id = localStorage.getItem('data-service-edit-endpoint') || ''
    const ids = id.split('-')

    if (!id || ids.length !== 2) {
      if (list.length) {
        setEditEndpoint(null)
        editEndpointRef.current = null
        setOpenedEndpList([])
        const id = localStorage.getItem('data-service-edit-app') || ''
        const curApp = id ? list.find((app) => `${app.id}` === `${id}`) : null
        if (!curApp) {
          setEditApp(list[0])
        } else {
          setEditApp({
            ...curApp,
            endpoints: []
          })
        }
      }
      return
    }

    const appId = ids[1]
    const pId = ids[0]
    const appIndex = list.findIndex((app) => `${app.id}` === `${appId}`)
    if (appIndex !== -1) {
      const pIndex = (list[appIndex].endpoints || []).findIndex((p) => `${p.id}` === `${pId}`)
      if (pIndex !== -1) {
        const endp = list[appIndex].endpoints[pIndex]
        setEditEndpoint(endp)
        editEndpointRef.current = endp
        setEditApp(null)
        setOpenedEndpList([endp])
      } else {
        if (list[appIndex].endpoints?.length) {
          const endps = list[appIndex].endpoints
          setEditApp(null)
          setEditEndpoint(endps[endps.length - 1])
          editEndpointRef.current = endps[endps.length - 1]
          setOpenedEndpList([endps[endps.length - 1]])
        } else {
          setEditApp(list[appIndex])
          setEditEndpoint(null)
          editEndpointRef.current = null
          setOpenedEndpList([])
        }
      }
    } else if (list.length) {
      setEditEndpoint(null)
      editEndpointRef.current = null
      setEditApp(list[list.length - 1])
      setOpenedEndpList([])
    }
  }

  useEffect(() => {
    if (!appList || !isInit) {
      return
    }

    setIsInit(false)

    initSelectMenu(appList)
  }, [appList])

  const initSelectMenu = (list: DataApp[]) => {
    if (!list?.length) {
      return
    }
    const initAtStart = () => {
      if (list.length) {
        if (list[0].endpoints?.length) {
          setEditEndpoint(list[0].endpoints[0])
          editEndpointRef.current = list[0].endpoints[0]
          setEditApp(null)
        } else {
          setEditApp(list[0])
          setEditEndpoint(null)
          editEndpointRef.current = null
        }
      }
    }
    // the first time here
    if (!editApp && !editEndpoint) {
      initAtStart()
      return
    }

    // last selected has been delete
    const hasApp = editApp && list.some((app) => `${app.id}` === `${editApp.id}`)
    if (hasApp) {
      return
    }
    const hasEndp =
      editEndpoint && list.some((app) => app.endpoints?.some((endp) => `${endp.id}` === `${editEndpoint.id}`))
    if (hasEndp) {
      return
    }

    initAtStart()
  }

  useEffect(() => {
    if (!loading && sqlContentRef.current) {
      setMaxHeight(sqlContentRef.current?.offsetHeight || 0)
    }
  }, [loading, sqlContentRef.current])

  const resize = () => {
    if (sqlContentRef.current) {
      const ele = sqlContentRef.current
      if (isMaxRef.current) {
        setMaxHeight(ele.offsetHeight)
      }
    }
  }

  const runningHeight = () => {
    setIsRun(true)

    setTimeout(() => {
      setIsRun(false)
    })
  }

  useEffect(() => {
    const index = openedEndpList.findIndex((ele) => ele?.id === scrollEle?.id)
    if (index !== -1) {
      const eles = document.getElementsByClassName('endpointItem')
      eles[index] && eles[index].scrollIntoView()
    }
  }, [scrollEle?.id])

  useEffect(() => {
    if (editorSettingLoading) {
      setIsAggVisible(false)
      return
    }

    if (!AISetting.is_privacy_allowed) {
      if (isShowButton()) {
        setIsAggVisible(true)
        return
      }
    }
    setIsAggVisible(false)
  }, [editApp, editEndpoint?.id, editorSettingLoading])

  const isShowButton = () => {
    if (!editEndpoint && !editApp) {
      return false
    }
    return editApp?.app_type === 'chat2query' || ['chat2data', 'chat2eda'].includes(editEndpoint?.type ?? '')
  }

  const app = useMemo(() => {
    return appList.find((app) => `${app.id}` === `${editEndpoint?.dataappp_id}`)
  }, [editEndpoint?.dataappp_id])
  const appType = app ? app.app_type : ''

  if (loading) {
    return (
      <Flex h="100%" align="center" justify="center">
        <Loader />
      </Flex>
    )
  }

  if (!appList.length) {
    return <CreateApp />
  }

  return (
    <Flex h="100%">
      <SideMenu />
      <Flex
        direction="column"
        sx={{
          flex: 1,
          overflow: 'hidden'
        }}
      >
        {!!openedEndpList.length && !editApp && (
          <Flex
            sx={(theme) => ({
              boxShadow: `inset 0 -1px 0 ${theme.colors.carbon[4]}`,
              position: 'relative',
              paddingRight: 16
            })}
          >
            <Box
              sx={{
                flex: 1,
                overflow: 'hidden',
                marginRight: 4
              }}
            >
              <Box
                sx={(t) => ({
                  height: 48,
                  overflowX: 'auto',
                  overflowY: 'hidden',
                  whiteSpace: 'nowrap',
                  '::-webkit-scrollbar': {
                    height: '0px !important'
                  },
                  '&:hover::-webkit-scrollbar': {
                    height: '4px !important'
                  },
                  '&:hover::-webkit-scrollbar-thumb': {
                    backgroundColor: t.colors.carbon[5],
                    borderRadius: 2
                  }
                })}
              >
                {openedEndpList.map((ele: EndPoint, index: number) => (
                  <Box
                    key={index}
                    sx={(theme) => ({
                      color: ele?.id === editEndpoint?.id ? theme.colors.carbon[9] : theme.colors.carbon[7],
                      position: 'relative',
                      display: 'inline-block',
                      minWidth: 120,
                      maxWidth: 200,
                      padding: '0 18px 0 12px',
                      overflow: 'hidden',
                      textOverflow: 'ellipsis',
                      borderRight: `1px solid ${theme.colors.carbon[4]}`,
                      backgroundColor: ele?.id === editEndpoint?.id ? theme.white : '',
                      lineHeight: '48px',
                      fontSize: 12,
                      fontWeight: 700,
                      cursor: 'pointer'
                    })}
                    className={clsx(classes.openedEndpoint, ele?.id === editEndpoint?.id && 'active', 'endpointItem')}
                    onClick={(e: any) => {
                      e.preventDefault()
                      e.stopPropagation()

                      const appIndex = appList.findIndex((app) => `${app.id}` === `${ele.dataappp_id}`)
                      if (appIndex === -1) {
                        return
                      }
                      const endpIndex = (appList[appIndex].endpoints || []).findIndex(
                        (endp) => `${endp.id}` === `${ele.id}`
                      )
                      if (endpIndex === -1) {
                        return
                      }

                      saveEndpointFromLastModified(editEndpointRef.current, sqlTextRef.current)

                      const endp = appList[appIndex].endpoints[endpIndex]

                      setEditEndpoint({ ...endp })
                      editEndpointRef.current = { ...endp }

                      setAutoSaveState(AutoSaveStateEnum.Saved)
                    }}
                  >
                    <Box
                      sx={(theme) => ({
                        position: 'absolute',
                        height: ele?.id === editEndpoint?.id ? 2 : 1,
                        left: 0,
                        right: 0,
                        background: ele?.id === editEndpoint?.id ? theme.black : theme.colors.carbon[4]
                      })}
                    ></Box>

                    <Text component="span" c={methodColor(ele.method)} fw={12} sx={{ marginRight: 4 }}>
                      {ele.method || 'GET'}
                    </Text>
                    <span>{ele?.name}</span>
                    {openedEndpList.length > 1 && (
                      <ActionIcon
                        aria-label="Delete"
                        variant="subtle"
                        component="span"
                        className="delete-btn"
                        sx={{
                          position: 'absolute',
                          right: 2,
                          top: 16,
                          minWidth: 20,
                          minHeight: 20,
                          width: 20,
                          height: 20
                        }}
                        onClick={async (e: any) => {
                          e.preventDefault()
                          e.stopPropagation()

                          const curList = openedEndpList.slice().filter((p) => p.id !== ele.id)
                          setOpenedEndpList(curList)

                          if (editEndpoint?.id !== ele.id) {
                            await saveEndpointFromLastModified(editEndpointRef.current, sqlTextRef.current)
                          }
                          const len = curList.length
                          if (!len) {
                            return
                          }

                          const lastEndp = curList[len - 1]
                          const endp = appList
                            .find((app) => `${app.id}` === `${lastEndp.dataappp_id}`)
                            ?.endpoints?.find((endp) => `${endp.id}` === `${lastEndp.id}`)
                          if (endp) {
                            setEditApp(null)
                            setEditEndpoint(endp)
                            editEndpointRef.current = endp
                          }
                          setAutoSaveState(AutoSaveStateEnum.Saved)
                        }}
                      >
                        <IconXClose size={14} />
                      </ActionIcon>
                    )}
                  </Box>
                ))}
              </Box>
            </Box>
            {!editApp && appType !== 'chat2query' ? (
              <Group justify="flex-end">
                <AutoSaveState />
                <Button
                  data-guide="test"
                  disabled={!editEndpoint?.cluster_id || editEndpoint?.cluster_id === '0'}
                  size="xs"
                  variant="default"
                  data-testid="test-endpoint"
                  data-mp-event="DataService test endpoint clicked"
                  onClick={testEndpoint}
                  loading={testRes?.loading}
                >
                  Test
                </Button>

                <Deploy endpoint={editEndpoint as EndPoint} source="topMenu" />

                {!AISetting.is_privacy_allowed && (
                  <Button
                    size="xs"
                    variant="default"
                    onClick={() => setIsAggVisible(true)}
                    data-mp-event="mp--1691461012912"
                  >
                    <IconAiExplore01 size={16} />
                  </Button>
                )}
                <EditPointActionList rename={false} endpoint={editEndpoint as EndPoint} source="topMenu" />
              </Group>
            ) : null}
          </Flex>
        )}

        {editApp ? (
          <DataAppDetail />
        ) : (
          <>
            <EndpointConflictBar />
            <EndpointMessageBar />

            <Flex
              sx={(t) => ({
                flex: 1,
                overflow: 'hidden',
                position: 'relative',
                backgroundColor: t.white
              })}
            >
              {detailLoading && (
                <Flex h="100%" w="100%" align="center" justify="center">
                  <Loader />
                </Flex>
              )}

              {!detailLoading && <HeroComponent name="c_/data-service/editor" />}
              {editEndpoint?.sql_template !== undefined && (
                <>
                  {appType === 'chat2query' ? (
                    <Chat2queryEndpoint />
                  ) : (
                    <>
                      <Flex
                        direction="column"
                        sx={{
                          flex: 1,
                          position: 'relative',
                          height: '100%',
                          overflow: 'hidden'
                        }}
                        ref={sqlContentRef}
                      >
                        <Box sx={{ flex: 1 }} ref={sqlRef} data-guide="editor">
                          <Editor onRun={runningHeight} />
                        </Box>

                        <MessageLogs sqlRef={sqlRef} maxHeight={maxHeight} isRun={isRun} />
                      </Flex>
                      <Panel />
                      {/* <SampleDataDetail /> */}
                    </>
                  )}
                </>
              )}
            </Flex>
          </>
        )}
      </Flex>

      {isAggVisible && (
        <AIAggModal
          showCloseButton={!isShowButton()}
          onReset={(isAccept) => {
            setIsAggVisible(false)
            setAISetting({
              chat2query_init: true,
              is_privacy_allowed: isAccept,
              privacy_box_count: AISetting.privacy_box_count + 1
            })
          }}
        />
      )}
      <EndpointDeleteModal />
      {dataServiceGuideStep > 1 && <Guide />}
    </Flex>
  )
})

export default DataService
