import { notifier } from '@tidbcloud/uikit'
import { ActionIcon, Alert, Button, Code, Divider, Flex, List, Menu, Modal, Typography } from '@tidbcloud/uikit'
import { Form, FormTextInput } from '@tidbcloud/uikit/biz'
import { IconDotsHorizontal } from '@tidbcloud/uikit/icons'
import { useEffect, useState } from 'react'
import { useForm } from 'react-hook-form'

import {
  dumpDataApiEndpoint,
  deleteDataApiEndpoint,
  offlineDataApiEndpoint,
  getEndpointVersions
} from 'dbaas/services/dataservice'

import SystemDataCodeExample from '../Chat2queryEndpoint/CodeExample'
import { useDataApiContext } from '../context'
import { useChangeEndpointStatus, showErrorMsg } from '../helpers'
import { DataApp, EndPoint, VersionItem } from '../types'

import CodeExample from './CodeExample'

const EditPointActionList: React.FC<
  React.PropsWithChildren<{
    endpoint: EndPoint
    onRename?: () => void
    rename?: boolean
    source?: 'topMenu' | 'sideMenu'
  }>
> = ({ endpoint, rename = true, onRename = () => {}, source = '' }) => {
  const {
    orgId,
    projectId,
    appListRef,
    getAppList,
    setAppList,
    setEditEndpoint,
    editEndpointRef,
    setEditApp,
    openedEndpList,
    setOpenedEndpList,
    setVersions,
    setIsAutoSaveClose
  } = useDataApiContext()
  const { update: updateEndpointStatus } = useChangeEndpointStatus()
  const formProps = useForm<{ endpoint_name: string; system_endpoint_name: string }>({})
  const { watch } = formProps
  const name = watch('endpoint_name')
  const systemEndpName = watch('system_endpoint_name')

  const [opened, setOpened] = useState(false)
  const [undeployOpened, setUndeployOpened] = useState(false)
  const [deleteOpend, setDeleteOpened] = useState(false)
  const [removeOpened, setRemoveOpened] = useState(false)

  useEffect(() => {
    setIsAutoSaveClose(deleteOpend || removeOpened)
  }, [deleteOpend, removeOpened])

  const duplicateEndp = async () => {
    const res = await dumpDataApiEndpoint(orgId, projectId, `${endpoint?.dataappp_id}`, `${endpoint?.id}`)
    if (res.code === 200) {
      const newEndp = res.endpoint as EndPoint
      setEditEndpoint(newEndp)
      editEndpointRef.current = newEndp

      const openList = openedEndpList.slice()
      openList.push(newEndp)
      setOpenedEndpList(openList)

      getAppList()
    } else {
      notifier.error(res.message)
    }
  }

  const deleteEndpoint = async () => {
    const deleteId = endpoint?.dataappp_id
    try {
      const res = await deleteDataApiEndpoint(orgId, projectId, `${deleteId}`, `${endpoint?.id}`)
      if (res?.code !== 200) {
        throw new Error(res.message)
      }

      setDeleteOpened(false)
      setRemoveOpened(false)

      const apps = [...appListRef.current]
      const app = apps.find((app) => `${app.id}` === `${deleteId}`)
      if (app) {
        app.endpoints = app.endpoints.filter((enp) => enp.id !== endpoint?.id)
      }
      setAppList(apps)

      const openL = openedEndpList.filter((enp) => enp.id !== endpoint?.id)
      setOpenedEndpList(openL)

      if (`${editEndpointRef.current?.id}` === `${endpoint?.id}`) {
        if (openL.length) {
          setEditEndpoint(openL[openL.length - 1])
          editEndpointRef.current = openL[openL.length - 1]

          setEditApp(null)
        } else {
          setEditEndpoint(null)
          editEndpointRef.current = null
          setEditApp(app as DataApp)
        }
      }
    } catch (e) {
      showErrorMsg(e)
    }
  }

  const undeploy = async () => {
    const dataappId = endpoint?.dataappp_id
    const endpointId = endpoint?.id

    try {
      await offlineDataApiEndpoint(orgId, projectId, `${dataappId}`, `${endpointId}`)
      const res = await getEndpointVersions(orgId, projectId, `${dataappId}`, `${endpointId}`)

      if (res.code === 200) {
        notifier.success(`The endpoint ${endpoint.name} has been un-deployed successfully`)
        setVersions(res.data as VersionItem[])
        updateEndpointStatus(`${dataappId}`, `${endpointId}`, 0)
        const newEndp = {
          ...editEndpointRef.current,
          has_modified: true
        } as EndPoint
        setEditEndpoint(newEndp)
        editEndpointRef.current = newEndp
        setUndeployOpened(false)
      } else {
        throw new Error(res.message)
      }
    } catch (e) {
      showErrorMsg(e)
    }
  }

  const isSystemEndpoint = endpoint?.type === 'system-data'

  return (
    <>
      <Menu
        position="bottom-end"
        offset={2}
        styles={(theme) => ({
          itemLabel: {
            color: theme.colors.carbon[8]
          },
          item: {
            '&[data-hovered]': {
              backgroundColor: theme.colors.carbon[4]
            }
          }
        })}
      >
        <Menu.Target>
          <ActionIcon variant={source === 'sideMenu' ? 'transparent' : 'default'}>
            <IconDotsHorizontal width={16} height={16} />
          </ActionIcon>
        </Menu.Target>
        <Menu.Dropdown>
          {rename && !isSystemEndpoint && (
            <Menu.Item data-mp-event="DataService endpoint rename clicked" data-mp-source={source} onClick={onRename}>
              Rename
            </Menu.Item>
          )}
          {!isSystemEndpoint && (
            <Menu.Item
              data-mp-event="DataService endpoint duplicate clicked"
              data-mp-source={source}
              onClick={duplicateEndp}
            >
              Duplicate
            </Menu.Item>
          )}
          <Menu.Item
            data-mp-event="DataService endpoint code example clicked"
            data-mp-source={source}
            onClick={() => {
              setOpened(true)
            }}
          >
            Code Example
          </Menu.Item>

          {!!endpoint?.is_online && !isSystemEndpoint && (
            <Menu.Item
              data-mp-event="DataService endpoint undeploy clicked"
              data-mp-source={source}
              onClick={() => setUndeployOpened(true)}
            >
              Undeploy
            </Menu.Item>
          )}

          {isSystemEndpoint ? (
            <Menu.Item
              data-mp-event="DataService endpoint remove clicked"
              data-mp-source={source}
              onClick={() => setRemoveOpened(true)}
            >
              Remove
            </Menu.Item>
          ) : (
            <Menu.Item
              data-mp-event="DataService endpoint delete clicked"
              data-mp-source={source}
              onClick={() => setDeleteOpened(true)}
            >
              Delete
            </Menu.Item>
          )}
        </Menu.Dropdown>
      </Menu>
      {endpoint?.type === 'system-data' ? (
        <SystemDataCodeExample default={opened} endpoint={endpoint} onClose={() => setOpened(false)} />
      ) : (
        <CodeExample endpoint={endpoint} open={opened} onClose={() => setOpened(false)} source={source} />
      )}

      <Modal
        title="Are you sure to undeploy endpoint?"
        centered
        trapFocus={false}
        opened={undeployOpened}
        onClose={() => setUndeployOpened(false)}
      >
        <Typography variant="body-lg">After you undeploy the endpoint, it will not be accessible.</Typography>
        <Typography variant="body-lg">Are you sure you want to undeploy this endpoint? </Typography>

        <Flex justify="flex-end" gap={24} mt={24}>
          <Button variant="default" onClick={() => setUndeployOpened(false)} data-mp-event="mp-cancel-1691461014885">
            Cancel
          </Button>
          <Button onClick={undeploy} data-mp-event="mp-undeploy-1691461014888">
            Undeploy
          </Button>
        </Flex>
      </Modal>

      <Modal
        size={600}
        title={
          <Typography variant="body-lg" sx={{ wordBreak: 'break-all' }}>
            Are you sure you want to delete the endpoint <b>{endpoint?.name}</b>?
          </Typography>
        }
        opened={deleteOpend}
        centered
        trapFocus={false}
        onClose={() => setDeleteOpened(false)}
      >
        <Typography variant="body-lg">Before deleting the Endpoint, please consider the following:</Typography>
        <Alert color="yellow" my={16}>
          <List
            styles={(theme) => ({
              item: {
                color: theme.colors.yellow[9],
                fontSize: 14,
                '*': {
                  paddingRight: 4,
                  wordBreak: 'break-word'
                }
              }
            })}
          >
            <List.Item>Deleting the Endpoint is a permanent action and cannot be undone.</List.Item>
            <List.Item>Once deleted, the Endpoint will no longer be available.</List.Item>
          </List>
        </Alert>

        <Typography variant="body-lg">
          We strongly recommend that you carefully review these considerations before proceeding with the deletion of
          the Endpoint.
        </Typography>

        <Divider my="lg"></Divider>

        <Typography variant="body-lg" mb={8}>
          Please type
          <Code fz={13} fw={600} bg="carbon.3" mx={4} sx={{ userSelect: 'all' }}>
            {endpoint?.name}
          </Code>
          to confirm deleting:
        </Typography>
        <Form
          onCancel={() => setDeleteOpened(false)}
          formMode="onChange"
          actionsProps={{
            confirmProps: {
              disabled: name !== endpoint?.name,
              color: 'red',
              variant: 'light'
            },
            confirmText: 'Delete'
          }}
          form={formProps}
          onSubmit={deleteEndpoint}
        >
          <FormTextInput
            name="endpoint_name"
            placeholder="Enter Endpoint Name to Delete"
            rules={{
              required: true,
              validate: (value) => value === endpoint?.name || 'Incorrect endpoint name'
            }}
          />
        </Form>
      </Modal>

      <Modal
        size={600}
        title={
          <Typography variant="body-lg" sx={{ wordBreak: 'break-all' }}>
            Are you sure you want to remove the endpoint `<b>{endpoint?.name}</b>`
          </Typography>
        }
        opened={removeOpened}
        centered
        trapFocus={false}
        onClose={() => setRemoveOpened(false)}
      >
        <Typography variant="body-lg" mb={24}>
          Before removing the endpoint, please consider the following:
        </Typography>

        <Typography variant="title-md">Once removed, the endpoint will no longer be available.</Typography>
        <Typography variant="title-md" mb={24}>
          Endpoints can be added back using ‘Manage Endpoint Library’ option.
        </Typography>

        <Typography variant="body-lg" mb={24}>
          We strongly recommend that you carefully review these considerations before proceeding with the removal of the
          endpoint.
        </Typography>

        <Typography variant="body-lg" mb={8}>
          To confirm removing, please type
          <Code fz={13} fw={600} bg="carbon.3" mx={4}>
            {endpoint?.name}
          </Code>
        </Typography>
        <Form
          onCancel={() => setRemoveOpened(false)}
          formMode="onChange"
          actionsProps={{
            confirmProps: {
              disabled: systemEndpName !== endpoint?.name,
              color: 'red'
            },
            confirmText: 'Remove'
          }}
          form={formProps}
          onSubmit={deleteEndpoint}
        >
          <FormTextInput
            name="system_endpoint_name"
            placeholder="Enter Endpoint Name to Remove"
            rules={{
              required: true,
              validate: (value) => value === endpoint?.name || 'Incorrect endpoint name'
            }}
          />
        </Form>
      </Modal>
    </>
  )
}

export default EditPointActionList
