import {
  Table,
  Space,
  Typography,
  Modal,
  Button,
  Input,
  Select,
  Progress
} from 'antd'
import { ColumnsType, TablePaginationConfig } from 'antd/lib/table'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { Link, useParams } from 'react-router-dom'

import { K8supgradeK8sCluster } from 'apiClient/services/devops/interface'

import {
  cancelUpgradeK8sCluster,
  excludeK8sUpgradeTaskCluster,
  getK8sUpgradeTask
} from '../../../../apiClient/services/devops'

import AutoGenerationSwitch from './AutoGenerationSwitch'

type ClusterFilters = {
  region?: string
  tenant?: string
  name?: string
}

const BATCH_EXCLUDE_CONCURRENCY = 3

type BatchExcludeProgress = {
  total: number
  done: number
  succeeded: number
  failed: number
  currentName?: string
}

type ExcludeResult = {
  cluster: K8supgradeK8sCluster
  status: 'fulfilled' | 'rejected'
  reason?: unknown
}

async function excludeClustersWithConcurrency(
  taskId: string,
  clusters: K8supgradeK8sCluster[],
  concurrency: number,
  onProgress: (progress: BatchExcludeProgress) => void
): Promise<ExcludeResult[]> {
  const queue = [...clusters]
  const results: ExcludeResult[] = []
  let done = 0
  let succeeded = 0
  let failed = 0
  const total = clusters.length

  onProgress({ total, done, succeeded, failed })

  const workers = Array.from({
    length: Math.min(concurrency, queue.length)
  }).map(async () => {
    while (queue.length) {
      const cluster = queue.shift()
      if (!cluster) return

      onProgress({ total, done, succeeded, failed, currentName: cluster.name })

      try {
        await excludeK8sUpgradeTaskCluster(taskId, cluster.name!)
        succeeded += 1
        results.push({ cluster, status: 'fulfilled' })
      } catch (reason) {
        failed += 1
        results.push({ cluster, status: 'rejected', reason })
      } finally {
        done += 1
        onProgress({ total, done, succeeded, failed })
      }
    }
  })

  await Promise.all(workers)
  return results
}

export const TaskK8sClusterList: React.FC<
  React.PropsWithChildren<{ status: string }>
