import { ActionIcon, Alert, Box, Button, Menu } from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import { IconDotsHorizontal, IconInfoCircle } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useMemo, useState } from 'react'
import { useQueryClient } from 'react-query'
import { Link } from 'react-router-dom'

import { HeroComponent } from 'dbaas/components/Measurement'
import TimeComponent from 'dbaas/components/TimeComponent'
import { AccessDeniedHoverHint, AccessGuard, useAccessCheck } from 'dbaas/contexts/access-control'
import { ProjectType } from 'dbaas/features/Project'
import { PageShell } from 'dbaas/layouts/v5/page'
import { CentralProject, getListLoginUserRolesQueryKey, useListProjects } from 'dbaas/services'
import { useCreateUserVisitHistory } from 'dbaas/services/account'
import useStores from 'dbaas/stores/useStores'

import { ProjectInvitationModal } from '../InviteUserModal'

import { ProjectEditModal } from './EditModal'
import { ProjectsPlaceholder } from './EmptyProjectsPlaceholder'

const TABLE_PAGE_SIZE = 10

export const Projects = observer(() => {
  const queryClient = useQueryClient()
  const {
    store: {
      tenantData: { id: orgId }
    },
    actions: { updateActiveProjectId, updateLastVisitLocation, fetchUserProfileV2 }
  } = useStores()

  const [currentPage, setCurrentPage] = useState(1)
  const { data, isLoading, refetch, isFetched } = useListProjects(orgId, {
    page: currentPage,
    per_page: TABLE_PAGE_SIZE,
    types: [ProjectType.DEDICATED]
  })

  const visitLocationMutation = useCreateUserVisitHistory()

  const [openProject, setOpenProject] = useState(false)
  const [openInvite, setOpenInvite] = useState(false)
  const [project, setProject] = useState<CentralProject>()

  const toggleProject = (data?: CentralProject) => () => {
    setProject(data)
    setOpenProject((preState) => !preState)
  }

  const onFinishProjectEdit = () => {
    queryClient.invalidateQueries(getListLoginUserRolesQueryKey())
    fetchUserProfileV2()
    return refetch()
  }

  const openInvitation = (data: CentralProject) => {
    setProject(data)
    setOpenInvite(true)
  }
  const closeInvitation = () => setOpenInvite(false)

  const actionsAccessible = useAccessCheck('OrgProjectsAction')
  const columns = useMemo<MRT_ColumnDef<CentralProject>[]>(
    () => [
      {
        header: 'Project ID',
        accessorKey: 'id',
        maxSize: 120,
        mantineTableHeadCellProps: {
          sx: {
            paddingLeft: '24px !important'
          }
        },
        mantineTableBodyCellProps: {
          sx: {
            paddingLeft: '24px !important'
          }
        }
      },
      {
        header: `Project Name`,
        id: 'name',
        accessorFn: ({ name, id }) => (
          <Box
            component={Link}
            to="/clusters"
            onClick={async () => {
              await visitLocationMutation.mutateAsync({
                data: {
                  org_id: orgId,
                  project_id: id
                }
              })
              updateLastVisitLocation({ projectId: id })
              updateActiveProjectId(id)
            }}
            data-mp-event="Project Link Clicked"
            sx={{ wordBreak: 'break-all' }}
          >
            {name}
          </Box>
        )
      },
      {
        header: 'Creation Time',
        id: 'created_at',
        accessorFn: ({ created_at }: CentralProject) => <TimeComponent time={created_at || ''} />
      },
      {
        header: 'Clusters',
        accessorKey: 'active_clusters_count',
        maxSize: 100,
        accessorFn(originalRow) {
          return originalRow.active_clusters_count < 0 ? '-' : originalRow.active_clusters_count
        },
        mantineTableHeadCellProps: {
          align: 'center'
        },
        mantineTableBodyCellProps: {
          align: 'center'
        }
      },
      {
        header: 'Users',
        accessorKey: 'users_count',
        maxSize: 100,
        mantineTableHeadCellProps: {
          align: 'center'
        },
        mantineTableBodyCellProps: {
          align: 'center'
        }
      },
      {
        header: 'CMEK',
        accessorFn: ({ aws_cmek_enabled }) => (aws_cmek_enabled ? 'Enabled' : 'Disabled')
      },
      {
        header: 'Actions',
        id: 'actions',
        Header: <Box px={8}>Actions</Box>,
        accessorFn: (row) => {
          return (
            <Menu withinPortal>
              <Menu.Target>
                <ActionIcon w={32} h={32} variant="subtle" data-mp-event="Project Management Actions Clicked">
                  <IconDotsHorizontal size={16} />
                </ActionIcon>
              </Menu.Target>
              <Menu.Dropdown>
                <Menu.Item
                  disabled={!actionsAccessible}
                  onClick={toggleProject(row)}
                  data-mp-event="Project Rename Button Clicked"
                >
                  Rename
                </Menu.Item>
                <Menu.Item
                  disabled={!actionsAccessible}
                  onClick={() => openInvitation(row)}
                  data-mp-event="Project Invite Button Clicked"
                >
                  Invite
                </Menu.Item>
              </Menu.Dropdown>
            </Menu>
          )
        }
      }
    ],
    [actionsAccessible, orgId, updateActiveProjectId, updateLastVisitLocation, visitLocationMutation]
  )

  const table = (
    <ProTable
      columns={columns}
      data={data?.items || []}
      loading={isLoading}
      emptyMessage="No Data"
      manualPagination={true}
      pagination={
        data?.total
          ? {
              total: Math.ceil((data?.total || 0) / TABLE_PAGE_SIZE) || 0,
              value: currentPage,
              onChange: (page) => {
                setCurrentPage(page)
              }
            }
          : void 0
      }
    />
  )

  return (
    <PageShell
      title="Dedicated Projects"
      headerProps={{
        sticky: true,
        rightSection: (
          <AccessDeniedHoverHint id="OrgProjectsAction">
            {({ accessible }) => (
              <Button
                size="sm"
                disabled={!accessible}
                onClick={toggleProject()}
                data-mp-event="Create New Project Button Clicked"
              >
                Create New Dedicated Project
              </Button>
            )}
          </AccessDeniedHoverHint>
        )
      }}
      bodyProps={{ mb: 88 }}
    >
      <Alert color="peacock" icon={<IconInfoCircle size={14} />} mb={16} data-testid="projects-legacy-alert">
        This is a legacy entry. Please use{' '}
        <Box
          component={Link}
          to="/tidbs?viewMode=project"
          sx={(theme) => ({
            display: 'inline',
            color: theme.colors.peacock[7],
            fontWeight: 600,
            textDecoration: 'none'
          })}
        >
          My TiDB Project View
        </Box>{' '}
        instead.
      </Alert>
      <AccessGuard
        id="OrgProjectsAction"
        fallback={isFetched && (data?.total || 0) === 0 ? <ProjectsPlaceholder /> : table}
      >
        {table}
        <ProjectEditModal
          project={project}
          opened={openProject}
          onClose={toggleProject()}
          onFinish={onFinishProjectEdit}
          createMode="dedicated-only"
        />
        <ProjectInvitationModal
          mode="free"
          projectId={project?.id!}
          opened={openInvite}
          onClose={closeInvitation}
          onFinish={refetch}
        />
        {isFetched && <HeroComponent />}
      </AccessGuard>
    </PageShell>
  )
})
