import {
  Button,
  Card,
  Code,
  Group,
  Select,
  SimpleGrid,
  Stack,
  Typography
} from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import { FormInstance, Modal } from 'antd'
import { useCallback, useEffect, useMemo, useState } from 'react'

import {
  cloudConfigControllerUpdateComponentImage,
  useCloudConfigControllerListAvailableComponentVersions,
  useCloudConfigControllerListComponents
} from 'apiClient/services/devops'
import { CloudConfigControllerListAvailableComponentVersionsClusterType } from 'apiClient/services/devops/interface'
import ModalForm from 'components/ModalForm'

import { ClusterComponentVersions } from './ClusterComponentVersions'
import UpdateNgComponentImageForm, {
  UpdateNgComponentImage
} from './Forms/UpdateNgComponentImage'

const COMPONENT_VIEW_OPTIONS = [
  {
    label: 'Available Component Versions',
    value: 'available_versions'
  },
  { label: 'Cluster Component Versions', value: 'cluster_versions' }
] as const

const AVAILABLE_CLUSTER_TYPE_OPTIONS = [
  { label: 'Dedicated', value: 'DEDICATED_TIDB' },
  { label: 'TiCDC', value: 'TICDC' },
  { label: 'Resource Pool', value: 'SHARED_POOL' },
  { label: 'Premium & BYOC', value: 'LOGICAL_CLUSTER' },
  { label: 'TiCDC NG', value: 'TICDC_NG' }
]

const AVAILABLE_PAGE_SIZE = 20

type TablePaginationState = {
  pageIndex: number
  pageSize: number
}

type TablePaginationUpdater =
  | TablePaginationState
  | ((prev: TablePaginationState) => TablePaginationState)

const getFixedPagination = (
  updaterOrValue: TablePaginationUpdater,
  currentPagination: TablePaginationState
) => {
  const nextPagination =
    typeof updaterOrValue === 'function'
      ? updaterOrValue(currentPagination)
      : updaterOrValue

  return {
    pageIndex: nextPagination.pageIndex,
    pageSize: AVAILABLE_PAGE_SIZE
  }
}

const getCodeValue = (value?: string) => {
  if (!value) {
    return (
      <Typography variant="body-sm" c="carbon.5">
        -
      </Typography>
    )
  }

  return (
    <Code
      title={value}
      style={{
        display: 'inline-block',
        maxWidth: 360,
        overflow: 'hidden',
        textOverflow: 'ellipsis',
        verticalAlign: 'middle',
        whiteSpace: 'nowrap'
      }}
    >
      {value}
    </Code>
  )
}

