import { Tabs, Tooltip } from 'antd'
import React, { useEffect, useMemo, useState } from 'react'
import { useHistory, useLocation } from 'react-router-dom'

import BackupPanel from './panels/Backup'
import ChangefeedSubTab from './panels/Changefeed'
import DMPanel from './panels/DM'
import ExportPanel from './panels/Export'
import ImportPanel from './panels/Import'
import RestorePanel from './panels/Restore'
import { strings } from './strings'
import { useToolsPage } from './ToolsPageContext'
import {
  isDedicatedDeployType,
  isNextGenDeployType,
  supportsBackupRestoreDeployType,
  supportsExportDeployType
} from './types'

const VALID = new Set([
  'changefeed',
  'dm',
  'import',
  'backup',
  'export',
  'restore'
])
const DEFAULT = 'changefeed'

function readHash(hash: string): string {
  const h = (hash || '').replace(/^#/, '').toLowerCase()
  return VALID.has(h) ? h : DEFAULT
}

function useActiveSubTab(): [string, (key: string) => void] {
  const history = useHistory()
  const location = useLocation()
  const [active, setActive] = useState<string>(readHash(location.hash))

  useEffect(() => {
    setActive(readHash(location.hash))
  }, [location.hash])

  const set = (key: string) => {
    setActive(key)
    // replace — tab changes shouldn't spam the history stack
    history.replace({ ...location, hash: '#' + key })
  }
  return [active, set]
}

export default function ToolsTabs() {
  const { cluster, deployType } = useToolsPage()
  const isDedicated = isDedicatedDeployType(deployType)
  const isNextGen = isNextGenDeployType(deployType)
  const supportsBackupRestore = supportsBackupRestoreDeployType(
    deployType,
    cluster.service_plan
  )
  const supportsExport = supportsExportDeployType(
    deployType,
    cluster.service_plan
  )

  const tabConfig = useMemo(
    () => [
      {
        key: 'changefeed',
        label: strings.tabs.changefeed,
        enabled: isDedicated || isNextGen,
        tooltip: strings.tooltips.changefeedOnlySome
      },
      {
        key: 'dm',
        label: strings.tabs.dm,
        enabled: isDedicated || isNextGen,
        tooltip: strings.tooltips.dmOnlyDedicatedNextGen
      },
      {
        key: 'import',
        label: strings.tabs.import,
        enabled: isDedicated || isNextGen,
        tooltip: strings.tooltips.importOnlyDedicatedNextGen
      },
      {
        key: 'backup',
        label: strings.tabs.backup,
        enabled: supportsBackupRestore,
        tooltip: strings.tooltips.backupDedicatedNextGen
      },
      {
        key: 'export',
        label: strings.tabs.export,
        enabled: supportsExport,
        tooltip: strings.tooltips.exportNextGen
      },
      {
        key: 'restore',
        label: strings.tabs.restore,
        enabled: supportsBackupRestore,
        tooltip: strings.tooltips.restoreDedicatedNextGen
      }
    ],
    [isDedicated, isNextGen, supportsBackupRestore, supportsExport]
  )

  const [active, setActive] = useActiveSubTab()

  // If the user deep-links to a disabled tab, fall back to the first enabled tab.
  useEffect(() => {
    const current = tabConfig.find((t) => t.key === active)
    if (current && !current.enabled) {
      const firstEnabled = tabConfig.find((t) => t.enabled)
      if (firstEnabled) setActive(firstEnabled.key)
    }
  }, [active, tabConfig]) // eslint-disable-line react-hooks/exhaustive-deps

  return (
    <Tabs activeKey={active} onChange={setActive}>
      {tabConfig.map((t) => (
        <Tabs.TabPane
          key={t.key}
          disabled={!t.enabled}
          tab={
            t.enabled ? t.label : <Tooltip title={t.tooltip}>{t.label}</Tooltip>
          }
        >
          {active === t.key && t.enabled ? (
            t.key === 'changefeed' ? (
              <ChangefeedSubTab />
            ) : t.key === 'dm' ? (
              <DMPanel />
            ) : t.key === 'import' ? (
              <ImportPanel />
            ) : t.key === 'backup' ? (
              <BackupPanel />
            ) : t.key === 'export' ? (
              <ExportPanel />
            ) : (
              <RestorePanel />
            )
          ) : null}
        </Tabs.TabPane>
      ))}
    </Tabs>
  )
}
