import { ArrowLeftOutlined, ReloadOutlined, StopOutlined, ApiOutlined } from '@ant-design/icons'
import { Alert, Button, Card, Descriptions, Space, Tag, Tabs, Typography, Popconfirm, message } from 'antd'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import type { ApiError } from '../lib/api'
import JsonViewer from '../components/JsonViewer'
import { getTask, getTaskResult, retryTask, cancelTask, markTaskRpa, type TaskRecord, type TaskResultResponse } from '../lib/tasks'

export default function TaskDetailPage() {
  const navigate = useNavigate()
  const params = useParams<{ id: string }>()
  const id = useMemo(() => params.id ?? '', [params.id])

  const [task, setTask] = useState<TaskRecord | null>(null)
  const [result, setResult] = useState<TaskResultResponse | null>(null)
  const [notReadyBody, setNotReadyBody] = useState<unknown>(null)
  const [loading, setLoading] = useState(false)
  const [polling, setPolling] = useState(false)
  const [error, setError] = useState<ApiError | null>(null)
  const controllerRef = useRef<AbortController | null>(null)

  const [actionLoading, setActionLoading] = useState(false)

  const refresh = useCallback(async () => {
    if (!id) return
    setLoading(true)
    setError(null)
    try {
      const taskRes = await getTask(id)
      setTask(taskRes)
    } catch (e) {
      setError(e as ApiError)
    } finally {
      setLoading(false)
    }
  }, [id])

  const handleRetry = async () => {
    if (!id) return
    setActionLoading(true)
    try {
      await retryTask(id)
      message.success('任务已重新排队')
      await refresh()
      startPolling()
    } catch (e) {
      message.error(`重试失败: ${(e as ApiError).message}`)
    } finally {
      setActionLoading(false)
    }
  }

  const handleCancel = async () => {
    if (!id) return
    setActionLoading(true)
    try {
      await cancelTask(id)
      message.success('任务已取消')
      await refresh()
      stopPolling()
    } catch (e) {
      message.error(`取消失败: ${(e as ApiError).message}`)
    } finally {
      setActionLoading(false)
    }
  }

  const handleMarkRpa = async () => {
    if (!id) return
    setActionLoading(true)
    try {
      await markTaskRpa(id)
      message.success('已转为等待 RPA')
      await refresh()
      stopPolling()
    } catch (e) {
      message.error(`转 RPA 失败: ${(e as ApiError).message}`)
    } finally {
      setActionLoading(false)
    }
  }

  useEffect(() => {
    void refresh()
  }, [refresh])

  function stopPolling() {
    controllerRef.current?.abort()
    controllerRef.current = null
    setPolling(false)
  }

  async function sleep(ms: number, signal?: AbortSignal) {
    await new Promise<void>((resolve, reject) => {
      const timer = window.setTimeout(() => {
        signal?.removeEventListener('abort', onAbort)
        resolve()
      }, ms)

      function onAbort() {
        window.clearTimeout(timer)
        reject(new DOMException('Aborted', 'AbortError'))
      }

      if (signal) {
        if (signal.aborted) return onAbort()
        signal.addEventListener('abort', onAbort, { once: true })
      }
    })
  }

  const startPolling = useCallback(async () => {
    if (!id) return
    stopPolling()

    setPolling(true)
    setError(null)
    setResult(null)
    setNotReadyBody(null)

    const controller = new AbortController()
    controllerRef.current = controller
    const signal = controller.signal

    try {
      while (true) {
        const res = await getTaskResult(id, signal)
        if (res.ready) {
          setResult(res.data)
          setNotReadyBody(null)
          setPolling(false)
          controllerRef.current = null
          return
        }

        setNotReadyBody(res.body)
        await sleep(1500, signal)
      }
    } catch (e) {
      if (e instanceof DOMException && e.name === 'AbortError') return
      setError(e as ApiError)
      setPolling(false)
      controllerRef.current = null
    }
  }, [id])

  useEffect(() => {
    if (!id) return undefined
    void startPolling()
    return () => stopPolling()
  }, [id, startPolling])

  function formatTs(value: number | null | undefined) {
    if (!value) return '-'
    const d = new Date(value * 1000)
    return Number.isFinite(d.getTime()) ? d.toLocaleString() : '-'
  }

  return (
    <div style={{ display: 'grid', gap: 16 }}>
      <Space>
        <Button icon={<ArrowLeftOutlined />} onClick={() => navigate('/tasks')}>
          返回
        </Button>
        <Typography.Title level={3} style={{ margin: 0 }}>
          Task: {id}
        </Typography.Title>
      </Space>

      {error ? (
        <Alert
          type="error"
          showIcon
          message={error.status ? `HTTP ${error.status}` : '请求失败'}
          description={error.message}
        />
      ) : null}

      <Card
        title="任务信息"
        loading={loading}
        extra={
          <Space>
            <Button onClick={refresh} disabled={loading || actionLoading}>
              刷新
            </Button>
            <Button type="primary" onClick={startPolling} loading={polling} disabled={actionLoading}>
              重新轮询结果
            </Button>
            <Button onClick={stopPolling} disabled={!polling || actionLoading}>
              停止轮询
            </Button>
            {task?.status === 'failed' && (
              <Popconfirm title="确定要重试此任务吗？" onConfirm={handleRetry}>
                <Button icon={<ReloadOutlined />} loading={actionLoading}>重试任务</Button>
              </Popconfirm>
            )}
            {task?.status === 'failed' && (
              <Popconfirm title="确定转为等待 RPA 吗？" onConfirm={handleMarkRpa}>
                <Button icon={<ApiOutlined />} loading={actionLoading}>转为 RPA</Button>
              </Popconfirm>
            )}
            {(task?.status === 'queued' || task?.status === 'running' || task?.status === 'retrying' || task?.status === 'fallback_running') && (
              <Popconfirm title="确定要取消此任务吗？" onConfirm={handleCancel}>
                <Button danger icon={<StopOutlined />} loading={actionLoading}>取消任务</Button>
              </Popconfirm>
            )}
          </Space>
        }
      >
        {task ? (
          <div style={{ display: 'grid', gap: 16 }}>
            <Descriptions column={2} size="small">
              <Descriptions.Item label="id">{task.id}</Descriptions.Item>
              <Descriptions.Item label="status">
                <Tag>{task.status}</Tag>
              </Descriptions.Item>
              <Descriptions.Item label="task_type">{task.task_type}</Descriptions.Item>
              <Descriptions.Item label="engine">{task.engine || '-'}</Descriptions.Item>
              <Descriptions.Item label="target" span={2}>
                {task.target || '-'}
              </Descriptions.Item>
              <Descriptions.Item label="created">{formatTs(task.created)}</Descriptions.Item>
              <Descriptions.Item label="started">{formatTs(task.started)}</Descriptions.Item>
              <Descriptions.Item label="finished">{formatTs(task.finished)}</Descriptions.Item>
              <Descriptions.Item label="retry_count">{task.retry_count}</Descriptions.Item>
            </Descriptions>

            <div style={{ display: 'grid', gap: 8 }}>
              <Typography.Text strong>payload</Typography.Text>
              <JsonViewer value={task.payload} height={260} />
            </div>

            <div style={{ display: 'grid', gap: 8 }}>
              <Typography.Text strong>error</Typography.Text>
              <JsonViewer value={task.error ?? null} height={220} />
            </div>
          </div>
        ) : (
          <Typography.Text type="secondary">无数据</Typography.Text>
        )}
      </Card>

      <Card
        title="任务结果"
        extra={
          <Space>
            {polling ? <Tag color="processing">轮询中</Tag> : null}
            {!polling && result ? <Tag color="success">已就绪</Tag> : null}
            {!polling && !result && notReadyBody ? <Tag color="default">未就绪</Tag> : null}
          </Space>
        }
      >
        {notReadyBody ? (
          <div style={{ display: 'grid', gap: 12 }}>
            <Alert type="info" showIcon message="未就绪，继续轮询中" />
            <JsonViewer value={notReadyBody} height={220} defaultExpandAll={false} />
          </div>
        ) : null}

        {result ? (
          <Tabs
            items={[
              {
                key: 'raw',
                label: 'raw',
                children: <JsonViewer value={result.raw} height={360} />,
              },
              {
                key: 'normalized',
                label: 'normalized',
                children: <JsonViewer value={result.normalized} height={360} />,
              },
              {
                key: 'meta',
                label: 'meta',
                children: <JsonViewer value={result.meta} height={360} />,
              },
            ]}
          />
        ) : null}

        {!result && !notReadyBody ? <Typography.Text type="secondary">暂无</Typography.Text> : null}
      </Card>
    </div>
  )
}
