import { Alert, Center, Loader, Skeleton } from '@tidbcloud/uikit'
import { useInViewport } from '@tidbcloud/uikit/hooks'
import { IconAlertCircle } from '@tidbcloud/uikit/icons'
import { useEffect, useMemo, useState } from 'react'

import { HeroComponent, isHeroQueryReady } from 'dbaas/components/Measurement'
import { useOrgProjectClusterIds } from 'dbaas/features/Common'
import { useListRecycleBinClustersV2 } from 'dbaas/services/dataflow'
import { DataflowRecycleBinCluster } from 'dbaas/services/dataflow/interface'

import { RecycleBinDedicatedCard } from './RecycleBinCard'
import { RecycleBinEmptyState } from './RecycleBinEmptyState'
import { DEFAULT_PAGE_SIZE, getRecycleBinEmptyStateMessage, RecycleBinFilterProps } from './recycleBinUtils'

export function DedicatedRecycleBinList({
  regionIds,
  projectIds,
  startTime,
  endTime,
  hasActiveFilters
}: RecycleBinFilterProps) {
  const { orgId } = useOrgProjectClusterIds()
  const { ref, inViewport } = useInViewport()

  // Pagination (page-based)
  const [page, setPage] = useState(1)
  const [displayedClusters, setDisplayedClusters] = useState<DataflowRecycleBinCluster[]>([])
  const [hasMore, setHasMore] = useState(true)

  // Synchronous reset when filters change
  const filterKey = `${JSON.stringify(regionIds)}-${JSON.stringify(projectIds)}-${startTime}-${endTime}`
  const [prevFilterKey, setPrevFilterKey] = useState(filterKey)
  if (filterKey !== prevFilterKey) {
    setPrevFilterKey(filterKey)
    setPage(1)
    setDisplayedClusters([])
    setHasMore(true)
  }

  // Dedicated API expects region codes without provider prefix (e.g. "us-west-2" instead of "aws-us-west-2")
  const apiRegionIds = useMemo(() => regionIds.map((id) => id.replace(/^[^-]+-/, '')), [regionIds])

  const { isFetching, isFetched, isError } = useListRecycleBinClustersV2(
    orgId,
    {
      per_page: DEFAULT_PAGE_SIZE,
      page,
      regions: apiRegionIds.length > 0 ? apiRegionIds : undefined,
      project_ids: projectIds.length > 0 ? projectIds : undefined,
      start_time: startTime,
      end_time: endTime
    },
    {
      query: {
        refetchOnWindowFocus: false,
        enabled: !!orgId && hasMore,
        onSuccess(data) {
          setDisplayedClusters((prev) => {
            const existingIds = new Set(prev.map((c) => c.id))
            const newItems = (data.items ?? []).filter((item) => !existingIds.has(item.id))
            return prev.concat(newItems)
          })
          const totalLoaded = (page - 1) * DEFAULT_PAGE_SIZE + (data.items?.length ?? 0)
          setHasMore(totalLoaded < (data.total ?? 0))
        }
      }
    }
  )

  // Infinite scroll
  useEffect(() => {
    if (inViewport && hasMore && !isFetching) {
      setPage((prev) => prev + 1)
    }
  }, [inViewport, hasMore, isFetching])

  const isInitialLoading = displayedClusters.length === 0

  return (
    <>
      <HeroComponent ready={isHeroQueryReady({ isFetched, isError })} />
      {displayedClusters.length > 0 && (
        <>
          <Alert color="peacock" icon={<IconAlertCircle />}>
            After you delete an instance, auto-backups whose lifetimes do not exceed the retention period, as set in the
            Backup Settings, will be retained.
          </Alert>
          {displayedClusters.map((cluster) => (
            <RecycleBinDedicatedCard key={cluster.id} cluster={cluster} />
          ))}
        </>
      )}

      {isInitialLoading && isFetching && (
        <>
          <Skeleton height={50} />
          <Skeleton height={50} />
          <Skeleton height={50} />
          <Skeleton height={50} />
          <Skeleton height={50} />
        </>
      )}

      {!isFetching && displayedClusters.length === 0 && (
        <RecycleBinEmptyState
          message={hasActiveFilters ? 'No results match your filters.' : getRecycleBinEmptyStateMessage('Dedicated')}
        />
      )}

      {!isInitialLoading && !isFetching && hasMore && <div ref={ref} />}
      {!isInitialLoading && isFetching && (
        <Center>
          <Loader size="md" />
        </Center>
      )}
    </>
  )
}
