import React, { useEffect, useMemo, useState, useRef } from 'react'

import { Divider, Modal, Select } from 'antd'
import useSWR from 'swr'

import { ClusterDataUrl, ClusterCluster } from '@clinic/client'
import {
  getClusterDataStatus,
  getMetricDashboards,
  rebuildClusterData,
  getDashboardVersionsList
} from '~/api'
import LoadingSpin from '~/components/LoadingSpin'
import { useCurOrg } from '~/hooks/state'
import { useMutation } from '~/hooks/use-mutation'
import { clusterDetailTelemetry } from '~/telemetry'
import { ClusterDeployType, ClusterDeployTypeV2 } from '~/utils/cluster-status'

import { DetailItemCard } from '../components/DetailItemCard'
import { applyMetricDashboardTimeRange } from './metric-dashboard-time-range'
import { ItemModalProps, ItemType } from './types'

interface MetricsTarget {
  title: string
  id: string
  node_info: string
}

const cloudMetricsTargets: MetricsTarget[] = [
  {
    title: 'Nodes-Info Legacy (include deleted)',
    id: 'fa49a4706d07a042595b664c87fb33easdfasdfa/nodes-info',
    node_info: ''
  }
]

type MetricsModalPros = ItemModalProps & {
  orgName?: string
  cluster: ClusterCluster
  visible: boolean
}

