import { ActionIcon, Badge, Center, Group, Menu, Modal, Stack, Typography } from '@tidbcloud/uikit'
import { Form, MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import { useDisclosure } from '@tidbcloud/uikit/hooks'
import { IconDotsHorizontal } from '@tidbcloud/uikit/icons'
import { sha256 } from 'js-sha256'
import { capitalize } from 'lodash-es'
import { observer } from 'mobx-react'
import { useContext, useEffect, useState } from 'react'

import { HeroComponent } from 'dbaas/components/Measurement'
import TimeComponent from 'dbaas/components/TimeComponent'
import { AccessCheck } from 'dbaas/contexts/access-control'
import { SharedCluster } from 'dbaas/features/ClusterManagement/cluster'
import { ServerlessConnectionV2 } from 'dbaas/screens/ClusterV2/features/Connection/serverless'
import { deleteBranch } from 'dbaas/services/api-clients/legacy/serverless'
import {
  ConsoleBasicBranch as ServerlessBasicBranch,
  ConsoleBranchState as ServerlessBranchState
} from 'dbaas/services/api-clients/legacy/serverless/interface'
import useStores from 'dbaas/stores/useStores'
import { eventTracking, GA4_PAGE_CATEGORY, PRODUCT_TYPES, reportGA } from 'dbaas/utils/tracking'

import { ServerlessBranchContext } from './context'
import { CreateBranchModal } from './CreateBranchModal'
import { getParentBranchName } from './helper'
import { RenameModal } from './RenameModal'
import { ResetBranchModal } from './ResetBranchModal'

export const BranchList: React.FC<React.PropsWithChildren<{ cluster: SharedCluster }>> = observer((props) => {
  const {
    store: { tenantData, activeProject, userProfile }
  } = useStores()
  const branchActionAccessCheckProps = {
    id: 'TidbxBranchAction' as const,
    scopeProps: { tidbId: props.cluster.id }
  }

  const [currentPage, setCurrentPage] = useState(1)

  const perPage = 10

  const [modalShow, setModalShow] = useState<boolean>(false)

  const [connectShow, setConnectShow] = useState<boolean>(false)

  const [branchDetail, setBranchDetail] = useState<ServerlessBasicBranch>()

  const [createModalOpened, createModalHandlers] = useDisclosure()

  const [resetModalOpened, resetModalHandlers] = useDisclosure()

  const [renameModalOpened, renameModalHandlers] = useDisclosure()

  const { getBranchList, branchList, branchListLoading, branchListLoaded } = useContext(
    ServerlessBranchContext
  ) as ServerlessBranchContext

  useEffect(() => {
    getBranchList(perPage, currentPage)
    const timer = setInterval(() => getBranchList(perPage, currentPage, false), 6000)
    return () => clearInterval(timer)
  }, [perPage, currentPage])

  useEffect(() => eventTracking('Serverless branch page view'), [])

  const handleDelete: React.MouseEventHandler<HTMLButtonElement> = async () => {
    await deleteBranch(tenantData.id, activeProject.id, props.cluster.id, branchDetail?.id || '')
    getBranchList()
    setModalShow(false)
  }

  const columns: MRT_ColumnDef<ServerlessBasicBranch>[] = [
    {
      header: 'Name',
      id: 'Name',
      accessorKey: 'display_name'
    },
    {
      header: 'Parent',
      accessorFn: (row) => {
        return <Group gap="xs">{getParentBranchName(row)}</Group>
      }
    },
    {
      header: 'Status',
      id: 'status',
      size: 120,
      accessorFn: (row) => {
        let color = '',
          state = row.state
        switch (row.state) {
          case ServerlessBranchState.CREATING:
            color = 'carbon.6'
            break
          case ServerlessBranchState.READY:
            color = 'green'
            state = 'ACTIVE'
            break
        }
        return (
          <Badge color={color} variant="dot" size="lg">
            {capitalize(state)}
          </Badge>
        )
      }
    },
    {
      header: 'Row Storage',
      id: 'rowStorage',
      accessorFn: (row) => {
        return row.usages.row_storage && formatBytes(+row.usages.row_storage, 2)
      }
    },
    {
      header: 'Creation Time',
      accessorFn: (row) => <TimeComponent time={row.create_time} />
    },
    {
      header: 'Action',
      id: 'action',
      size: 100,
      accessorFn: (row) => (
        <Menu width="200" position="bottom-end">
          <Menu.Target>
            <ActionIcon variant="subtle" w={32} h={32}>
              <IconDotsHorizontal width={16} height={16} />
            </ActionIcon>
          </Menu.Target>
          <Menu.Dropdown w={140}>
            <Menu.Item
              disabled={row.state !== ServerlessBranchState.READY}
              onClick={() => {
                reportGA({
                  event: 'connect_button_click',
                  page_category: GA4_PAGE_CATEGORY.CLUSTER_BRANCHES,
                  product_type: PRODUCT_TYPES.SERVERLESS,
                  user_id: sha256(userProfile.email)
                })
                setBranchDetail(row)
                setConnectShow(true)
              }}
              data-mp-event="Serverless branch connect clicked"
            >
              Connect
            </Menu.Item>
            <AccessCheck {...branchActionAccessCheckProps}>
              {({ accessible }) => (
                <Menu.Item
                  disabled={row.state !== ServerlessBranchState.READY || !accessible}
                  onClick={() => {
                    setBranchDetail(row)
                    createModalHandlers.open()
                  }}
                  data-mp-event="Serverless branch create clicked"
                >
                  Create branch
                </Menu.Item>
              )}
            </AccessCheck>
            <AccessCheck {...branchActionAccessCheckProps}>
              {({ accessible }) => (
                <Menu.Item
                  disabled={row.state !== ServerlessBranchState.READY || !accessible}
                  onClick={() => {
                    setBranchDetail(row)
                    resetModalHandlers.open()
                  }}
                  data-mp-event="Serverless branch reset clicked"
                >
                  Reset
                </Menu.Item>
              )}
            </AccessCheck>
            <AccessCheck {...branchActionAccessCheckProps}>
              {({ accessible }) => (
                <Menu.Item
                  disabled={row.state !== ServerlessBranchState.READY || !accessible}
                  onClick={() => {
                    setBranchDetail(row)
                    renameModalHandlers.open()
                  }}
                  data-mp-event="Serverless branch rename clicked"
                >
                  Rename
                </Menu.Item>
              )}
            </AccessCheck>
            <AccessCheck {...branchActionAccessCheckProps}>
              {({ accessible }) => (
                <Menu.Item
                  disabled={!accessible}
                  onClick={() => {
                    setBranchDetail(row)
                    setModalShow(true)
                  }}
                  data-mp-event="Serverless branch delete clicked"
                >
                  Delete
                </Menu.Item>
              )}
            </AccessCheck>
          </Menu.Dropdown>
        </Menu>
      )
    }
  ]

  return (
    <>
      {branchListLoaded && <HeroComponent />}
      <ProTable
        columns={columns}
        data={branchListLoading ? [] : branchList?.branches || []}
        loading={branchListLoading}
        mantinePaperProps={{ mx: 24 }}
        mantineTableHeadCellProps={{
          sx: {
            ':first-of-type': { paddingLeft: '24px !important' }
          }
        }}
        mantineTableBodyCellProps={{
          sx: {
            ':first-of-type': { paddingLeft: '24px !important' }
          }
        }}
        manualPagination={true}
        pagination={
          branchList?.total
            ? {
                position: 'center',
                total: Math.ceil((branchList?.total || 0) / perPage) || 0,
                value: currentPage || 1,
                onChange: (page) => {
                  setCurrentPage(page)
                  getBranchList(perPage, page)
                }
              }
            : undefined
        }
        errorMessage="No data"
        renderEmptyRowsFallback={() => (
          <Center sx={{ height: 'calc(100vh - 220px)' }}>
            <Stack w={800} align="center" gap={0}>
              <Typography variant="headline-sm" c={'carbon.7'} mb={16}>
                Unlock development efficiency with branches
              </Typography>
              <Typography variant="body-lg" c={'carbon.7'}>
                A branch is a separate instance that contains a diverged copy of data from the original cluster.
              </Typography>
              <Typography variant="body-lg" c={'carbon.7'}>
                It provides an isolated environment, allowing you to experiment freely without worrying about affecting
                the original cluster.
              </Typography>
              <Typography variant="body-lg" c={'carbon.7'}>
                The creation usually completes within a few minutes. Learn more about{' '}
                <a href="https://docs.pingcap.com/tidbcloud/branch-overview" target="_blank" rel="noreferrer">
                  Branching
                </a>
                .
              </Typography>
            </Stack>
          </Center>
        )}
      />
      {branchDetail && (
        <ServerlessConnectionV2
          cluster={props.cluster}
          branchScope="single"
          givenBranch={branchDetail}
          opened={connectShow}
          onClose={() => setConnectShow(false)}
        />
      )}
      <Modal title="Delete" centered trapFocus={false} opened={modalShow} onClose={() => setModalShow(false)}>
        <Form
          onSubmit={handleDelete}
          onCancel={() => setModalShow(false)}
          actionsProps={{
            confirmText: 'I understand, delete',
            confirmProps: {
              color: 'red',
              variant: 'light',
              'data-mp-event': 'Serverless branch delete'
            }
          }}
        >
          <Typography variant="body-lg">Branch deletion is unrecoverable, are you sure want to delete?</Typography>
        </Form>
      </Modal>
      {branchDetail && (
        <CreateBranchModal
          opened={createModalOpened}
          clusterId={props.cluster.id}
          parentId={branchDetail.id}
          createTime={branchDetail.create_time}
          branchList={branchList?.branches ?? []}
          onClose={createModalHandlers.close}
          onConfirm={getBranchList}
        />
      )}
      <ResetBranchModal
        opened={resetModalOpened}
        clusterId={props.cluster.id}
        branchId={branchDetail?.id ?? ''}
        branchName={branchDetail?.display_name ?? ''}
        parentBranchName={getParentBranchName(branchDetail)}
        onClose={resetModalHandlers.close}
        onConfirm={getBranchList}
      />
      {branchDetail && (
        <RenameModal
          opened={renameModalOpened}
          clusterId={props.cluster.id}
          branchId={branchDetail?.id ?? ''}
          branchName={branchDetail?.display_name ?? ''}
          onClose={renameModalHandlers.close}
          onConfirm={getBranchList}
        />
      )}
    </>
  )
})

function formatBytes(bytes: number, decimals = 2) {
  if (!+bytes) return '0 MiB'
  const k = 1024
  const dm = decimals < 0 ? 0 : decimals
  let unit = 'MiB'
  let result = bytes / Math.pow(k, 2)
  if (result > k) {
    unit = 'GiB'
    result = result / k
    if (result > k) {
      unit = 'TiB'
      result = result / k
    }
  }

  return `${result.toFixed(dm)} ${unit}`
}
