import useUrlState from '@ahooksjs/use-url-state'
import { ActionIcon, Box, Button, Center, Flex, Group, Menu, Stack, TextInput, Typography } from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProMultiSelect, ProTable } from '@tidbcloud/uikit/biz'
import { useDebouncedValue, useMediaQuery } from '@tidbcloud/uikit/hooks'
import { IconDotsHorizontal, IconRefreshCw02, IconSearchSm, IconXCircle, IconXClose } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { stringify } from 'qs'
import { useRef, useState } from 'react'
import { useHistory } from 'react-router-dom'

import TimeComponent from 'dbaas/components/TimeComponent'
import { CloudProviderLabelConst } from 'dbaas/features/Project/profile'
import { TableFallback } from 'dbaas/screens/ClusterV2/components/PausedStatus'
import { useRequestSupport } from 'dbaas/screens/HelpCenter/RequestSupport/helper'
import { useGetOrgInfo, useListWarehouses } from 'dbaas/services/warehouse'
import useStores from 'dbaas/stores/useStores'

import { WarehouseDeletionModal } from './delete'
import { WAREHOUSE_URL } from './helper'
import { WarehouseRenameModal } from './rename'
import { StateTag } from './StateTag'

const DEFAULT_PAGE_SIZE = 10

interface UrlStateParams {
  search?: string
  status?: string | string[]
  pageIndex?: string
  pageSize?: string
}

