import {
  Alert,
  Button,
  Card,
  Descriptions,
  Form,
  Input,
  Modal,
  Popconfirm,
  Space,
  Tag
} from 'antd'
import React from 'react'

import {
  clusterServiceApplyHeterogeneousDeploy,
  clusterServiceDeleteHeterogeneousDeploy,
  useClusterServiceGetHeterogeneousDeploy
} from 'apiClient/services/devops'
import {
  ClusterApplyHeterogeneousDeployRequest,
  ClusterComponentInfo,
  ClusterComponentType,
  ClusterHeterogeneousDeployPodCount
} from 'apiClient/services/devops/interface'
import {
  FormOption,
  FormSection,
  FormSectionGroup
} from 'components/FormSection'
import ModalForm from 'components/ModalForm'

interface ComponentHeterogeneousDeployProps {
  tenantId: string
  clusterId: string
  comp: ClusterComponentInfo
}

type ConfigureHeterogeneousDeployFormValues =
  ClusterApplyHeterogeneousDeployRequest & {
    tenant_id: string
    cluster_id: string
  }

const emptyHeterogeneousDeployText = <span style={{ color: '#aaa' }}>-</span>

const formOptionItemStyle = { marginBottom: 0 }

const renderHeterogeneousDeployText = (value?: React.ReactNode) => {
  if (
    value === undefined ||
    value === null ||
    value === '' ||
    (Array.isArray(value) && value.length === 0)
  ) {
    return emptyHeterogeneousDeployText
  }

  return value
}

const renderPodCountTag = (podCount?: number) => {
  if (podCount === undefined || podCount === null) {
    return null
  }

  return (
    <Tag color="blue" style={{ margin: 0 }}>
      {podCount} {podCount === 1 ? 'pod' : 'pods'}
    </Tag>
  )
}

const findPodCountForMachineType = (
  machineType?: string,
  podCounts?: ClusterHeterogeneousDeployPodCount[]
) => {
  const normalizedMachineType = machineType?.trim()
  if (!normalizedMachineType) {
    return undefined
  }

  return podCounts?.find(
    (podCount) => podCount.machine_type?.trim() === normalizedMachineType
  )?.pod_count
}

const renderMachineTypeWithPodCount = (
  machineType?: string,
  podCounts?: ClusterHeterogeneousDeployPodCount[]
) => {
  const podCountTag = renderPodCountTag(
    findPodCountForMachineType(machineType, podCounts)
  )

  if (!podCountTag) {
    return renderHeterogeneousDeployText(machineType)
  }

  return (
    <Space size={8}>
      {renderHeterogeneousDeployText(machineType)}
      {podCountTag}
    </Space>
  )
}

const showOperationCreatedModal = (title: string, operationId?: number) => {
  Modal.success({
    title,
    content: (
      <div>
        <p>
          The operation has been created.
          <br></br>
          However, you should go to to the <b>Detail</b> Page to check the
          Approval information. Click <b>OK</b> will redirect you to that page.
        </p>
      </div>
    ),
    onOk() {
      window.open(`/operations/${operationId}`, '_blank')
    }
  })
}

export const ComponentHeterogeneousDeploy: React.FC<
  ComponentHeterogeneousDeployProps
