import { Box, Button, Group, Modal, Popover, Stack, Typography } from '@tidbcloud/uikit'
import { MRT_ColumnDef } from '@tidbcloud/uikit/biz'
import { useDisclosure } from '@tidbcloud/uikit/hooks'
import { observer } from 'mobx-react'
import { FC, forwardRef, useImperativeHandle, useMemo, useRef, useState } from 'react'
import { Link } from 'react-router-dom'

import { FilledTable } from 'dbaas/components/FilledTable'
import { useTimeFormatter } from 'dbaas/components/TimeComponent'
import { AccessGuard } from 'dbaas/contexts/access-control'
import { PageShell } from 'dbaas/layouts/v5/page'
import { UserDebugAuthorizationDetail } from 'dbaas/services'
import { useGetUserDebugAuthorizationList, useRevokeUserDebugAuthorization } from 'dbaas/services/api'
import useStores from 'dbaas/stores/useStores'

import { AuthorizationForm } from './AuthorizationForm'

const AuthorizationList: FC<React.PropsWithChildren<unknown>> = () => {
  const [opened, { open, close }] = useDisclosure()
  const tableRef = useRef<{
    fetchTableData: () => void
  }>(null)

  return (
    <PageShell title="Authorizations" headerProps={{ sticky: true }} bodyProps={{ px: 24, pt: 0 }}>
      <Stack>
        <Group justify="space-between" h={30}>
          <AccessGuard
            id="OrgAuthorizationAction"
            fallback={
              <Typography variant="body-md">No permission. Only the owner can create an authorization.</Typography>
            }
          >
            <Typography variant="body-md">
              You can authorize technical supports to access the necessary diagnostic data.
            </Typography>
          </AccessGuard>
          <AccessGuard id="OrgAuthorizationAction">
            <Button size="xs" onClick={open} data-mp-event="Create Authorization Button Clicked">
              Create Authorization
            </Button>
          </AccessGuard>
        </Group>

        <AuthorizationTable ref={tableRef} />
      </Stack>

      <Modal title="Create Authorization" size="lg" centered opened={opened} onClose={close}>
        <AuthorizationForm
          onSubmitSuccess={() => {
            close()
            tableRef.current?.fetchTableData()
          }}
          onCancel={close}
        />
      </Modal>
    </PageShell>
  )
}

enum AuthorizationStatus {
  NORMAL = 'normal',
  REVOKE = 'revoked'
}

const PER_PAGE_SIZE = 10

const AuthorizationTable = forwardRef<{ fetchTableData: () => void }>((_props, ref) => {
  const {
    store: { tenantData }
  } = useStores()
  const formatter = useTimeFormatter()
  const [page, setPage] = useState(1)
  const { data, isLoading, refetch } = useGetUserDebugAuthorizationList(tenantData.id, {
    page,
    per_page: PER_PAGE_SIZE
  })
  const total = Math.ceil((data?.total || 0) / PER_PAGE_SIZE)
  const columns: MRT_ColumnDef<UserDebugAuthorizationDetail>[] = useMemo(
    () => [
      {
        id: 'project',
        header: 'Project',
        accessorKey: 'project_name'
      },
      {
        id: 'cluster',
        header: 'Cluster',
        accessorKey: 'cluster_name'
      },
      {
        id: 'features',
        header: 'Authorized Features',
        accessorFn: () => <>TiDB Dashboard (Sensitive Data)</>
      },
      {
        id: 'time_limit',
        header: 'Time Limit',
        accessorFn: ({ expires_at, created_at }) =>
          !!expires_at &&
          !!created_at && (
            <>
              <p>From {formatter(created_at)}</p>
              <p>To {formatter(expires_at)}</p>
            </>
          )
      },
      {
        id: 'status',
        header: 'Status',
        accessorFn: ({ status, updated_at }) => (
          <>
            <p>{status ? status.replace(status[0], status[0].toUpperCase()) : 'Unknown'}</p>
            {status === AuthorizationStatus.REVOKE && !!updated_at && <p>At {formatter(updated_at)}</p>}
          </>
        )
      },
      {
        id: 'actions',
        header: 'Actions',
        accessorFn: (rowData) => {
          return (
            <Group gap="xs">
              <Button
                component={Link}
                variant="default"
                size="xs"
                data-mp-event="To Authorization Detail Button Clicked"
                data-mp-from="authorization"
                to={`/authorization/${rowData.id}?cluster_id=${rowData.cluster_id}`}
              >
                Details
              </Button>
              <AccessGuard id="OrgAuthorizationAction">
                {rowData.status === 'normal' && (
                  <RevokeAuthButton
                    clusterID={rowData.cluster_id as any}
                    authID={rowData.id as any}
                    onSuccess={() => refetch()}
                  />
                )}
              </AccessGuard>
            </Group>
          )
        }
      }
    ],
    [refetch, formatter]
  )

  useImperativeHandle(ref, () => ({
    fetchTableData: refetch
  }))

  return (
    <Box>
      <FilledTable
        columns={columns}
        data={data?.items || []}
        loading={isLoading}
        manualPagination={true}
        pagination={
          total > 1
            ? {
                value: page,
                total,
                onChange: setPage
              }
            : undefined
        }
        emptyMessage="No Authorization."
      />
    </Box>
  )
})

const RevokeAuthButton: FC<
  React.PropsWithChildren<{
    clusterID: string
    authID: string
    onSuccess?: () => void
  }>
> = ({ clusterID, authID, onSuccess }) => {
  const {
    store: { tenantData }
  } = useStores()
  const { mutateAsync: revokeAuth, isLoading } = useRevokeUserDebugAuthorization()
  return (
    <Popover position="bottom-end" withArrow>
      <Popover.Target>
        <Button size="xs" color="red" variant="light" data-mp-event="Open Revoke Button Clicked">
          Revoke
        </Button>
      </Popover.Target>
      <Popover.Dropdown>
        <Stack>
          <Typography variant="title-md">Are you absolutely sure?</Typography>

          <Group justify="flex-end">
            <Button
              size="xs"
              variant="default"
              loading={isLoading}
              onClick={async () => {
                await revokeAuth({
                  organization: tenantData.id,
                  cluster: clusterID,
                  data: { id: authID } as any
                })
                onSuccess?.()
              }}
              data-mp-event="Confirm Revoke Button Clicked"
            >
              Yes
            </Button>
          </Group>
        </Stack>
      </Popover.Dropdown>
    </Popover>
  )
}

export default observer(AuthorizationList)
