import { ActionIcon, HoverCard, Menu, MenuProps } from '@tidbcloud/uikit'
import { IconDotsHorizontal } from '@tidbcloud/uikit/icons'
// import { sha256 } from 'js-sha256'
import { observer } from 'mobx-react'
import React, { useState } from 'react'
import { useQueryClient } from 'react-query'
import { Link, useHistory } from 'react-router-dom'

import { useAccessCheck } from 'dbaas/contexts/access-control'
import { SharedCluster } from 'dbaas/features/ClusterManagement/cluster'
import {
  DedicatedDeletionModal,
  DedicatedPauseModal,
  DedicatedResumingModal,
  useFetchPause2024Enabled
} from 'dbaas/features/ClusterManagement/dedicated'
import { CloudProviderConst } from 'dbaas/features/Project'
import { DedicatedPwdSettingModal } from 'dbaas/screens/ClusterV2/features/Password/dedicated'
import { useRequestSupport } from 'dbaas/screens/HelpCenter/RequestSupport/helper'
import { getClusterServiceListClustersQueryKey } from 'dbaas/services/api-clients/v2023/cluster-management/v1beta1'
import {
  getTiDBServiceListTidbsQueryKey,
  getTiDBServiceGetTidbQueryKey
} from 'dbaas/services/api-clients/v2023/cluster-management/v1beta2'
import useStores from 'dbaas/stores/useStores'
import { compareVersion } from 'dbaas/utils/chore'
// import { GA4_PAGE_CATEGORY, PRODUCT_TYPES, reportGA } from 'dbaas/utils/tracking'

import { useModifyStatus } from '../ClusterItem/ListItem'
import PauseOrResumeCluster from '../PauseOrResumeCluster'

function getOnClick(disabled?: boolean, fallback?: (e: React.MouseEvent<HTMLElement>) => unknown) {
  if (disabled) {
    return (e: React.MouseEvent<HTMLElement>) => e.preventDefault()
  }

  return fallback || undefined
}

function ClusterOpImport({ cluster }: { cluster: Pick<SharedCluster, 'id' | 'computed'> }) {
  const { id: clusterId, computed } = cluster
  const disabled = !computed?.active
  const disabledTips = !computed?.active ? `Please wait for the cluster to be active.` : ''

  return disabled ? (
    <HoverCard position="left" shadow="md" width={220} withArrow>
      <HoverCard.Target>
        <div>
          <Menu.Item disabled>Import</Menu.Item>
        </div>
      </HoverCard.Target>
      <HoverCard.Dropdown>
        <span>{disabledTips}</span>
      </HoverCard.Dropdown>
    </HoverCard>
  ) : (
    <Menu.Item
      component={Link}
      to={`/clusters/${clusterId}/imports/create-import`}
      data-mp-event="Import Button Clicked"
    >
      Import
    </Menu.Item>
  )
}

interface ClusterOpsProps {
  cluster: Pick<SharedCluster, 'id' | 'displayName' | 'version' | 'provider' | 'region' | 'computed'>
  from?: 'list' | 'overview' | 'my-tidb'
  position?: MenuProps['position']
  actionVariant?: 'subtle' | 'default'
  onMenuOpen?: () => void
}