export const MetricsModalBody: React.FC<MetricsModalPros> = ({
  oid,
  cid,
  timeRange,
  onClose,
  cluster,
  visible
}) => {
  const { start, end } = timeRange
  const itemType = ItemType.Metrics

  const { curOrg } = useCurOrg()

  // invalidate the cache
  const now = useMemo(() => new Date().valueOf(), [])
  const { data: dataStatusRes, error } = useSWR(
    [`/orgs/${oid}/clusters/${cid}/data_status`, start, end, itemType, now],
    () => getClusterDataStatus(oid, cid, start, end, itemType)
  )
  const loading = !dataStatusRes && !error

  const { run: runRebuildClusterData } = useMutation(rebuildClusterData)

  const [metricDashboards, setMetricDashboards] = useState<
    ClusterDataUrl[] | undefined
  >(undefined)
  const [dashboardVersions, setDashboardVersions] = useState<string[]>([])

  const [metricModalVisible, setMetricModalVisible] = useState(false)

  const selectedDashboardVersion = useRef<undefined | string>(undefined)

  useEffect(() => {
    // metrics
    if (dataStatusRes) {
      if (metricModalVisible) {
        return
      }
      const coldItems =
        dataStatusRes.data.items?.filter((i) => i.status === -1) ?? []
      if (coldItems.length > 0) {
        setMetricModalVisible(true)
        Modal.confirm({
          title: 'Do you want to rebuild the data?',
          content: 'The data is cold, need to rebuild before ready',
          onOk: () => {
            coldItems.forEach((item) => {
              runRebuildClusterData({
                oid,
                cid,
                rebuild: { dataType: itemType, itemID: item.itemID }
              })
            })
            onClose?.()
          },
          onCancel: () => {
            onClose?.()
          }
        })
        return
      }
      const totalProgress =
        dataStatusRes.data.items?.reduce((pre, cur) => pre + cur.status!, 0) ??
        0
      const avgProgress =
        totalProgress / (dataStatusRes.data.items?.length ?? 1)
      if (avgProgress === 0) {
        setMetricModalVisible(true)
        Modal.info({
          title: 'Data rebuild is queued',
          content: 'It may need several minutes to start rebuilding',
          onOk: () => {
            onClose?.()
          }
        })
        return
      }
      if (avgProgress === -2) {
        setMetricModalVisible(true)
        Modal.info({
          title: 'Rebuild failed or data expired',
          content: 'Rebuild failed or data expired',
          onOk: () => {
            onClose?.()
          }
        })
        return
      }
      if (avgProgress < 100) {
        setMetricModalVisible(true)
        Modal.info({
          title: 'The data is still rebuilding',
          content: `Please wait untill the data is ready (process: ${avgProgress.toFixed(
            2
          )}%)`,
          onOk: () => {
            onClose?.()
          }
        })
        return
      }
      getMetricDashboards(
        oid,
        cid,
        start,
        end,
        selectedDashboardVersion.current
      )
        .then((res) => {
          setMetricDashboards(
            applyMetricDashboardTimeRange(res.data, start, end)
          )
        })
        .catch((err) => console.log(err))
      getDashboardVersionsList(oid, cid)
        .then((res) => {
          setDashboardVersions(res.data)
        })
        .catch((err) => console.log(err))
    }
  }, [
    metricModalVisible,
    itemType,
    dataStatusRes,
    oid,
    cid,
    end,
    start,
    runRebuildClusterData,
    onClose
  ])

  if (loading) {
    return (
      <div className='text-center'>
        <LoadingSpin />
      </div>
    )
  }

  const DEFAUTL_VERSION_VALUE = 'Default'

  const onSelectedVersionChange = (version: string) => {
    getMetricDashboards(
      oid,
      cid,
      start,
      end,
      version === DEFAUTL_VERSION_VALUE ? undefined : version
    )
      .then((res) => {
        setMetricDashboards(applyMetricDashboardTimeRange(res.data, start, end))
        selectedDashboardVersion.current = version
      })
      .catch((err) => console.log(err))
  }

  let nodeMetricsClusterID = cluster.id
  if (
    cluster.deployType === ClusterDeployType.Premium ||
    cluster.deployType === ClusterDeployType.Byoc
  ) {
    nodeMetricsClusterID = cluster.parentID
  }
  const shootName =
    cluster.shootName ||
    `${cluster.region!}-${cluster.provider === 'alicloud' ? 'a01' : 'f01'}`
  const serverlessControlPlaneInfo = `${shootName}/${cluster.provider!}-${cluster.region!}/devtier-infra`
  const isStarterOrEssentialV1 =
    cluster.deployTypeV2 === ClusterDeployTypeV2.Starter ||
    cluster.deployTypeV2 === ClusterDeployTypeV2.Essential
  const buildServerlessGrafanaHref = (
    uid: string,
    slug: string,
    extraParams: Record<string, string | number | undefined> = {}
  ) => {
    const params = new URLSearchParams()
    const baseParams: Record<string, string | undefined> = {
      orgId: '1',
      'var-org': `${oid}`,
      'var-org_type': 'cloud',
      'var-tidb_cluster': cluster.id,
      'var-cluster_id': cluster.id,
      'var-cluster_name': cluster.name,
      'var-tenant_id': curOrg?.externalID,
      'var-tenant_name': curOrg?.name,
      'var-control_plane_info': serverlessControlPlaneInfo,
      'var-keyspace_id':
        cluster.keyspaceID != null && cluster.keyspaceID !== 0
          ? String(cluster.keyspaceID)
          : undefined,
      'var-keyspace_name': cluster.keyspaceName
    }

    Object.entries(baseParams).forEach(([key, value]) => {
      if (typeof value === 'string' && value !== '') {
        params.set(key, value)
      }
    })

    Object.entries(extraParams).forEach(([key, value]) => {
      if (value !== undefined && value !== '') {
        params.set(key, `${value}`)
      }
    })

    return `/grafana/d/${uid}/${slug}?${params.toString()}`
  }
  return (
    <div className='flex justify-center'>
      <div className='flex flex-col'>
        {cluster.deployType === ClusterDeployType.Shared && (
          <>
            <a
              key='kFzFvOTSz'
              href={buildServerlessGrafanaHref(
                'kFzFvOTSz',
                'tidb-serverless-cluster-metrics-clinic',
                {
                  refresh: '15m',
                  from: start * 1000,
                  to: end * 1000
                }
              )}
              target='_blank'
              className='text-cc-primary hover:text-cc-primary'
            >
              TiDB-Serverless-Cluster-Metrics-Clinic
            </a>
            <a
              key='fsN8WxH4k'
              href={buildServerlessGrafanaHref(
                'fsN8WxH4k',
                'serverless-tier-one-screen',
                {
                  from: start * 1000,
                  to: end * 1000,
                  refresh: '30s'
                }
              )}
              target='_blank'
              className='text-cc-primary hover:text-cc-primary'
            >
              Starter-Essential-One-Screen-for-Clinic
            </a>
            <a
              key='_eCx0ZDvz'
              href={buildServerlessGrafanaHref(
                '_eCx0ZDvz',
                'starter-essential-tikv-details-for-clinic',
                {
                  refresh: '10s',
                  'var-command': 'All',
                  'var-db': 'All',
                  'var-instance': 'All',
                  'var-titan_db': 'All'
                }
              )}
              target='_blank'
              className='text-cc-primary hover:text-cc-primary'
            >
              Starter-Essential-TiKV-Details-for-Clinic
            </a>
            {isStarterOrEssentialV1 && (
              <a
                key='tikv-worker-serverless'
                href={buildServerlessGrafanaHref(
                  'tikv-worker-serverless',
                  'starter-essential-tikv-worker-for-clinic',
                  {
                    refresh: '30s',
                    'var-db': 'All',
                    'var-command': 'All',
                    'var-worker_instance': 'All',
                    'var-titan_db': 'All',
                    'var-additional_groupby': 'none',
                    'var-optional_quantile': '0.99'
                  }
                )}
                target='_blank'
                className='text-cc-primary hover:text-cc-primary'
              >
                Starter-Essential-TiKV-Worker-for-Clinic
              </a>
            )}
            <a
              key='EHufAWDDz'
              href={buildServerlessGrafanaHref(
                'EHufAWDDz',
                'starter-essential-tiflash-summary-for-clinic',
                {
                  'var-keyspace': 'All',
                  'var-instance': 'All'
                }
              )}
              target='_blank'
              className='text-cc-primary hover:text-cc-primary'
            >
              Starter-Essential-TiFlash-Summary-for-Clinic
            </a>
            <a
              key='IFisAZvvz'
              href={buildServerlessGrafanaHref(
                'IFisAZvvz',
                'starter-essential-etcd-group-for-clinic',
                {
                  refresh: '5s'
                }
              )}
              target='_blank'
              className='text-cc-primary hover:text-cc-primary'
            >
              Starter-Essential-ETCD-Group-for-Clinic
            </a>
            <a
              key='NdbU0WDDz'
              href={buildServerlessGrafanaHref(
                'NdbU0WDDz',
                'starter-essential-pd-tso-for-clinic',
                {
                  'var-store': 'All',
                  'var-instance': 'All'
                }
              )}
              target='_blank'
              className='text-cc-primary hover:text-cc-primary'
            >
              Starter-Essential-PD-TSO-for-Clinic
            </a>
            <a
              key='hIP_AZDDk'
              href={buildServerlessGrafanaHref(
                'hIP_AZDDk',
                'starter-essential-pd-ms-for-clinic',
                {
                  'var-store': 'All',
                  'var-instance': 'All',
                  from: start * 1000,
                  to: end * 1000
                }
              )}
              target='_blank'
              className='text-cc-primary hover:text-cc-primary'
            >
              Starter-Essential-PD-MS-for-Clinic
            </a>
            <a
              key='rYdddlPWa'
              href={buildServerlessGrafanaHref(
                'rYdddlPWa',
                'node-exporter-full',
                {
                  'var-DS_PROMETHEUS': 'o11y-global-data',
                  'var-job': 'node-exporter',
                  'var-node': 'All',
                  'var-diskdevices': '[a-z]+|nvme[0-9]+n[0-9]+|mmcblk[0-9]+'
                }
              )}
              target='_blank'
              className='text-cc-primary hover:text-cc-primary'
            >
              Starter-Essential-Node-info-for-Clinic
            </a>
            <a
              key='YiGL8hBZ2'
              href={buildServerlessGrafanaHref(
                'YiGL8hBZ2',
                'serverless-cluster-ticdc'
              )}
              target='_blank'
              className='text-cc-primary hover:text-cc-primary'
            >
              Serverless-Cluster-TiCDC-for-Clinic
            </a>
            {isStarterOrEssentialV1 && (
              <a
                key='YiGL8hBZ0aac'
                href={buildServerlessGrafanaHref(
                  'YiGL8hBZ0aac',
                  'tidb-serverless-test-ticdc-new-arch',
                  {
                    'var-changefeed': 'All',
                    'var-ticdc_instance': 'All',
                    'var-tikv_instance': 'All',
                    'var-spike_threshold': 'All',
                    'var-runtime_instance': 'All',
                    from: start * 1000,
                    to: end * 1000
                  }
                )}
                target='_blank'
                className='text-cc-primary hover:text-cc-primary'
              >
                Serverless-Cluster-TiCDC-New-Arch-for-Clinic
              </a>
            )}
          </>
        )}
        {cluster.deployType !== ClusterDeployType.Shared && dashboardVersions && (
          <div className='mb-8'>
            <p>Versions of dashboard</p>
            <Select
              defaultValue={DEFAUTL_VERSION_VALUE}
              style={{ width: 300 }}
              onChange={onSelectedVersionChange}
              options={[
                {
                  label: DEFAUTL_VERSION_VALUE,
                  value: DEFAUTL_VERSION_VALUE
                }
              ].concat(
                dashboardVersions.map((v) => ({
                  label: v,
                  value: v
                }))
              )}
            />
          </div>
        )}
        {cluster.clusterType === 'cloud' &&
          cluster.deployType !== ClusterDeployType.Shared &&
          visible && (
            <>
              <a
                href={`/grafana/d/clinic-resource-overview/dataplane-resource-overview?orgId=1&var-cluster=All&var-tidb_cluster=${nodeMetricsClusterID}&var-namespace=tidb${nodeMetricsClusterID}&from=${
                  start * 1000
                }&to=${end * 1000}`}
                target='_blank'
                className='text-blue-800 hover:text-blue-800'
              >
                K8S Resource Overview
              </a>
              <a
                href={`/grafana/d/clinic-dataplane-node/dedicated-dataplane-node-info?orgId=1&var-k8s_cluster=All&var-tidb_cluster=${nodeMetricsClusterID}&var-namespace=tidb${nodeMetricsClusterID}&from=${
                  start * 1000
                }&to=${end * 1000}`}
                target='_blank'
                className='text-blue-800 hover:text-blue-800'
              >
                Nodes Info
              </a>
              <a
                href={`/grafana/d/rnogfAznk/resource-overview?orgId=1&var-control_plane_info=seed/${cluster.provider!}-${cluster.region!}/seed&var-project_id=${
                  // TODO: change logic region
                  cluster.projectID
                }&var-namespace=tidb${cluster.id}&from=${start * 1000}&to=${
                  end * 1000
                }`}
                target='_blank'
                className='text-gray-400 hover:text-blue-800'
              >
                K8S Resource Overview Legacy
              </a>
              {cloudMetricsTargets.map((target) => (
                <a
                  key={target.id}
                  href={`/grafana/d/${
                    target.id
                  }?orgId=1&refresh=15m&var-project_id=${
                    cluster.projectID
                  }&var-cluster_id=${
                    cluster.id
                  }&var-control_plane_info=seed/${cluster.provider!}-${cluster.region!}/seed&from=${
                    // TODO: change logic region
                    start * 1000
                  }&to=${end * 1000}`}
                  target='_blank'
                  className='text-gray-400 hover:text-blue-800'
                >
                  {target.title}
                </a>
              ))}
              <Divider className='my-1' />
            </>
          )}
        {cluster.deployType !== ClusterDeployType.Shared &&
          (metricDashboards ?? []).map((m) => {
            // Determine link style based on deploy type and dashboard name
            const hasKeyspaceInName =
              m.name?.toLowerCase().includes('keyspacename') ||
              m.name?.toLowerCase().includes('tiproxy') ||
              false
            let linkClassName = 'text-blue-800 hover:text-blue-800'

            // For NG-Host: Gray out dashboards with "keyspace"
            if (cluster.deployType === 'nextgen-host' && hasKeyspaceInName) {
              linkClassName = 'text-gray-400 hover:text-gray-400'
            }

            return (
              <a
                key={m.name || `dashboard-${Math.random()}`}
                className={linkClassName}
                href={m.url!}
                target='_blank'
                onClick={() => {
                  clusterDetailTelemetry.clickMetricsItem(m.url!)
                }}
              >
                {m.name}
              </a>
            )
          })}
      </div>
    </div>
  )
}

export const OPMetricsModal: React.FC<MetricsModalPros> = (props) => {
  const name = 'Metrics'
  const [modalVisible, setModalVisible] = useState(false)
  return (
    <>
      <DetailItemCard
        onClick={() => {
          clusterDetailTelemetry.clickMetricsCard()
          setModalVisible(true)
        }}
        name={name}
      />

      <Modal
        visible={modalVisible}
        footer={null}
        onCancel={() => setModalVisible(false)}
        title={name}
        destroyOnClose={true}
      >
        <MetricsModalBody onClose={() => setModalVisible(false)} {...props} />
      </Modal>
    </>
  )
}