> = ({ status }) => {
  const { task_id } = useParams<{ task_id: string }>()
  const [reload, setReload] = useState(false)
  const [taskStatus, setTaskStatus] = useState<string>(status)
  const [clusters, setTaskClusters] = useState<K8supgradeK8sCluster[]>()
  const [filters, setFilters] = useState<ClusterFilters>({})
  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([])
  const [batchExcludeProgress, setBatchExcludeProgress] =
    useState<BatchExcludeProgress | null>(null)
  const [pagination, setPagination] = useState<TablePaginationConfig>({
    current: 1,
    pageSize: 20,
    showSizeChanger: true,
    pageSizeOptions: ['10', '20', '50', '100'],
    showTotal: (total) => `Total ${total} clusters`
  })

  async function fetch() {
    const data = (await getK8sUpgradeTask(task_id)).data
    setTaskStatus(data?.status!)
    setTaskClusters(data?.k8s_cluster_list!)
  }

  useEffect(() => {
    fetch()
  }, [reload])

  const regionOptions = useMemo(() => {
    const regions = new Set<string>()
    clusters?.forEach((c) => {
      if (c.business_region) regions.add(c.business_region)
    })
    return Array.from(regions)
      .sort()
      .map((v) => ({ label: v, value: v }))
  }, [clusters])

  const tenantOptions = useMemo(() => {
    const tenants = new Set<string>()
    clusters?.forEach((c) => {
      if (c.tenant_name) tenants.add(c.tenant_name)
    })
    return Array.from(tenants)
      .sort()
      .map((v) => ({ label: v, value: v }))
  }, [clusters])

  const filteredClusters = useMemo(() => {
    if (!clusters) return []
    const nameQuery = filters.name?.trim().toLowerCase()
    return clusters.filter((c) => {
      if (filters.region && c.business_region !== filters.region) return false
      if (filters.tenant && c.tenant_name !== filters.tenant) return false
      if (nameQuery && !c.name?.toLowerCase().includes(nameQuery)) return false
      return true
    })
  }, [clusters, filters])

  useEffect(() => {
    setPagination((prev) => ({ ...prev, current: 1 }))
    setSelectedRowKeys([])
  }, [filters.region, filters.tenant, filters.name])

  useEffect(() => {
    setPagination((prev) => {
      const pageSize = prev.pageSize || 20
      const maxPage = Math.max(
        1,
        Math.ceil(filteredClusters.length / pageSize) || 1
      )
      const current = prev.current || 1
      if (current > maxPage) return { ...prev, current: maxPage }
      return prev
    })
  }, [filteredClusters.length, pagination.pageSize])

  const handleFilterChange = (patch: Partial<ClusterFilters>) => {
    setFilters((prev) => ({ ...prev, ...patch }))
  }

  const handleTableChange = (p: TablePaginationConfig) => {
    setPagination((prev) => ({
      ...prev,
      ...(p.current != null ? { current: p.current } : {}),
      ...(p.pageSize != null ? { pageSize: p.pageSize } : {})
    }))
  }

  const handleClick = useCallback(
    async (record: K8supgradeK8sCluster) => {
      Modal.info({
        title: 'Info',
        closable: true,
        content: (
          <div>
            <p>
              Sure to exclude this K8S cluster <b>{record.name}</b> from the
              upgrade task?
            </p>
          </div>
        ),
        okText: 'Confirm',
        async onOk() {
          try {
            await excludeK8sUpgradeTaskCluster(
              task_id!.toString(),
              record.name!
            )
            Modal.success({
              title: 'info',
              content: (
                <div>
                  <p>Successfully Exclude</p>
                </div>
              ),
              onOk() {}
            })
            setReload((pre) => !pre)
          } catch (error: any) {
            Modal.error({
              title: error.response.data.errcode,
              content: error.response.data.errmsg
            })
            setReload((pre) => !pre)
          }
        }
      })
    },
    [task_id]
  )

  const handleBatchExclude = useCallback(() => {
    const selected = filteredClusters.filter((c) =>
      selectedRowKeys.includes(c.id!)
    )
    if (!selected.length) return

    Modal.info({
      title: 'Info',
      closable: true,
      content: (
        <div>
          <p>
            Sure to exclude the following {selected.length} K8S cluster(s) from
            the upgrade task?
          </p>
          <ul>
            {selected.map((c) => (
              <li key={c.id}>
                <b>{c.name}</b>
              </li>
            ))}
          </ul>
        </div>
      ),
      okText: 'Confirm',
      async onOk() {
        setBatchExcludeProgress({
          total: selected.length,
          done: 0,
          succeeded: 0,
          failed: 0
        })
        try {
          const results = await excludeClustersWithConcurrency(
            task_id!.toString(),
            selected,
            BATCH_EXCLUDE_CONCURRENCY,
            setBatchExcludeProgress
          )
          const failedResults = results.filter((r) => r.status === 'rejected')
          if (failedResults.length === 0) {
            Modal.success({
              title: 'info',
              content: (
                <div>
                  <p>Successfully excluded {selected.length} cluster(s)</p>
                </div>
              ),
              onOk() {}
            })
          } else {
            const firstError = failedResults[0].reason as any
            Modal.error({
              title: firstError?.response?.data?.errcode || 'Error',
              content: `${failedResults.length} of ${
                selected.length
              } cluster(s) failed to exclude. ${
                firstError?.response?.data?.errmsg || ''
              }`
            })
          }
        } finally {
          setBatchExcludeProgress(null)
          setSelectedRowKeys([])
          setReload((pre) => !pre)
        }
      }
    })
  }, [filteredClusters, selectedRowKeys, task_id])

  const handleClickCancel = useCallback(
    async (record: K8supgradeK8sCluster) => {
      Modal.info({
        title: 'Info',
        closable: true,
        content: (
          <div>
            <p>
              Sure to cancel the upgrade of this K8S cluster{' '}
              <b>{record.name}</b>?
            </p>
          </div>
        ),
        okText: 'Confirm',
        async onOk() {
          try {
            await cancelUpgradeK8sCluster(task_id!.toString(), record.name!)
            Modal.success({
              title: 'info',
              content: (
                <div>
                  <p>Successfully Cancelled</p>
                </div>
              ),
              onOk() {}
            })
            setReload((pre) => !pre)
          } catch (error: any) {
            Modal.error({
              title: error.response.data.errcode,
              content: error.response.data.errmsg
            })
            setReload((pre) => !pre)
          }
        }
      })
    },
    [task_id]
  )

  const columns = useMemo(() => {
    const cols: ColumnsType<K8supgradeK8sCluster> = [
      {
        title: 'Name',
        width: 180,
        fixed: 'left',
        dataIndex: 'name',
        render: (_, record) => (
          <Space direction="vertical">
            {record.name ? (
              <Typography.Text
                style={{ width: 250 }}
                ellipsis={{ tooltip: record.name }}
              >
                {record.name}
              </Typography.Text>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
          </Space>
        )
      },
      {
        title: 'Tenant',
        width: 100,
        dataIndex: 'tenant_name',
        render: (_, record) => (
          <Space direction="vertical">
            {record.tenant_name ? (
              <Typography.Text
                style={{ width: 110 }}
                ellipsis={{ tooltip: record.tenant_name }}
              >
                {record.tenant_name}
              </Typography.Text>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
          </Space>
        )
      },
      {
        title: 'Region',
        width: 65,
        dataIndex: 'business_region',
        render: (_, record) => (
          <Space direction="vertical">
            {record.business_region ? (
              <Typography.Text
                style={{ width: 65 }}
                ellipsis={{ tooltip: record.business_region }}
              >
                {record.business_region}
              </Typography.Text>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
          </Space>
        )
      },
      {
        title: 'Desired Version',
        width: 90,
        dataIndex: 'desired_version',
        render: (_, record) => (
          <Space direction="vertical">
            {record.desired_version ? (
              <Typography.Text
                style={{ width: 100 }}
                ellipsis={{ tooltip: record.desired_version }}
              >
                {record.desired_version}
              </Typography.Text>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
          </Space>
        )
      },
      {
        title: 'Maintenance',
        width: 70,
        dataIndex: 'maintenance_window_id',
        render: (_: any, record: K8supgradeK8sCluster) => (
          <Space>
            {record.maintenance_window_id ? (
              <Link to={`/maintenance/${record.maintenance_window_id}`}>
                {record.maintenance_window_id}
              </Link>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
          </Space>
        )
      },
      {
        title: 'Auto Generate CR',
        key: 'auto_sync',
        width: 100,
        render: (_: any, record: K8supgradeK8sCluster) => (
          <Space>
            <AutoGenerationSwitch record={record} task_status={taskStatus!} />
          </Space>
        )
      },
      {
        title: 'Status',
        width: 60,
        dataIndex: 'upgrade_operation_status',
        render: (_, record) => (
          <Space direction="vertical">
            {record.upgrade_operation_status ? (
              <Typography.Text
                style={{ width: 100 }}
                ellipsis={{ tooltip: record.upgrade_operation_status }}
              >
                {record.upgrade_operation_status}
              </Typography.Text>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
          </Space>
        )
      },
      {
        title: 'Action',
        key: 'action',
        fixed: 'right',
        render: (_: any, record: K8supgradeK8sCluster) => (
          <Space>
            <Link
              to={`/k8sUpgradeTask/${task_id}/K8sCluster/${record.name}?cloud_provider=${record.cloud_provider}&task_status=${taskStatus}&region=${record.region}`}
            >
              Detail
            </Link>
            <Button
              type="primary"
              onClick={() => handleClick(record)}
              danger
              size={'small'}
              disabled={taskStatus != 'pending'}
            >
              Exclude
            </Button>
            <Button
              type="primary"
              onClick={() => handleClickCancel(record)}
              danger
              size={'small'}
              disabled={
                taskStatus != 'running' ||
                record.upgrade_operation_status == 'cancelled'
              }
            >
              Cancel
            </Button>
          </Space>
        ),
        width: 130
      }
    ]

    return cols
  }, [handleClick, handleClickCancel, taskStatus, task_id])

  const rowSelection =
    taskStatus === 'pending'
      ? {
          selectedRowKeys,
          onChange: (keys: React.Key[]) => setSelectedRowKeys(keys),
          preserveSelectedRowKeys: true,
          getCheckboxProps: () => ({
            disabled: batchExcludeProgress !== null
          })
        }
      : undefined

  if (!clusters) {
    return <></>
  }
  if (clusters?.length == 0) {
    return <></>
  }

  return (
    <>
      <Space style={{ marginBottom: 16 }} wrap>
        <Select
          allowClear
          showSearch
          placeholder="Region"
          style={{ width: 160 }}
          options={regionOptions}
          value={filters.region}
          onChange={(value) => handleFilterChange({ region: value })}
          optionFilterProp="label"
        />
        <Select
          allowClear
          showSearch
          placeholder="Tenant"
          style={{ width: 200 }}
          options={tenantOptions}
          value={filters.tenant}
          onChange={(value) => handleFilterChange({ tenant: value })}
          optionFilterProp="label"
        />
        <Input
          allowClear
          placeholder="Name"
          style={{ width: 200 }}
          value={filters.name}
          onChange={(e) => handleFilterChange({ name: e.target.value })}
        />
        {taskStatus === 'pending' ? (
          <Button
            type="primary"
            danger
            disabled={!selectedRowKeys.length || batchExcludeProgress !== null}
            loading={batchExcludeProgress !== null}
            onClick={handleBatchExclude}
          >
            Exclude Selected ({selectedRowKeys.length})
          </Button>
        ) : null}
      </Space>
      <Modal
        visible={batchExcludeProgress !== null}
        footer={null}
        closable={false}
        title="Excluding clusters..."
      >
        <Progress
          percent={
            batchExcludeProgress
              ? Math.round(
                  (batchExcludeProgress.done / batchExcludeProgress.total) * 100
                )
              : 0
          }
          status="active"
        />
        <p style={{ textAlign: 'center', marginTop: 12, color: '#666' }}>
          {batchExcludeProgress
            ? `${batchExcludeProgress.done}/${batchExcludeProgress.total} completed (success: ${batchExcludeProgress.succeeded}, failed: ${batchExcludeProgress.failed})`
            : ''}
        </p>
        {batchExcludeProgress?.currentName ? (
          <p style={{ textAlign: 'center', color: '#999', fontSize: 12 }}>
            Processing: {batchExcludeProgress.currentName}
          </p>
        ) : null}
      </Modal>
      <Table<K8supgradeK8sCluster>
        columns={columns}
        rowKey="id"
        dataSource={filteredClusters}
        loading={false}
        pagination={{
          ...pagination,
          total: filteredClusters.length
        }}
        onChange={handleTableChange}
        rowSelection={rowSelection}
        size="small"
        scroll={{ x: 1200 }}
      />
    </>
  )
}