export const ClusterOperations = observer((props: ClusterOpsProps) => {
  const history = useHistory()
  const queryClient = useQueryClient()
  const { cluster, from = 'list', position, actionVariant = 'default' } = props
  const { id: clusterId, displayName: clusterName, version: clusterVersion, computed } = cluster || {}

  const importAccessible = useAccessCheck('ClusterImportAction')
  const modifyAccessible = useAccessCheck('ClusterModifyGate')
  const resumeAccessible = useAccessCheck('ClusterResume')
  const pauseAccessible = useAccessCheck('ClusterPause')
  const securityAccessible = useAccessCheck('ClusterSecurityAction')
  const deleteAccessible = useAccessCheck('ClusterDelete')

  const {
    store: {
      lastVisitLocation: { orgId, projectId },
      config: { enableAuditLog, oneConsoleEnabled }
    },
    actions: { fetchCluster: actionFetchCluster }
  } = useStores()
  const { open: openSupport } = useRequestSupport()

  const [modalVisible, setModalVisible] = useState({
    dedicatedPause: false,
    dedicatedResume: false,
    pauseOrResume: false,
    auditLog: false,
    dedicatedDelete: false,
    dedicatedPwd: false
  })

  const openModal = (name: keyof typeof modalVisible) => {
    setModalVisible({ ...modalVisible, [name]: true })
  }

  const closeModal = (name: keyof typeof modalVisible) => {
    setModalVisible({ ...modalVisible, [name]: false })
  }

  const pause2024ExpQuery = useFetchPause2024Enabled()

  const { disableModify, modifyTips } = useModifyStatus(cluster)

  const visibleConfig = {
    import: importAccessible,
    modifying: modifyAccessible,
    pause: !computed?.pausing && !computed?.paused,
    resume: computed?.paused,
    auditLog:
      enableAuditLog &&
      cluster.provider?.toLowerCase() !== CloudProviderConst.AZURE &&
      compareVersion(clusterVersion, '5.4.0', '>=')
  }

  const unavailable = !computed?.ready
  const pausedOrResuming = computed?.pausing || computed?.paused || computed?.resuming

  const modifyDisabled =
    unavailable || pausedOrResuming || computed?.unavailable || computed?.modifying || computed?.upgrading

  const pauseDisabled = !computed?.active

  const securityDisabled =
    pausedOrResuming || computed?.unavailable || computed?.maintaining || computed?.creating || computed.inactive

  const trigger = (
    <ActionIcon
      variant={actionVariant}
      w={32}
      h={32}
      aria-label="Cluster operation dropdown menu"
      data-mp-event="Setting Button Clicked"
    >
      <IconDotsHorizontal size={16} />
    </ActionIcon>
  )

  const fetchCluster = async (clusterId: string) => {
    if (oneConsoleEnabled) {
      return await Promise.all([
        actionFetchCluster(clusterId),
        queryClient.invalidateQueries({ queryKey: getTiDBServiceGetTidbQueryKey(clusterId, { orgId }) })
      ])
    }
    return await actionFetchCluster(clusterId)
  }

  const refetchClusterList = async (from: 'list' | 'my-tidb') => {
    if (from === 'list') {
      return await queryClient.invalidateQueries({
        queryKey: getClusterServiceListClustersQueryKey({ orgId, projectId })
      })
    } else if (from === 'my-tidb') {
      return await queryClient.invalidateQueries({ queryKey: getTiDBServiceListTidbsQueryKey({ orgId }) })
    }
  }

  return (
    <>
      <Menu position={position} data-testid="dedicated-cluster-operations" onOpen={props.onMenuOpen}>
        <Menu.Target>{trigger}</Menu.Target>
        <Menu.Dropdown>
          {visibleConfig.import && <ClusterOpImport cluster={cluster} />}

          {/* only primary, dedicated clusters show scale item */}
          {visibleConfig.modifying &&
            (disableModify ? (
              // if modifyTips is empty, the hover card will not be shown
              <HoverCard position="left" shadow="md" width={220} withArrow disabled={!modifyTips}>
                <HoverCard.Target>
                  <div>
                    <Menu.Item disabled>Modify</Menu.Item>
                  </div>
                </HoverCard.Target>
                <HoverCard.Dropdown>{modifyTips}</HoverCard.Dropdown>
              </HoverCard>
            ) : (
              <Menu.Item
                component={Link}
                to={`/clusters/${cluster?.id}/modifying`}
                disabled={modifyDisabled || undefined}
                onClick={getOnClick(modifyDisabled)}
                data-mp-event="Modify Button Clicked"
              >
                Modify
              </Menu.Item>
            ))}

          {visibleConfig.resume && (
            <Menu.Item
              disabled={!resumeAccessible}
              onClick={() => {
                if (pause2024ExpQuery.data) {
                  openModal('dedicatedResume')
                } else {
                  openModal('pauseOrResume')
                }
              }}
              data-mp-event="Try To Resume The Cluster"
            >
              Resume
            </Menu.Item>
          )}

          {visibleConfig.pause && (
            <Menu.Item
              disabled={pauseDisabled || !pauseAccessible}
              onClick={getOnClick(pauseDisabled || !pauseAccessible, () => {
                if (pause2024ExpQuery.data) {
                  openModal('dedicatedPause')
                } else {
                  openModal('pauseOrResume')
                }
              })}
              data-mp-event="Try To Pause The Cluster"
            >
              Pause
            </Menu.Item>
          )}

          <Menu.Item
            onClick={getOnClick(securityDisabled || !securityAccessible, () => {
              openModal('dedicatedPwd')
            })}
            disabled={securityDisabled || !securityAccessible}
            data-mp-event="Password Settings Button Clicked"
          >
            Password Settings
          </Menu.Item>

          <Menu.Item
            disabled={!deleteAccessible}
            onClick={() => {
              openModal('dedicatedDelete')
            }}
            data-mp-event="Open Delete Modal Button Clicked"
          >
            Delete
          </Menu.Item>

          <Menu.Item onClick={() => openSupport()} data-mp-event="Get Support Button Clicked">
            Get Support
          </Menu.Item>
        </Menu.Dropdown>
      </Menu>

      {(visibleConfig.pause || visibleConfig.resume) && !pause2024ExpQuery.data && (
        <PauseOrResumeCluster
          id={clusterId}
          cluster={cluster}
          useNewApi
          visible={modalVisible.pauseOrResume}
          onClose={() => {
            closeModal('pauseOrResume')
          }}
          onFinish={async () => {
            if (from === 'overview') {
              return await fetchCluster(clusterId)
            } else {
              return await refetchClusterList(from)
            }
          }}
        />
      )}
      {visibleConfig.pause && pause2024ExpQuery.data && (
        <DedicatedPauseModal
          clusterId={clusterId}
          clusterName={clusterName}
          opened={modalVisible.dedicatedPause}
          onClose={() => {
            closeModal('dedicatedPause')
          }}
          onFinish={async () => {
            if (from === 'overview') {
              return await fetchCluster(clusterId)
            } else {
              return await refetchClusterList(from)
            }
          }}
        />
      )}
      {visibleConfig.resume && pause2024ExpQuery.data && (
        <DedicatedResumingModal
          clusterId={clusterId}
          clusterName={clusterName}
          opened={modalVisible.dedicatedResume}
          onClose={() => {
            closeModal('dedicatedResume')
          }}
          onFinish={async () => {
            if (from === 'overview') {
              return await fetchCluster(clusterId)
            } else {
              return await refetchClusterList(from)
            }
          }}
        />
      )}
      <DedicatedPwdSettingModal
        clusterId={clusterId}
        clusterName={clusterName}
        opened={modalVisible.dedicatedPwd}
        onClose={() => closeModal('dedicatedPwd')}
      />
      <DedicatedDeletionModal
        cluster={cluster}
        opened={modalVisible.dedicatedDelete}
        onClose={() => {
          closeModal('dedicatedDelete')
        }}
        onFinish={async () => {
          if (from === 'overview') {
            history.replace('/tidbs')
            return
          } else {
            return await refetchClusterList(from)
          }
        }}
      />
    </>
  )
})