function CCComponent() {
  const [viewMode, setViewMode] = useState<
    'available_versions' | 'cluster_versions'
  >('available_versions')
  const [selectedComponent, setSelectedComponent] = useState<string>('')
  const [selectedClusterType, setSelectedClusterType] =
    useState<CloudConfigControllerListAvailableComponentVersionsClusterType>(
      'SHARED_POOL'
    )
  const [availablePagination, setAvailablePagination] = useState({
    pageIndex: 0,
    pageSize: AVAILABLE_PAGE_SIZE
  })

  const [modalEdit, setModalEdit] = useState(false)
  const [selectedVersion, setSelectedVersion] = useState<string>('')
  const { data: componentsResponse, isLoading: isLoadingComponents } =
    useCloudConfigControllerListComponents({
      cluster_type: selectedClusterType
    })

  const components = useMemo(
    () => componentsResponse?.data?.components || [],
    [componentsResponse]
  )

  // Only fetch component versions when a component is actually selected AND it's valid for current cluster type
  const { data: response, isLoading } =
    useCloudConfigControllerListAvailableComponentVersions(
      selectedComponent,
      {
        cluster_type: selectedClusterType
      },
      {
        query: {
          enabled: !!selectedComponent && components.includes(selectedComponent)
        }
      }
    )

  const availableVersions = useMemo(
    () => response?.data?.detail || [],
    [response?.data?.detail]
  )

  useEffect(() => {
    setSelectedComponent('')
  }, [selectedClusterType])

  useEffect(() => {
    if (components.length > 0) {
      setSelectedComponent((current) => current || components[0])
    }
  }, [components])

  useEffect(() => {
    setAvailablePagination((current) => ({ ...current, pageIndex: 0 }))
  }, [selectedClusterType, selectedComponent])

  interface ComponentVersion {
    version?: string
    base_image?: string
    image_tag?: string
  }

  const columns = useMemo<MRT_ColumnDef<ComponentVersion>[]>(() => {
    const nextColumns: MRT_ColumnDef<ComponentVersion>[] = [
      {
        header: 'Version',
        accessorKey: 'version',
        size: 160,
        Cell: ({ row }) => getCodeValue(row.original.version)
      },
      {
        header: 'Base Image',
        accessorKey: 'base_image',
        size: 360,
        Cell: ({ row }) => getCodeValue(row.original.base_image)
      },
      {
        header: 'Image Tag',
        accessorKey: 'image_tag',
        size: 260,
        Cell: ({ row }) => getCodeValue(row.original.image_tag)
      }
    ]

    if (
      ['DEDICATED_TIDB', 'SHARED_POOL', 'LOGICAL_CLUSTER', 'TICDC_NG'].includes(
        selectedClusterType as string
      ) ||
      selectedComponent === 'ticdc'
    ) {
      nextColumns.push({
        header: 'Action',
        id: 'action',
        size: 120,
        Cell: ({ row }) => (
          <Button
            size="sm"
            onClick={() => {
              setSelectedVersion(row.original.version || '')
              setModalEdit(true)
            }}
          >
            Action
          </Button>
        )
      })
    }

    return nextColumns
  }, [selectedClusterType, selectedComponent])

  const renderImageParamFields = useCallback(
    (form: FormInstance) => {
      form.setFieldsValue({ cluster_type: selectedClusterType })
      form.setFieldsValue({ component_name: selectedComponent })
      form.setFieldsValue({ version: selectedVersion })
      form.setFieldsValue({
        image_base: availableVersions.find(
          (item) => item.version === selectedVersion
        )?.base_image
      })
      form.setFieldsValue({
        image_tag: availableVersions.find(
          (item) => item.version === selectedVersion
        )?.image_tag
      })
      return <UpdateNgComponentImageForm form={form} />
    },
    [availableVersions, selectedClusterType, selectedComponent, selectedVersion]
  )

  const handleImage = useCallback(async (payload: UpdateNgComponentImage) => {
    try {
      const id = (
        await cloudConfigControllerUpdateComponentImage(
          payload.component_name,
          {
            base_image: payload.image_base,
            cluster_type:
              payload.cluster_type as CloudConfigControllerListAvailableComponentVersionsClusterType,
            tag: payload.image_tag,
            version: payload.version
          }
        )
      ).data.instance_id
      Modal.success({
        title: 'info',
        content: (
          <div>
            <p>
              Successfully submit the request to update the global Component
              Image.
              <br></br>
              <br></br>
              To check the progress of this operation, please refer to the{' '}
              <a href={`/operations/${id}`}>Detail</a> page.
            </p>
          </div>
        ),
        onOk() {
          window.open(`/operations/${id}`, '_blank')
        }
      })
      setModalEdit(false)
    } catch (error) {
      Modal.error({
        title: error.response.data.errcode,
        content: error.response.data.errmsg
      })
    }
  }, [])

  const handleCancelImage = useCallback(() => {
    setModalEdit(false)
  }, [])

  const shouldPaginateAvailableVersions =
    availableVersions.length > AVAILABLE_PAGE_SIZE

  return (
    <Stack gap="md">
      <Group gap={4}>
        {COMPONENT_VIEW_OPTIONS.map((option) => {
          const active = viewMode === option.value

          return (
            <Button
              key={option.value}
              variant="subtle"
              size="sm"
              onClick={() => setViewMode(option.value)}
              style={{
                borderBottom: active
                  ? '2px solid var(--mantine-color-peacock-6, #0b6fcb)'
                  : '2px solid transparent',
                borderRadius: 0,
                color: active
                  ? 'var(--mantine-color-carbon-9, #1f2d3d)'
                  : 'var(--mantine-color-carbon-6, #5f6b7a)',
                fontWeight: active ? 600 : 400,
                paddingLeft: 12,
                paddingRight: 12
              }}
            >
              {option.label}
            </Button>
          )
        })}
      </Group>

      {viewMode === 'cluster_versions' ? (
        <ClusterComponentVersions scope="global" />
      ) : (
        <>
          <Card withBorder shadow="xs" padding="md" radius="sm">
            <Stack gap="md">
              <Stack gap={4}>
                <Typography variant="title-md">
                  Available Component Versions
                </Typography>
                <Typography variant="body-sm" c="carbon.6">
                  View available component versions in config center.
                </Typography>
              </Stack>

              <SimpleGrid cols={{ base: 1, sm: 2, lg: 5 }} spacing="sm">
                <Select
                  label="Cluster Type"
                  data={AVAILABLE_CLUSTER_TYPE_OPTIONS}
                  value={selectedClusterType}
                  onChange={(value) => {
                    if (!value) {
                      return
                    }
                    setSelectedClusterType(
                      value as CloudConfigControllerListAvailableComponentVersionsClusterType
                    )
                  }}
                />
                <Select
                  label="Component"
                  data={components.map((component: string) => ({
                    label: component,
                    value: component
                  }))}
                  disabled={isLoadingComponents}
                  value={selectedComponent}
                  onChange={(value) => setSelectedComponent(value || '')}
                  searchable
                />
              </SimpleGrid>

              <ProTable<ComponentVersion>
                columns={columns}
                data={availableVersions}
                enableColumnActions={false}
                enableColumnFilters={false}
                enableDensityToggle={false}
                enableFullScreenToggle={false}
                enableHiding={false}
                enablePagination={shouldPaginateAvailableVersions}
                enableSorting={false}
                enableTopToolbar={false}
                getRowId={(row, rowIndex) =>
                  [row.version, row.base_image, row.image_tag, rowIndex].join(
                    '-'
                  )
                }
                loading={isLoading}
                onPaginationChange={(updaterOrValue) => {
                  setAvailablePagination((currentPagination) =>
                    getFixedPagination(updaterOrValue, currentPagination)
                  )
                }}
                pagination={{ showRowsPerPage: false }}
                rowCount={
                  shouldPaginateAvailableVersions
                    ? availableVersions.length
                    : undefined
                }
                state={{ pagination: availablePagination }}
              />
            </Stack>
          </Card>
          <ModalForm<UpdateNgComponentImage>
            title={'Modify Component Image'}
            visible={!!modalEdit}
            onCancel={handleCancelImage}
            width={1000}
            name="image"
            getFields={renderImageParamFields}
            onSubmit={handleImage}
            destoryOnClose={true}
            okText="Next"
          />
        </>
      )}
    </Stack>
  )
}

export default CCComponent
