import {
  Alert,
  Button,
  Card,
  Descriptions,
  Drawer,
  Empty,
  Progress,
  Space,
  Spin,
  Table,
  Tabs
} from 'antd'
import type { ColumnsType } from 'antd/lib/table'
import React, { useState } from 'react'

import { formatServicePlanDisplayName } from 'utils/string'

import {
  useGetCurrentRestoreProgress,
  useGetRestore,
  useListRestores
} from '../hooks'
import { strings } from '../strings'
import { useToolsPage } from '../ToolsPageContext'
import { getDeployTypeDisplayName, isNextGenDeployType } from '../types'
import type { Restore } from '../types'
import { formatBytes, formatDuration, formatTs, statusBadge } from '../utils'

const PAGE_SIZE_OPTS = ['10', '20', '50', '100']

// ---- Restore Detail Drawer ----------------------------------------------

function RestoreDetailDrawer({
  open,
  restoreId,
  onClose
}: {
  open: boolean
  restoreId?: string
  onClose: () => void
}) {
  const { clusterId } = useToolsPage()
  const { data, isLoading } = useGetRestore(clusterId, restoreId, open)
  return (
    <Drawer
      open={open}
      onClose={onClose}
      width={480}
      title={data ? `Restore: ${data.id}` : 'Restore Detail'}
    >
      {isLoading && <div>Loading…</div>}
      {!isLoading && !data && <div>{strings.common.empty}</div>}
      {data && (
        <Space direction="vertical" style={{ width: '100%' }}>
          <Descriptions
            size="small"
            column={1}
            bordered
            labelStyle={{ width: 130 }}
          >
            <Descriptions.Item label="ID">{data.id}</Descriptions.Item>
            <Descriptions.Item label="Status">
              {statusBadge(data.status)}
            </Descriptions.Item>
            <Descriptions.Item label="Backup ID">
              {data.backup_id || '—'}
            </Descriptions.Item>
            <Descriptions.Item label="Restored Cluster ID">
              {data.cluster_id || '—'}
            </Descriptions.Item>
            {data.cluster?.name && (
              <Descriptions.Item label="Restored Cluster Name">
                {data.cluster.name}
              </Descriptions.Item>
            )}
            {data.cluster?.status && (
              <Descriptions.Item label="Cluster Status">
                {data.cluster.status}
              </Descriptions.Item>
            )}
            <Descriptions.Item label="Created At">
              {formatTs(data.created_at)}
            </Descriptions.Item>
          </Descriptions>
        </Space>
      )}
    </Drawer>
  )
}

// ---- Tab 1: restore jobs for this cluster --------------------------------

function RestoreJobsTab() {
  const { clusterId } = useToolsPage()
  const [page, setPage] = useState(1)
  const [pageSize, setPageSize] = useState(20)
  const [openRestoreId, setOpenRestoreId] = useState<string | undefined>()
  const { data, isLoading, isError } = useListRestores(clusterId, {
    page,
    page_size: pageSize
  })

  const columns: ColumnsType<Restore> = [
    { title: 'ID', dataIndex: 'id', width: 80 },
    {
      title: 'Name',
      dataIndex: 'name',
      ellipsis: true,
      render: (v) => v || '—'
    },
    {
      title: 'Status',
      dataIndex: 'status',
      width: 110,
      render: (v) => statusBadge(v)
    },
    {
      title: 'Progress',
      dataIndex: 'progress_percent',
      width: 160,
      render: (v) => <Progress percent={v ?? 0} size="small" />
    },
    { title: 'Mode', dataIndex: 'mode', width: 90, render: (v) => v || '—' },
    {
      title: 'Source Backup',
      dataIndex: 'source_backup_name',
      width: 130,
      render: (v) => v || '—'
    },
    {
      title: 'Restore Region',
      dataIndex: 'restore_region',
      width: 120,
      render: (v) => v || '—'
    },
    {
      title: 'Restored At',
      dataIndex: 'restored_at',
      width: 170,
      render: (v) => (v ? formatTs(v) : '—')
    },
    {
      title: 'Started At',
      dataIndex: 'started_at',
      width: 170,
      render: (v) => formatTs(v)
    },
    {
      title: 'Finished At',
      dataIndex: 'finished_at',
      width: 170,
      render: (v) => (v ? formatTs(v) : '—')
    },
    {
      title: 'Action',
      key: 'action',
      render: (_, record) => (
        <Button
          type="link"
          size="small"
          style={{ padding: '0 4px' }}
          onClick={() => setOpenRestoreId(record.id)}
        >
          Detail
        </Button>
      )
    }
  ]

  return (
    <>
      {isError && <Alert type="error" message={strings.common.errorPanel} />}
      <Table<Restore>
        rowKey="id"
        size="small"
        loading={isLoading}
        dataSource={(data?.items || []) as Restore[]}
        columns={columns}
        pagination={{
          current: page,
          pageSize,
          total: data?.total || 0,
          pageSizeOptions: PAGE_SIZE_OPTS,
          showSizeChanger: true,
          onChange: (p, ps) => {
            setPage(p)
            setPageSize(ps || pageSize)
          }
        }}
      />
      <RestoreDetailDrawer
        open={!!openRestoreId}
        restoreId={openRestoreId}
        onClose={() => setOpenRestoreId(undefined)}
      />
    </>
  )
}