> = ({ tenantId, clusterId, comp }) => {
  const [isApplying, setIsApplying] = React.useState(false)
  const [isDeleting, setIsDeleting] = React.useState(false)
  const [applyFormVisible, setApplyFormVisible] = React.useState(false)
  const componentType = comp.component_type!
  const isTidbGroup =
    componentType === ClusterComponentType.tidb && comp.tidb_group_id
  const heterogeneousDeployRequest = {
    component_type: componentType,
    ...(isTidbGroup ? { tidb_group_id: comp.tidb_group_id } : {})
  }
  const { data, isError, isLoading, refetch } =
    useClusterServiceGetHeterogeneousDeploy(
      clusterId,
      heterogeneousDeployRequest
    )

  const handleApply = async (
    payload: ConfigureHeterogeneousDeployFormValues
  ) => {
    const heterogeneousDeployPayload: ClusterApplyHeterogeneousDeployRequest = {
      component_type: payload.component_type,
      tidb_group_id: payload.tidb_group_id,
      current_instance_type: payload.current_instance_type,
      alternative_instance_type: payload.alternative_instance_type,
      reason: payload.reason
    }

    setIsApplying(true)
    try {
      const resp = await clusterServiceApplyHeterogeneousDeploy(
        clusterId,
        heterogeneousDeployPayload
      )
      showOperationCreatedModal(
        'Apply Heterogeneous Deploy Operation Created',
        resp.data.instance_id
      )
      await refetch()
      setApplyFormVisible(false)
    } finally {
      setIsApplying(false)
    }
  }

  const handleDelete = async () => {
    setIsDeleting(true)
    try {
      const resp = await clusterServiceDeleteHeterogeneousDeploy(
        clusterId,
        heterogeneousDeployRequest
      )
      showOperationCreatedModal(
        'Turn Off Heterogeneous Deploy Operation Created',
        resp.data.instance_id
      )
      await refetch()
    } finally {
      setIsDeleting(false)
    }
  }

  const applyFormInitValues: ConfigureHeterogeneousDeployFormValues = {
    tenant_id: tenantId,
    cluster_id: clusterId,
    ...heterogeneousDeployRequest,
    current_instance_type: comp.instance_type,
    alternative_instance_type: data?.data.deploy?.alternative_instance_type
  }

  let content: React.ReactNode = null

  if (isError) {
    content = (
      <Alert
        type="error"
        showIcon
        message="Failed to load heterogeneous deploy."
      />
    )
  } else if (data) {
    const deploy = data.data.deploy!
    const podCounts = deploy.pod_counts

    content =
      deploy.enabled === false ? (
        <Alert
          type="info"
          showIcon
          message="Heterogeneous deploy is disabled for this component."
        />
      ) : (
        <Descriptions column={1} size="small">
          <Descriptions.Item label="Current Instance Type">
            {renderMachineTypeWithPodCount(
              deploy.current_instance_type,
              podCounts
            )}
          </Descriptions.Item>
          <Descriptions.Item label="Fallback Instance Type">
            {renderMachineTypeWithPodCount(
              deploy.alternative_instance_type,
              podCounts
            )}
          </Descriptions.Item>
          <Descriptions.Item label="Status">
            {renderHeterogeneousDeployText(
              deploy.status?.replace(/^GKE_HETEROGENEOUS_DEPLOY_STATUS_/, '')
            )}
          </Descriptions.Item>
        </Descriptions>
      )
  }

  return (
    <>
      <Card
        title={
          <>
            Heterogeneous Deploy
            <a
              href="https://pingcap.feishu.cn/wiki/XfkrwzBaSiqG2ykTmfCcIktVnjc"
              rel="noreferrer"
              target="_blank"
              style={{ fontSize: 12, marginLeft: 8 }}
            >
              Info
            </a>
          </>
        }
        extra={
          <Space>
            <Button
              type="primary"
              loading={isApplying}
              disabled={
                isLoading ||
                isDeleting ||
                isError ||
                data?.data.deploy?.enabled === true
              }
              onClick={() => setApplyFormVisible(true)}
            >
              Configure
            </Button>
            <Popconfirm
              title={
                <div style={{ maxWidth: 360 }}>
                  <div>Are you sure to turn off heterogeneous deploy?</div>
                  <div>
                    Pods may stay pending if the base instance type lacks
                    capacity after this is turned off.
                  </div>
                </div>
              }
              okText="Yes"
              cancelText="No"
              onConfirm={handleDelete}
            >
              <Button
                danger
                loading={isDeleting}
                disabled={
                  isLoading ||
                  isApplying ||
                  isError ||
                  data?.data.deploy?.enabled === false
                }
              >
                Turn Off
              </Button>
            </Popconfirm>
          </Space>
        }
        loading={isLoading}
        style={{ marginBottom: 16, border: '1px solid #d9d9d9' }}
        headStyle={{ backgroundColor: '#fafafa' }}
      >
        {content}
      </Card>
      <ModalForm<ConfigureHeterogeneousDeployFormValues>
        visible={applyFormVisible}
        name="apply_heterogeneous_deploy"
        title="Configure Heterogeneous Deploy"
        okText="Apply"
        initValues={applyFormInitValues}
        onSubmit={handleApply}
        onCancel={() => setApplyFormVisible(false)}
        destoryOnClose={true}
        width={800}
        getFields={() => (
          <FormSectionGroup show_outline>
            <FormSection title="Component">
              <FormOption title="tenant id">
                <Form.Item name="tenant_id" style={formOptionItemStyle}>
                  <Input disabled />
                </Form.Item>
              </FormOption>
              <FormOption title="cluster id">
                <Form.Item name="cluster_id" style={formOptionItemStyle}>
                  <Input disabled />
                </Form.Item>
              </FormOption>
              <FormOption title="component_type">
                <Form.Item name="component_type" style={formOptionItemStyle}>
                  <Input disabled />
                </Form.Item>
              </FormOption>
              {componentType === ClusterComponentType.tidb && (
                <FormOption title="tidb_group_id">
                  <Form.Item name="tidb_group_id" style={formOptionItemStyle}>
                    <Input disabled />
                  </Form.Item>
                </FormOption>
              )}
            </FormSection>
            <FormSection title="Topology">
              <FormOption title="current_instance_type">
                <Form.Item
                  name="current_instance_type"
                  style={formOptionItemStyle}
                >
                  <Input disabled />
                </Form.Item>
              </FormOption>
              <FormOption
                title="fallback_instance_type"
                description="A fallback instance type with equivalent vCPU/memory but different architecture (e.g. n2d-standard-8 for n2-standard-8). Used when the current type lacks capacity. Not a scale target."
              >
                <Form.Item
                  name="alternative_instance_type"
                  style={formOptionItemStyle}
                >
                  <Input />
                </Form.Item>
              </FormOption>
              <FormOption title="reason">
                <Form.Item name="reason" style={formOptionItemStyle}>
                  <Input.TextArea rows={3} />
                </Form.Item>
              </FormOption>
            </FormSection>
          </FormSectionGroup>
        )}
      />
    </>
  )
}
