import { ActionIcon, Alert, Box, Button, Group, HoverCard, Menu, Select, TextInput, Typography } from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import { useDebouncedCallback } from '@tidbcloud/uikit/hooks'
import { IconDotsHorizontal, IconInfoCircle, IconSearchSm, IconXClose } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useState } from 'react'

import { HeroComponent } from 'dbaas/components/Measurement'
import TimeComponent from 'dbaas/components/TimeComponent'
import { useAccessCheck, AccessDeniedHoverHint } from 'dbaas/contexts/access-control'
import { PageAccessGuard } from 'dbaas/contexts/access-control'
import { PageShell } from 'dbaas/layouts/v5/page'
import { useListConsoleApiKeys } from 'dbaas/services/account'
import { useTidbServiceListTidbs } from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2'
import useStores from 'dbaas/stores/useStores'

import { RolesView } from '../users/shared/roles/RolesView'

import { DeletionConfirm } from './deletion-confirm/DeletionConfirm'
import { DetailView } from './Details'
import APIKeyEditor from './edit-key'
import { APIKeyItem } from './shared/helpers'
import { mpEvents } from './tracker'

const APIKeys = observer(() => {
  const {
    store: {
      tenantData: { id: orgId },
      lastVisitLocation,
      userProfile: { projects }
    }
  } = useStores()

  const [pagination, setPagination] = useState({
    pageIndex: 0,
    pageSize: 10
  })
  const [params, setParams] = useState<{
    search?: string
    projectId?: string
    clusterId?: string
  }>({})

  const [debouncedFilterParams, setDebouncedFilterParams] = useState<{
    search?: string
    projectId?: string
    clusterId?: string
  }>({})

  const handleFilter = useDebouncedCallback((newParams: typeof params) => {
    setDebouncedFilterParams(newParams)
    setPagination((prev) => ({ ...prev, pageIndex: 0 }))
  }, 500)

  const { data: tidbData } = useTidbServiceListTidbs({
    orgId,
    projectId: lastVisitLocation.projectId,
    pageSize: 100
  })

  const projectOptions = projects.map((project) => ({ label: project.name, value: project.id }))
  const instanceOptions = tidbData?.tidbs?.map((tidb) => ({ label: tidb.displayName || '', value: tidb.tidbId || '' }))
  const isProjectFilterDisabled = params.clusterId ? true : false
  const isInstanceFilterDisabled = params.projectId ? true : false

  const {
    data,
    isLoading,
    refetch: refetchOrgAPIKeys,
    isFetched
  } = useListConsoleApiKeys(
    orgId,
    {
      page: pagination.pageIndex + 1,
      per_page: pagination.pageSize,
      project_id: debouncedFilterParams.projectId ? debouncedFilterParams.projectId : undefined,
      cluster_id: debouncedFilterParams.clusterId ? debouncedFilterParams.clusterId : undefined,
      search: debouncedFilterParams.search ? debouncedFilterParams.search : undefined
    },
    {
      query: {
        refetchOnWindowFocus: false
      }
    }
  )

  const actionAccessible = useAccessCheck('OrgAPIKeysV2Action')

  const [creationOpened, setCreationOpened] = useState(false)
  const [editKey, setEditKey] = useState<APIKeyItem | null>(null)
  const [deleteKey, setDeleteKey] = useState<APIKeyItem | null>(null)
  const [viewKeyIndex, setViewKeyIndex] = useState<number | undefined>(undefined)

  const columns: MRT_ColumnDef<APIKeyItem>[] = [
    {
      header: 'Public Key',
      id: 'public_key',
      Cell: ({ row: { original: originalRow, index: rowIndex } }) => {
        return (
          <Box
            onClick={() => setViewKeyIndex(rowIndex)}
            sx={(theme) => ({
              cursor: 'pointer',
              color: theme.colors.peacock[7]
            })}
          >
            {originalRow.public_key}
          </Box>
        )
      },
      mantineTableHeadCellProps: {
        sx: {
          paddingLeft: '24px !important'
        }
      },
      mantineTableBodyCellProps: {
        sx: {
          paddingLeft: '24px !important'
        }
      }
    },

    {
      header: 'Role',
      id: 'role',
      minSize: 240,
      Cell: ({ row }) => (
        <RolesView user={row.original} projectOptions={projectOptions} instanceOptions={instanceOptions || []} />
      )
    },
    {
      header: 'Description',
      accessorKey: 'description',
      minSize: 160
    },
    {
      header: 'Created At',
      id: 'created_at',
      accessorFn: (row) => (row.created_at ? <TimeComponent time={row.created_at} /> : '-')
    },
    {
      header: 'Created By',
      id: 'created_by',
      accessorFn: (row) => (row.created_by ? row.created_by : '-')
    },
    {
      header: 'Updated At',
      id: 'updated_at',
      accessorFn: (row) => (row.updated_at ? <TimeComponent time={row.updated_at} /> : '-')
    },
    {
      header: '',
      id: 'actions',
      size: 40,
      accessorFn: (row) => (
        <Menu withinPortal>
          <Menu.Target>
            <ActionIcon w={32} h={32} variant="subtle" data-mp-event="APIKey Actions Clicked">
              <IconDotsHorizontal size={16} />
            </ActionIcon>
          </Menu.Target>
          <Menu.Dropdown w={160}>
            <Menu.Item
              onClick={() => {
                setEditKey(row)
              }}
              disabled={!actionAccessible}
            >
              Update Role
            </Menu.Item>
            <Menu.Item
              c="red.7"
              disabled={!actionAccessible}
              onClick={() => {
                setDeleteKey(row)
              }}
            >
              Delete
            </Menu.Item>
          </Menu.Dropdown>
        </Menu>
      )
    }
  ]

  return creationOpened || editKey ? (
    <APIKeyEditor
      onClose={() => {
        setCreationOpened(false)
        setEditKey(null)
      }}
      onFinish={refetchOrgAPIKeys}
      data={editKey || undefined}
    />
  ) : (
    <PageAccessGuard id="OrgAPIKeysV2Action">
      <PageShell
        title="API Keys"
        headerProps={{
          sticky: true,
          rightSection: (
            <AccessDeniedHoverHint id="OrgAPIKeysV2Action">
              {({ accessible }) => (
                <Button
                  size="sm"
                  disabled={!accessible}
                  onClick={() => setCreationOpened(true)}
                  data-mp-event={mpEvents.startCreation}
                  data-testid="create-api-key"
                >
                  Create API Key
                </Button>
              )}
            </AccessDeniedHoverHint>
          )
        }}
      >
        <Alert my={24}>
          Create an API key to grant programmatic access to TiDB Cloud with{' '}
          <Typography
            variant="action-md"
            fw={400}
            component="a"
            target="_blank"
            href="https://docs.pingcap.com/api/tidb-cloud-api-overview/"
            rel="noreferrer"
            data-mp-event={mpEvents.learnMore}
          >
            TiDB Cloud API
          </Typography>
          .
        </Alert>
        <Group>
          <TextInput
            w={240}
            placeholder="Search API Key"
            value={params.search || ''}
            leftSection={<IconSearchSm size={14} sx={{ cursor: 'pointer' }} />}
            rightSection={
              params.search && (
                <IconXClose
                  size={14}
                  sx={{ cursor: 'pointer' }}
                  onClick={() => {
                    const newParams = { ...params, search: '' }
                    setParams(newParams)
                    handleFilter(newParams)
                  }}
                />
              )
            }
            onChange={(event) => {
              const newParams = { ...params, search: event.currentTarget.value }
              setParams(newParams)
              handleFilter(newParams)
            }}
          />
          <HoverCard disabled={!isProjectFilterDisabled}>
            <HoverCard.Target>
              <Box>
                <Select
                  placeholder="Project"
                  disabled={isProjectFilterDisabled}
                  rightSection={isProjectFilterDisabled ? <IconInfoCircle size={16} /> : undefined}
                  searchable
                  data={projectOptions}
                  clearable
                  value={params.projectId}
                  onChange={(value) => {
                    const newParams = { ...params, projectId: value || '' }
                    setParams(newParams)
                    handleFilter(newParams)
                  }}
                ></Select>
              </Box>
            </HoverCard.Target>
            <HoverCard.Dropdown>Only one context (Project or Instance) can be filtered at a time.</HoverCard.Dropdown>
          </HoverCard>
          <HoverCard disabled={!isInstanceFilterDisabled}>
            <HoverCard.Target>
              <Box>
                <Select
                  data={instanceOptions}
                  placeholder="Instances"
                  searchable
                  clearable
                  value={params.clusterId}
                  disabled={isInstanceFilterDisabled}
                  rightSection={isInstanceFilterDisabled ? <IconInfoCircle size={16} /> : undefined}
                  onChange={(value) => {
                    const newParams = { ...params, clusterId: value || '' }
                    setParams(newParams)
                    handleFilter(newParams)
                  }}
                ></Select>
              </Box>
            </HoverCard.Target>
            <HoverCard.Dropdown>Only one context (Project or Instance) can be filtered at a time.</HoverCard.Dropdown>
          </HoverCard>
        </Group>
        <Box mt="xl" mb={8}>
          <ProTable
            columns={columns}
            data={data?.items || []}
            loading={isLoading}
            emptyMessage="No API Keys available"
            state={{
              pagination
            }}
            onPaginationChange={setPagination}
            manualPagination={true}
            rowCount={data?.total || 0}
            pagination={{
              showTotal: true,
              showRowsPerPage: true
            }}
          />
        </Box>
        {viewKeyIndex !== undefined && data?.items[viewKeyIndex] && (
          <DetailView
            opened={true}
            onClose={() => {
              setViewKeyIndex(undefined)
              refetchOrgAPIKeys()
            }}
            data={data?.items[viewKeyIndex]}
            onEdit={(key) => {
              setEditKey(key)
              setViewKeyIndex(undefined)
            }}
            disablePrev={viewKeyIndex === 0}
            disableNext={viewKeyIndex === data?.items.length - 1}
            onPrev={() => setViewKeyIndex(viewKeyIndex - 1)}
            onNext={() => setViewKeyIndex(viewKeyIndex + 1)}
          />
        )}
        {!!deleteKey && (
          <DeletionConfirm
            visible={true}
            onConfirm={refetchOrgAPIKeys}
            data={deleteKey!}
            onClose={() => {
              setDeleteKey(null)
            }}
          />
        )}
        {isFetched && <HeroComponent />}
      </PageShell>
    </PageAccessGuard>
  )
})

export { APIKeys }
export default APIKeys