// ---- Tab 2: active restore progress (cluster-scoped) --------------------

function RestoreProgressTab({
  enabled,
  nextGen = false
}: {
  enabled: boolean
  nextGen?: boolean
}) {
  const { clusterId } = useToolsPage()
  const { data, isLoading, isError } = useGetCurrentRestoreProgress(
    clusterId,
    enabled
  )

  if (isLoading) {
    return (
      <div style={{ textAlign: 'center', padding: '24px 0' }}>
        <Spin />
      </div>
    )
  }

  if (isError) {
    return (
      <Alert
        type="error"
        message="Failed to load restore progress. Please try again later."
        style={{ margin: '16px 0' }}
      />
    )
  }

  // not_found:true means no active restore record exists for this cluster (200 response).
  if (!data || data.not_found) {
    return (
      <Empty
        description={
          nextGen
            ? 'No restore record is available for this instance'
            : 'No restore is currently in progress'
        }
        image={Empty.PRESENTED_IMAGE_SIMPLE}
      />
    )
  }

  if (!nextGen) {
    return (
      <Descriptions
        size="small"
        column={1}
        bordered
        labelStyle={{ width: 140 }}
      >
        {data.status && (
          <Descriptions.Item label="Stage">{data.status}</Descriptions.Item>
        )}
        <Descriptions.Item label="Progress">
          <Progress
            percent={data.progress_percent}
            size="small"
            style={{ marginBottom: 0 }}
          />
        </Descriptions.Item>
        {data.steps && data.steps.length > 0 && (
          <Descriptions.Item label="Steps">
            <Space direction="vertical" style={{ width: '100%' }}>
              {data.steps.map((s, i) => (
                <div key={i}>
                  <div style={{ marginBottom: 2, fontSize: 12 }}>
                    {s.step_name || `Step ${i + 1}`}
                  </div>
                  <Progress
                    percent={Math.round(s.progress ?? 0)}
                    size="small"
                    style={{ marginBottom: 0 }}
                  />
                </div>
              ))}
            </Space>
          </Descriptions.Item>
        )}
        {data.restore_bytes != null && data.restore_bytes > 0 && (
          <Descriptions.Item label="Bytes Restored">
            {formatBytes(data.restore_bytes)}
          </Descriptions.Item>
        )}
        {data.rate_bytes_per_sec != null && data.rate_bytes_per_sec > 0 && (
          <Descriptions.Item label="Rate">
            {formatBytes(data.rate_bytes_per_sec)}/s
          </Descriptions.Item>
        )}
        {data.eta_seconds != null && data.eta_seconds > 0 && (
          <Descriptions.Item label="ETA">
            {formatDuration(data.eta_seconds)}
          </Descriptions.Item>
        )}
        {data.updated_at != null && data.updated_at > 0 && (
          <Descriptions.Item label="Updated At">
            {formatTs(data.updated_at)}
          </Descriptions.Item>
        )}
        {data.error?.message && (
          <Descriptions.Item label="Error">
            {data.error.message}
          </Descriptions.Item>
        )}
        {data.error?.retryable !== undefined && (
          <Descriptions.Item label="Retryable">
            {data.error.retryable ? 'Yes' : 'No'}
          </Descriptions.Item>
        )}
      </Descriptions>
    )
  }

  const hasRuntimeDiagnostics = Boolean(
    data.data_restore_step ||
      data.data_restore_duration_seconds ||
      data.restore_bytes ||
      data.rate_bytes_per_sec ||
      (data.steps && data.steps.length > 0)
  )

  return (
    <Space direction="vertical" size={20} style={{ width: '100%' }}>
      <Descriptions
        title="Restore Status"
        size="small"
        column={2}
        bordered
        labelStyle={{ width: 170 }}
      >
        <Descriptions.Item label="Restore / Target ID">
          {data.id}
        </Descriptions.Item>
        <Descriptions.Item label="Stage">
          {data.status || '—'}
        </Descriptions.Item>
        <Descriptions.Item label="Progress" span={2}>
          <Progress
            percent={data.progress_percent}
            size="small"
            style={{ marginBottom: 0 }}
          />
        </Descriptions.Item>
        <Descriptions.Item label="Restore Started">
          {data.restore_started_at ? formatTs(data.restore_started_at) : '—'}
        </Descriptions.Item>
        <Descriptions.Item label="Restore Finished">
          {data.restore_finished_at ? formatTs(data.restore_finished_at) : '—'}
        </Descriptions.Item>
        <Descriptions.Item label="Elapsed">
          {data.duration_seconds ? formatDuration(data.duration_seconds) : '—'}
        </Descriptions.Item>
        <Descriptions.Item label="Last Updated">
          {data.updated_at ? formatTs(data.updated_at) : '—'}
        </Descriptions.Item>
        <Descriptions.Item label="Restore Mode">
          {data.audit?.restore_mode || '—'}
        </Descriptions.Item>
        <Descriptions.Item label="Point in Time">
          {data.audit?.point_in_time ? formatTs(data.audit.point_in_time) : '—'}
        </Descriptions.Item>
        <Descriptions.Item label="Restore Requested">
          {data.audit?.event_at ? formatTs(data.audit.event_at) : '—'}
        </Descriptions.Item>
        {data.message && (
          <Descriptions.Item label="Upstream Message" span={2}>
            {data.message}
          </Descriptions.Item>
        )}
        {data.error?.message && (
          <Descriptions.Item label="Error" span={2}>
            {data.error.message}
          </Descriptions.Item>
        )}
        {data.error?.retryable !== undefined && (
          <Descriptions.Item label="Retryable">
            {data.error.retryable ? 'Yes' : 'No'}
          </Descriptions.Item>
        )}
      </Descriptions>

      <div>
        <Descriptions
          title="Source and Backup"
          size="small"
          column={2}
          bordered
          labelStyle={{ width: 170 }}
        >
          <Descriptions.Item label="Source Instance ID">
            {data.source_cluster_id || 'Unavailable'}
          </Descriptions.Item>
          <Descriptions.Item label="Backup ID">
            {data.backup?.id || 'Unavailable'}
          </Descriptions.Item>
          <Descriptions.Item label="Backup Name">
            {data.backup?.name || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Backup TSO">
            {data.backup?.tso || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Backup Type">
            {data.backup?.type || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Backup Status">
            {data.backup?.status || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Backup Created">
            {data.backup?.created_at ? formatTs(data.backup.created_at) : '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Backup Finished">
            {data.backup?.finished_at ? formatTs(data.backup.finished_at) : '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Backup Size">
            {data.backup?.size_bytes
              ? formatBytes(data.backup.size_bytes)
              : '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Backup Region">
            {data.backup?.region || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Source Region">
            {data.source?.region || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Source Cloud Provider">
            {data.source?.cloud_provider || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Source Service Plan">
            {formatServicePlanDisplayName(data.source?.service_plan) || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Expected Restore Size">
            {data.source?.expected_restore_data_bytes
              ? formatBytes(data.source.expected_restore_data_bytes)
              : '—'}
          </Descriptions.Item>
        </Descriptions>
        {data.source_metadata_note && (
          <Alert
            type={data.source_metadata_available ? 'info' : 'warning'}
            showIcon
            message={
              data.source_metadata_available
                ? 'Some historical backup details are unavailable'
                : 'Source backup association is unavailable'
            }
            description={data.source_metadata_note}
            style={{ marginTop: 12 }}
          />
        )}
      </div>

      {data.target && (
        <Descriptions
          title="Target Instance"
          size="small"
          column={2}
          bordered
          labelStyle={{ width: 170 }}
        >
          <Descriptions.Item label="Instance ID">
            {data.target.id}
          </Descriptions.Item>
          <Descriptions.Item label="Instance Name">
            {data.target.name || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Instance State">
            {data.target.state || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Service Plan">
            {data.target.service_plan || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Region">
            {data.target.region_display || data.target.region || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Cloud Provider">
            {data.target.cloud_provider || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="TiDB Version">
            {data.target.tidb_version || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Created By">
            {data.target.creator || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Project ID">
            {data.target.project_id || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Organization ID">
            {data.target.organization_id || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Shared Pool ID">
            {data.target.shared_pool_id || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Data Plane ID">
            {data.target.dataplane_id || '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Provisioning Started">
            {data.target.create_started_at
              ? formatTs(data.target.create_started_at)
              : '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Instance Ready">
            {data.target.create_ready_at
              ? formatTs(data.target.create_ready_at)
              : '—'}
          </Descriptions.Item>
          <Descriptions.Item label="Instance Updated" span={2}>
            {data.target.updated_at ? formatTs(data.target.updated_at) : '—'}
          </Descriptions.Item>
        </Descriptions>
      )}

      {hasRuntimeDiagnostics ? (
        <Descriptions
          title="Data Restore Runtime"
          size="small"
          column={2}
          bordered
          labelStyle={{ width: 170 }}
        >
          {data.data_restore_step && (
            <Descriptions.Item label="Current Step">
              {data.data_restore_step}
            </Descriptions.Item>
          )}
          {!!data.data_restore_duration_seconds && (
            <Descriptions.Item label="Kernel Duration">
              {formatDuration(data.data_restore_duration_seconds)}
            </Descriptions.Item>
          )}
          {!!data.restore_bytes && (
            <Descriptions.Item label="Bytes Restored">
              {formatBytes(data.restore_bytes)}
            </Descriptions.Item>
          )}
          {!!data.rate_bytes_per_sec && (
            <Descriptions.Item label="Transfer Rate">
              {formatBytes(data.rate_bytes_per_sec)}/s
            </Descriptions.Item>
          )}
          {data.runtime_diagnostic && (
            <Descriptions.Item label="Runtime Diagnostic" span={2}>
              {data.runtime_diagnostic}
            </Descriptions.Item>
          )}
          {data.steps && data.steps.length > 0 && (
            <Descriptions.Item label="Steps" span={2}>
              <Space direction="vertical" style={{ width: '100%' }}>
                {data.steps.map((s, i) => (
                  <div key={i}>
                    <div style={{ marginBottom: 2, fontSize: 12 }}>
                      {s.step_name || `Step ${i + 1}`}
                    </div>
                    <Progress
                      percent={Math.round(s.progress ?? 0)}
                      size="small"
                      style={{ marginBottom: 0 }}
                    />
                  </div>
                ))}
              </Space>
            </Descriptions.Item>
          )}
        </Descriptions>
      ) : (
        <Alert
          type="info"
          showIcon
          message="Data restore runtime diagnostics are unavailable"
          description="The restore service did not report runtime diagnostics for this instance."
        />
      )}
    </Space>
  )
}

// ---- Panel ------------------------------------------------------------------

export default function RestorePanel() {
  const { cluster, deployType } = useToolsPage()
  const [activeTab, setActiveTab] = useState('jobs')
  if (isNextGenDeployType(deployType)) {
    const servicePlan = getDeployTypeDisplayName(
      deployType,
      cluster.service_plan
    )
    return (
      <Card
        title={`${servicePlan} Restore Status`}
        size="small"
        bordered={false}
      >
        <Alert
          type="info"
          showIcon
          message={`${servicePlan} restore creates a new TiDB instance. This view shows the restore status of the current instance; ${servicePlan} does not expose a Dedicated-style restore job history on the source instance.`}
          style={{ marginBottom: 16 }}
        />
        <RestoreProgressTab enabled nextGen />
      </Card>
    )
  }
  return (
    <Card size="small" bordered={false}>
      <Tabs activeKey={activeTab} onChange={setActiveTab}>
        <Tabs.TabPane tab="Restore from" key="jobs">
          <RestoreJobsTab />
        </Tabs.TabPane>
        <Tabs.TabPane tab="Restore into" key="progress">
          <RestoreProgressTab enabled={activeTab === 'progress'} />
        </Tabs.TabPane>
      </Tabs>
    </Card>
  )
}
