import { Alert, Descriptions, Spin } from 'antd'
import type { DescriptionsProps } from 'antd/lib/descriptions'
import React, { useEffect, useRef, useState } from 'react'

import { getCluster, getTenant } from 'apiClient/services/devops'
import {
  ClusterGetClusterResp,
  TenantGetTenantResp
} from 'apiClient/services/devops/interface'

import {
  getTenantLabel,
  isResourcePoolDeployType,
  shouldLoadTenant
} from './shared'

export interface ClusterDescriptionProps {
  clusterId: string
  bordered?: boolean
  column?: DescriptionsProps['column']
  onLoaded?: (
    clusterInfo: ClusterGetClusterResp,
    tenantInfo?: TenantGetTenantResp
  ) => void
}

const DEFAULT_ERROR_MESSAGE = 'Failed to fetch cluster detail.'

function getErrorMessage(error: unknown) {
  const axiosLikeError = error as {
    response?: { data?: { errmsg?: string } }
    message?: string
  }

  return (
    axiosLikeError?.response?.data?.errmsg ||
    axiosLikeError?.message ||
    DEFAULT_ERROR_MESSAGE
  )
}

export const ClusterDescription: React.FC<ClusterDescriptionProps> = ({
  clusterId,
  bordered = false,
  column = 1,
  onLoaded
}) => {
  const [clusterInfo, setClusterInfo] = useState<ClusterGetClusterResp>()
  const [tenantInfo, setTenantInfo] = useState<TenantGetTenantResp>()
  const [curError, setCurError] = useState<string>()
  const [loading, setLoading] = useState(false)
  const requestIdRef = useRef(0)

  useEffect(() => {
    if (!clusterId) {
      setClusterInfo(undefined)
      setTenantInfo(undefined)
      setCurError(undefined)
      setLoading(false)
      return
    }

    const currentRequestId = requestIdRef.current + 1
    requestIdRef.current = currentRequestId

    const fetchInfo = async () => {
      setLoading(true)
      setCurError(undefined)
      setClusterInfo(undefined)
      setTenantInfo(undefined)

      try {
        const clusterData = (await getCluster(clusterId)).data

        if (currentRequestId !== requestIdRef.current) {
          return
        }

        setClusterInfo(clusterData)

        let tenantData: TenantGetTenantResp | undefined
        if (shouldLoadTenant(clusterData.tenant_id)) {
          tenantData = (await getTenant(clusterData.tenant_id)).data

          if (currentRequestId !== requestIdRef.current) {
            return
          }

          setTenantInfo(tenantData)
        }

        onLoaded?.(clusterData, tenantData)
      } catch (error) {
        if (currentRequestId !== requestIdRef.current) {
          return
        }

        setCurError(getErrorMessage(error))
      } finally {
        if (currentRequestId === requestIdRef.current) {
          setLoading(false)
        }
      }
    }

    fetchInfo()
  }, [clusterId, onLoaded])

  if (curError) {
    return (
      <Alert
        message="Error"
        description={curError}
        type="error"
        showIcon
        style={{ width: '100%', marginBottom: '12px' }}
      />
    )
  }

  if (loading || !clusterInfo) {
    return (
      <div style={{ width: '100%', padding: '12px 0', textAlign: 'center' }}>
        <Spin />
      </div>
    )
  }

  return (
    <div style={{ width: '100%' }}>
      <Descriptions bordered={bordered} column={column} size="small">
        <Descriptions.Item
          label={
            isResourcePoolDeployType(clusterInfo.deploy_type)
              ? 'Resource Pool'
              : 'Cluster'
          }
        >
          {clusterInfo.name} ({clusterInfo.id})
        </Descriptions.Item>
        <Descriptions.Item label="Type">
          {clusterInfo.deploy_type}
        </Descriptions.Item>
        <Descriptions.Item label="Status">
          {clusterInfo.status
            ? clusterInfo.status.replace('USER_CLUSTER_STATUS_', '')
            : '-'}
        </Descriptions.Item>
        <Descriptions.Item label="Project">
          {clusterInfo.project_name} ({clusterInfo.project_id})
        </Descriptions.Item>
        <Descriptions.Item label="Tenant">
          {getTenantLabel(clusterInfo.tenant_id, tenantInfo)}
        </Descriptions.Item>
      </Descriptions>
    </div>
  )
}

export default ClusterDescription