export const MyLakeListView = observer(() => {
  const {
    store: {
      lastVisitLocation: { orgId }
    }
  } = useStores()
  const history = useHistory()

  const [refetching, setRefetching] = useState(false)
  const { open: openSupport } = useRequestSupport()
  const [isRenameModalOpen, setIsRenameModalOpen] = useState(false)
  const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false)

  const [urlState, setUrlState] = useUrlState<UrlStateParams>(
    {
      search: undefined,
      status: undefined,
      pageIndex: '0',
      pageSize: `${DEFAULT_PAGE_SIZE}`
    },
    { navigateMode: 'replace' }
  )

  const normalizeArrayParam = <T extends string>(value: string | string[] | undefined): T[] => {
    if (!value) return []
    if (Array.isArray(value)) return value as T[]
    return [value as T]
  }

  const params = {
    search: urlState.search || '',
    status: normalizeArrayParam<string>(urlState.status)
  }

  const pagination = {
    pageIndex: Number(urlState.pageIndex || 0),
    pageSize: Number(urlState.pageSize || DEFAULT_PAGE_SIZE)
  }

  const [debouncedParams] = useDebouncedValue(params, 300)
  const firstLoadedRef = useRef(false)

  const hasSearch = debouncedParams.search || debouncedParams.status.length > 0
  const matchedXl = useMediaQuery('(max-width: 1500px)')
  const [operationWarehouse, setOperationWarehouse] = useState(undefined)

  const { data: orgInfo } = useGetOrgInfo(orgId)

  const columns: MRT_ColumnDef<any>[] = [
    {
      header: 'Name',
      Header: () => <Typography pl={16}>Name</Typography>,
      Cell: ({ row: rowData }) => {
        const row = rowData.original
        return (
          <Typography
            tabIndex={0}
            variant="label-lg"
            c="peacock.7"
            ml={16}
            sx={{
              cursor: 'pointer',
              maxWidth: matchedXl ? 300 : 500,
              overflow: 'hidden',
              wordBreak: 'keep-all',
              whiteSpace: 'nowrap',
              textOverflow: 'ellipsis'
            }}
            onClick={() => {
              window.open(`${WAREHOUSE_URL}/${orgId}/warehouse/${row.id}`, '_blank')
            }}
          >
            {row?.id || '-'}
          </Typography>
        )
      }
    },
    {
      header: 'Status',
      accessorFn: (row) => (
        <Group>
          <StateTag state={row.state} />
        </Group>
      ),
      maxSize: 100
    },
    {
      header: 'Size',
      accessorFn: (row) => row.size || '-',
      size: 110
    },
    {
      header: 'Cloud',
      accessorFn: () => CloudProviderLabelConst[orgInfo?.data?.storageInfo?.provider ?? ''] ?? '-',
      size: 100
    },
    {
      header: 'Region',
      accessorFn: () => orgInfo?.data?.storageInfo?.regionTitle || '-'
    },
    {
      header: 'Created At',
      accessorFn: (row) => <TimeComponent time={row.createdAt || ''} format="YYYY-MM-DD HH:mm:ss" />
    },
    {
      id: 'Action',
      header: '',
      accessorFn: (row) => (
        <Menu withArrow withinPortal position="bottom-end" data-testid="serverless-cluster-operations">
          <Menu.Target>
            <ActionIcon
              variant="subtle"
              w={32}
              h={32}
              aria-label="Warehouse operation dropdown menu"
              data-mp-event="Warehouse Actions Button Clicked"
            >
              <IconDotsHorizontal size={16} />
            </ActionIcon>
          </Menu.Target>
          <Menu.Dropdown>
            <Menu.Item onClick={() => history.push(`/lakes/${row.id}/modifying`)}>Settings</Menu.Item>
            <Menu.Item
              disabled={row.state !== 'Suspended'}
              onClick={() => {
                setOperationWarehouse(row)
                setIsRenameModalOpen(true)
              }}
            >
              Rename
            </Menu.Item>
            <Menu.Item
              onClick={() => {
                setOperationWarehouse(row)
                setIsDeleteModalOpen(true)
              }}
            >
              Delete
            </Menu.Item>
            <Menu.Item onClick={() => openSupport()}>Get Support</Menu.Item>
          </Menu.Dropdown>
        </Menu>
      ),
      size: 80
    }
  ]

  const handleClearFilters = () => {
    setUrlState({ search: undefined, status: undefined, pageIndex: '0' })
  }

  const statusOptions = [
    { label: 'Started', value: 'Started' },
    { label: 'Running', value: 'Running' },
    { label: 'Suspended', value: 'Suspended' },
    { label: 'Failed', value: 'Failed' }
  ]

  const { data, isLoading, isError, refetch } = useListWarehouses(
    orgId,
    {
      warehouseName: debouncedParams.search,
      state: debouncedParams.status
    },
    {
      query: {
        retry: 3,
        retryDelay: 5 * 1000,
        refetchOnWindowFocus: (query) => !query.state.error,
        onSuccess: () => {
          setRefetching(false)
          if (!firstLoadedRef.current) {
            firstLoadedRef.current = true
          }
        },
        onError: () => {
          setRefetching(false)
        }
      },
      request: {
        paramsSerializer(params) {
          return stringify(params, { arrayFormat: 'repeat' })
        }
      }
    }
  )

  const warehouses = data?.data ?? []
  const paginatedWarehouses = warehouses.slice(
    pagination.pageIndex * pagination.pageSize,
    pagination.pageIndex * pagination.pageSize + pagination.pageSize
  )

  return (
    <Box data-testid="my-lake-list-view">
      {isError && !firstLoadedRef.current ? (
        <Stack align="center" mt={48} data-testid="my-tidb-error-state">
          <IconXCircle size={48} color="red" />
          <Typography variant="headline-lg" c="carbon.7">
            Fetch failed.
          </Typography>
          <Typography variant="body-lg" c="carbon.7">
            Please retry in a short while or contact <a onClick={() => openSupport()}>technical support</a>.
          </Typography>
          <Button onClick={() => refetch()}>Retry</Button>
        </Stack>
      ) : (
        <>
          <Flex
            justify="space-between"
            align="center"
            sx={{
              position: 'sticky',
              top: 'var(--app-page-shell-header-height)',
              zIndex: 8,
              backgroundColor: 'var(--mantine-color-carbon-0)',
              paddingBottom: 0
            }}
          >
            <Flex gap={8} align="center">
              <TextInput
                placeholder="Search Name"
                w={240}
                value={params.search}
                data-testid="my-lake-search-input"
                rightSection={
                  params.search ? (
                    <IconXClose
                      size={14}
                      sx={{ cursor: 'pointer' }}
                      onClick={() => {
                        setUrlState({ search: undefined, pageIndex: '0' })
                      }}
                    />
                  ) : (
                    <IconSearchSm size={14} sx={{ cursor: 'pointer' }} />
                  )
                }
                onChange={(event) => {
                  setUrlState({ search: event.currentTarget.value || undefined, pageIndex: '0' })
                }}
              />

              <ProMultiSelect
                data={statusOptions}
                placeholder="Status"
                clearable
                width={190}
                value={params.status}
                searchable
                onChange={(value) => {
                  setUrlState({ status: value?.length ? value : undefined, pageIndex: '0' })
                }}
                data-testid="my-lake-status-filter"
              />

              <Button onClick={handleClearFilters} variant="subtle" data-testid="my-lake-clear-filter-button">
                Clear Filter
              </Button>
            </Flex>

            <ActionIcon
              onClick={() => {
                setRefetching(true)
                refetch().finally(() => {
                  setRefetching(false)
                })
              }}
              variant="subtle"
              data-mp-event="My Lake Refresh Button Clicked"
              data-testid="my-lake-refresh-button"
            >
              <IconRefreshCw02 size={16} />
            </ActionIcon>
          </Flex>

          <Box data-testid="my-lake-list-table-container">
            <ProTable
              columns={columns}
              data={paginatedWarehouses}
              loading={isLoading || refetching}
              mantinePaperProps={{ mt: 16, mb: 16 }}
              renderEmptyRowsFallback={() => {
                if (hasSearch) {
                  return <Center h={40}>{isError ? 'Error occurred, please try again later.' : 'No data.'}</Center>
                }
                return (
                  <TableFallback height="calc(100vh - 260px)">
                    <TableFallback.Empty title="Get started by creating a warehouse" desc="" />
                  </TableFallback>
                )
              }}
              state={{ pagination }}
              onPaginationChange={(updater) => {
                const newPagination = typeof updater === 'function' ? updater(pagination) : updater
                setUrlState({ pageIndex: String(newPagination.pageIndex), pageSize: String(newPagination.pageSize) })
              }}
              rowCount={warehouses.length}
              pagination={{ showRowsPerPage: true, showTotal: true }}
              data-testid="my-lake-list-table"
              enablePagination
              manualPagination
            />
          </Box>
        </>
      )}
      {operationWarehouse && (
        <WarehouseRenameModal
          opened={isRenameModalOpen}
          warehouse={operationWarehouse!}
          onClose={() => {
            setOperationWarehouse(undefined)
            setIsRenameModalOpen(false)
            refetch()
          }}
        />
      )}
      {operationWarehouse && (
        <WarehouseDeletionModal
          opened={isDeleteModalOpen}
          warehouse={operationWarehouse!}
          onClose={() => {
            setOperationWarehouse(undefined)
            setIsDeleteModalOpen(false)
            refetch()
          }}
        />
      )}
    </Box>
  )
})

export default MyLakeListView
