import { getValueFormat } from '@baurine/grafana-value-formats'
import { Button, HoverCard, Menu, Text } from '@tidbcloud/uikit'
import { IconChevronSelectorVertical, IconRefreshCw01 } from '@tidbcloud/uikit/icons'
import { useRafInterval } from 'ahooks'
import { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react'

import RefreshProgress from './RefreshProgress'

interface AutoRefreshButtonProps {
  autoRefreshValue?: number
  autoRefreshOptions?: number[]
  onAutoRefreshChange?: (v: number) => void
  onRefresh?: () => void
  loading?: boolean
  disabled?: boolean
  disableAutoRefreshSelect?: boolean
  leftSection?: React.ReactNode
  tooltip?: string
}

export interface AutoRefreshButtonRef {
  refresh: () => void
  resetCountdown: () => void
}

const AUTO_REFRESH_SECONDS_OPTIONS = [30, 60, 5 * 60, 15 * 60, 30 * 60, 60 * 60, 2 * 60 * 60]

export const DEFAULT_AUTO_REFRESH_SECONDS = 60

const AutoRefreshButton = forwardRef<AutoRefreshButtonRef, AutoRefreshButtonProps>(
  (
    {
      autoRefreshValue = DEFAULT_AUTO_REFRESH_SECONDS,
      autoRefreshOptions = AUTO_REFRESH_SECONDS_OPTIONS,
      onAutoRefreshChange,
      onRefresh,
      loading,
      disabled,
      disableAutoRefreshSelect,
      leftSection,
      tooltip
    },
    ref
  ) => {
    const selectedOption = useMemo(
      () => autoRefreshOptions.find((op) => op === autoRefreshValue),
      [autoRefreshValue, autoRefreshOptions]
    )
    const [remaining, setRemaining] = useState<number>(autoRefreshValue)
    const [menuOpened, setMenuOpened] = useState(false)

    const resetCountdown = () => {
      setRemaining(autoRefreshValue)
    }

    // useRafInterval stops running when browser render doesn't work, for example, browser tab is not active, browser window is minimized.
    useRafInterval(() => {
      if (disabled || autoRefreshValue === 0) {
        return
      }
      setRemaining((r) => Math.max(r - 1, 0))
    }, 1000)

    const handleRefresh = async () => {
      if (disabled) {
        return
      }
      resetCountdown()
      onRefresh?.()
    }

    useImperativeHandle(ref, () => ({
      refresh: handleRefresh,
      resetCountdown
    }))

    const handleAutoRefreshChange = (v: number) => {
      onAutoRefreshChange?.(v)
    }

    useEffect(() => {
      setRemaining(selectedOption ?? 0)
    }, [selectedOption])

    useEffect(() => {
      if (remaining !== 0 || disabled || autoRefreshValue === 0) {
        return
      }

      setRemaining(autoRefreshValue)
      onRefresh?.()
    }, [autoRefreshValue, disabled, onRefresh, remaining])

    const refreshButton = (
      <Button
        variant="default"
        px={12}
        styles={(theme) => ({
          root: {
            backgroundColor: theme.colors.carbon[0],
            borderColor: theme.colors.carbon[4],
            '&:hover': {
              backgroundColor: theme.colors.carbon[0],
              borderColor: theme.colors.carbon[5]
            }
          },
          label: { fontWeight: 400 }
        })}
        onClick={handleRefresh}
        leftSection={
          leftSection !== undefined ? (
            leftSection
          ) : autoRefreshValue && !disabled ? (
            <RefreshProgress value={Math.floor(((autoRefreshValue - remaining) / autoRefreshValue) * 100)} />
          ) : (
            <IconRefreshCw01 size={16} />
          )
        }
        loading={loading}
        disabled={disabled}
        data-mp-event="mp-refresh-1691461017436"
        loaderProps={{ size: 16 }}
      >
        Refresh
      </Button>
    )

    return (
      <Button.Group>
        <HoverCard disabled={!tooltip} shadow="md" withArrow withinPortal position="top">
          <HoverCard.Target>{refreshButton}</HoverCard.Target>
          <HoverCard.Dropdown maw={480}>
            <Text>{tooltip}</Text>
          </HoverCard.Dropdown>
        </HoverCard>

        <Menu position="bottom-end" offset={4} width={110} opened={menuOpened} onChange={setMenuOpened}>
          <Menu.Target>
            <Button
              disabled={disabled || loading || disableAutoRefreshSelect}
              variant="default"
              styles={(theme) => ({
                root: {
                  backgroundColor: theme.colors.carbon[0],
                  borderColor: menuOpened ? theme.colors.carbon[9] : theme.colors.carbon[4],
                  '&:hover': {
                    backgroundColor: theme.colors.carbon[0],
                    borderColor: menuOpened ? theme.colors.carbon[9] : theme.colors.carbon[5]
                  },
                  '&:active': { transform: 'none' }
                },
                label: { fontWeight: 400 }
              })}
              px={12}
              data-mp-event="mp--1691461017439"
            >
              {!!autoRefreshValue && <Text mr={8}>{getValueFormat('s')(autoRefreshValue, 0)}</Text>}

              <IconChevronSelectorVertical size={16} />
            </Button>
          </Menu.Target>

          <Menu.Dropdown>
            <Menu.Label>Auto Refresh</Menu.Label>
            <Menu.Item
              sx={(theme) => ({
                background: !selectedOption ? theme.colors.carbon[3] : undefined
              })}
              onClick={() => handleAutoRefreshChange(0)}
            >
              Off
            </Menu.Item>

            <Menu.Divider />

            <>
              {autoRefreshOptions.map((seconds) => (
                <Menu.Item
                  key={seconds}
                  sx={(theme) => ({
                    background: seconds === selectedOption ? theme.colors.carbon[3] : undefined
                  })}
                  onClick={() => handleAutoRefreshChange(seconds)}
                >
                  {getValueFormat('s')(seconds, 0)}
                </Menu.Item>
              ))}
            </>
          </Menu.Dropdown>
        </Menu>
      </Button.Group>
    )
  }
)

export default AutoRefreshButton
