import {
  LoaderCircle,
  RefreshCcw,
  RotateCcw,
  Send,
  SquareTerminal,
  StopCircle,
  TimerReset,
  Workflow,
} from 'lucide-react'
import { startTransition, useCallback, useEffect, useMemo, useState } from 'react'
import { toast } from 'sonner'

import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Select } from '@/components/ui/select'
import { Skeleton } from '@/components/ui/skeleton'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { adminApi, ApiError } from '@/lib/api'
import type { WorkerJobRecord, WorkerOverview } from '@/lib/types'
import { cn } from '@/lib/utils'
import { useSearchParams } from 'react-router-dom'

function prettyJson(value: unknown) {
  if (value === null || value === undefined) {
    return '—'
  }

  try {
    return JSON.stringify(value, null, 2)
  } catch {
    return String(value)
  }
}

function statusVariant(status: string) {
  switch (status) {
    case 'succeeded':
      return 'success' as const
    case 'running':
      return 'default' as const
    case 'queued':
      return 'secondary' as const
    case 'failed':
      return 'danger' as const
    case 'cancelled':
      return 'warning' as const
    default:
      return 'outline' as const
  }
}

const EMPTY_OVERVIEW: WorkerOverview = {
  total_jobs: 0,
  queued: 0,
  running: 0,
  succeeded: 0,
  failed: 0,
  cancelled: 0,
  active_jobs: 0,
  worker_stats: [],
  catalog: [],
}

export function WorkersPage() {
  const [searchParams] = useSearchParams()
  const [overview, setOverview] = useState<WorkerOverview>(EMPTY_OVERVIEW)
  const [jobs, setJobs] = useState<WorkerJobRecord[]>([])
  const [total, setTotal] = useState(0)
  const [loading, setLoading] = useState(true)
  const [refreshing, setRefreshing] = useState(false)
  const [actioning, setActioning] = useState<string | null>(null)
  const [selectedJobId, setSelectedJobId] = useState<number | null>(null)
  const [statusFilter, setStatusFilter] = useState(searchParams.get('status') || 'all')
  const [kindFilter, setKindFilter] = useState(searchParams.get('kind') || 'all')
  const [workerFilter, setWorkerFilter] = useState(searchParams.get('worker') || 'all')
  const [search, setSearch] = useState(searchParams.get('search') || '')

  const requestedJobId = useMemo(() => {
    const raw = Number.parseInt(searchParams.get('job') || '', 10)
    return Number.isFinite(raw) ? raw : null
  }, [searchParams])

  useEffect(() => {
    setStatusFilter(searchParams.get('status') || 'all')
    setKindFilter(searchParams.get('kind') || 'all')
    setWorkerFilter(searchParams.get('worker') || 'all')
    setSearch(searchParams.get('search') || '')
  }, [searchParams])

  const loadData = useCallback(async (showToast = false) => {
    try {
      if (showToast) {
        setRefreshing(true)
      }
      const [nextOverview, nextJobs] = await Promise.all([
        adminApi.getWorkersOverview(),
        adminApi.listWorkerJobs({
          status: statusFilter === 'all' ? undefined : statusFilter,
          jobKind: kindFilter === 'all' ? undefined : kindFilter,
          workerName: workerFilter === 'all' ? undefined : workerFilter,
          search: search.trim() || undefined,
          limit: 120,
        }),
      ])
      let nextJobList = nextJobs.jobs
      if (requestedJobId && !nextJobList.some((item) => item.id === requestedJobId)) {
        try {
          const requestedJob = await adminApi.getWorkerJob(requestedJobId)
          nextJobList = [requestedJob, ...nextJobList]
        } catch {
          // ignore deep-link miss and keep current list
        }
      }
      startTransition(() => {
        setOverview(nextOverview)
        setJobs(nextJobList)
        setTotal(nextJobs.total)
      })
      if (showToast) {
        toast.success('Worker 管理面板已刷新。')
      }
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : '无法加载 worker 面板。')
    } finally {
      setLoading(false)
      setRefreshing(false)
    }
  }, [kindFilter, requestedJobId, search, statusFilter, workerFilter])

  useEffect(() => {
    void loadData(false)
  }, [loadData])

  useEffect(() => {
    const timer = window.setInterval(() => {
      void loadData(false)
    }, 5000)

    return () => window.clearInterval(timer)
  }, [loadData])

  useEffect(() => {
    setSelectedJobId((current) => {
      if (requestedJobId) {
        return requestedJobId
      }
      if (current && jobs.some((item) => item.id === current)) {
        return current
      }
      return jobs[0]?.id ?? null
    })
  }, [jobs, requestedJobId])

  const selectedJob = useMemo(
    () => jobs.find((item) => item.id === selectedJobId) ?? null,
    [jobs, selectedJobId],
  )

  const runTask = useCallback(async (task: 'weekly' | 'monthly' | 'retry') => {
    try {
      setActioning(task)
      const result =
        task === 'retry'
          ? await adminApi.runRetryDeliveriesWorker(80)
          : await adminApi.runDigestWorker(task)
      toast.success(`已入队：#${result.job.id} ${result.job.display_name ?? result.job.worker_name}`)
      await loadData(false)
      setSelectedJobId(result.job.id)
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : '任务入队失败。')
    } finally {
      setActioning(null)
    }
  }, [loadData])

  const workerOptions = overview.catalog.map((item) => ({
    value: item.worker_name,
    label: item.label,
  }))

  if (loading) {
    return (
      <div className="space-y-6">
        <Skeleton className="h-40 rounded-3xl" />
        <Skeleton className="h-[760px] rounded-3xl" />
      </div>
    )
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-4 xl:flex-row xl:items-end xl:justify-between">
        <div className="space-y-3">
          <Badge variant="secondary">Workers / Queue</Badge>
          <div>
            <h2 className="text-3xl font-semibold tracking-tight">异步 Worker 控制台</h2>
            <p className="mt-2 max-w-3xl text-sm leading-7 text-muted-foreground">
              统一查看后台下载、通知投递与 digest / 重试任务；支持筛选、查看详情、取消、重跑与手动触发。
            </p>
          </div>
        </div>

        <div className="flex flex-wrap items-center gap-3">
          <Button variant="outline" onClick={() => void loadData(true)} disabled={refreshing}>
            <RefreshCcw className="h-4 w-4" />
            {refreshing ? '刷新中...' : '刷新'}
          </Button>
          <Button
            variant="secondary"
            data-testid="workers-run-weekly"
            disabled={actioning !== null}
            onClick={() => void runTask('weekly')}
          >
            <Send className="h-4 w-4" />
            {actioning === 'weekly' ? '入队中...' : '发送周报'}
          </Button>
          <Button
            data-testid="workers-run-monthly"
            disabled={actioning !== null}
            onClick={() => void runTask('monthly')}
          >
            <Workflow className="h-4 w-4" />
            {actioning === 'monthly' ? '入队中...' : '发送月报'}
          </Button>
          <Button
            variant="outline"
            data-testid="workers-run-retry"
            disabled={actioning !== null}
            onClick={() => void runTask('retry')}
          >
            <TimerReset className="h-4 w-4" />
            {actioning === 'retry' ? '处理中...' : '重试待投递'}
          </Button>
        </div>
      </div>

      <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-6">
        {[
          { label: '总任务', value: overview.total_jobs, hint: `${overview.worker_stats.length} 种 worker`, icon: SquareTerminal },
          { label: '排队中', value: overview.queued, hint: 'queued', icon: LoaderCircle },
          { label: '运行中', value: overview.running, hint: 'running', icon: Workflow },
          { label: '成功', value: overview.succeeded, hint: 'succeeded', icon: Send },
          { label: '失败', value: overview.failed, hint: 'failed', icon: RotateCcw },
          { label: '已取消', value: overview.cancelled, hint: 'cancelled', icon: StopCircle },
        ].map((item) => {
          const Icon = item.icon
          return (
            <Card key={item.label}>
              <CardContent className="flex items-center justify-between gap-4 p-5">
                <div>
                  <div className="text-xs uppercase tracking-[0.22em] text-muted-foreground">{item.label}</div>
                  <div className="mt-2 text-3xl font-semibold tracking-tight">{item.value}</div>
                  <div className="mt-1 text-xs text-muted-foreground">{item.hint}</div>
                </div>
                <div className="rounded-2xl border border-primary/20 bg-primary/10 p-3 text-primary">
                  <Icon className="h-5 w-5" />
                </div>
              </CardContent>
            </Card>
          )
        })}
      </div>

      <Card>
        <CardHeader>
          <CardTitle>Worker 分类视图</CardTitle>
          <CardDescription>快速看每类 worker / task 当前堆积、失败与最近执行情况。</CardDescription>
        </CardHeader>
        <CardContent className="grid gap-4 lg:grid-cols-2 2xl:grid-cols-3">
          {overview.worker_stats.map((item) => (
            <button
              key={item.worker_name}
              type="button"
              className={cn(
                'rounded-3xl border border-border/70 bg-background/50 p-4 text-left transition hover:border-primary/30 hover:bg-primary/5',
                workerFilter === item.worker_name && 'border-primary/40 bg-primary/10',
              )}
              onClick={() => setWorkerFilter((current) => (current === item.worker_name ? 'all' : item.worker_name))}
            >
              <div className="flex items-center justify-between gap-3">
                <div>
                  <div className="text-sm font-medium text-foreground">{item.label}</div>
                  <div className="mt-1 text-xs text-muted-foreground">{item.worker_name}</div>
                </div>
                <Badge variant="outline">{item.job_kind}</Badge>
              </div>
              <div className="mt-4 grid grid-cols-5 gap-2 text-center text-xs">
                {[
                  ['Q', item.queued],
                  ['R', item.running],
                  ['OK', item.succeeded],
                  ['ERR', item.failed],
                  ['X', item.cancelled],
                ].map(([label, value]) => (
                  <div key={String(label)} className="rounded-2xl border border-border/70 px-2 py-2">
                    <div className="text-[10px] uppercase tracking-[0.18em] text-muted-foreground">{label}</div>
                    <div className="mt-1 text-base font-semibold text-foreground">{value}</div>
                  </div>
                ))}
              </div>
              <div className="mt-3 text-xs text-muted-foreground">
                最近任务：{item.last_job_at ?? '—'}
              </div>
            </button>
          ))}
        </CardContent>
      </Card>

      <div className="grid gap-6 xl:grid-cols-[1.4fr_0.9fr]">
        <Card>
          <CardHeader>
            <CardTitle>任务历史</CardTitle>
            <CardDescription>当前筛选后共 {total} 条，列表保留最近 120 条任务记录。</CardDescription>
          </CardHeader>
          <CardContent className="space-y-4">
            <div className="grid gap-3 lg:grid-cols-[180px_180px_220px_1fr]">
              <Select value={statusFilter} onChange={(event) => setStatusFilter(event.target.value)}>
                <option value="all">全部状态</option>
                <option value="queued">queued</option>
                <option value="running">running</option>
                <option value="succeeded">succeeded</option>
                <option value="failed">failed</option>
                <option value="cancelled">cancelled</option>
              </Select>
              <Select value={kindFilter} onChange={(event) => setKindFilter(event.target.value)}>
                <option value="all">全部类型</option>
                <option value="worker">worker</option>
                <option value="task">task</option>
              </Select>
              <Select value={workerFilter} onChange={(event) => setWorkerFilter(event.target.value)}>
                <option value="all">全部 worker</option>
                {workerOptions.map((item) => (
                  <option key={item.value} value={item.value}>
                    {item.label}
                  </option>
                ))}
              </Select>
              <Input
                data-testid="workers-search"
                placeholder="按 worker / display / entity 搜索"
                value={search}
                onChange={(event) => setSearch(event.target.value)}
              />
            </div>

            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>ID</TableHead>
                  <TableHead>任务</TableHead>
                  <TableHead>状态</TableHead>
                  <TableHead>来源</TableHead>
                  <TableHead>实体</TableHead>
                  <TableHead>时间</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {jobs.map((item) => (
                  <TableRow
                    key={item.id}
                    data-testid={`worker-job-row-${item.id}`}
                    className={cn(
                      'cursor-pointer',
                      selectedJobId === item.id && 'bg-primary/5',
                    )}
                    onClick={() => setSelectedJobId(item.id)}
                  >
                    <TableCell className="font-mono text-xs">#{item.id}</TableCell>
                    <TableCell>
                      <div className="space-y-1">
                        <div className="font-medium text-foreground">{item.display_name ?? item.worker_name}</div>
                        <div className="text-xs text-muted-foreground">{item.worker_name}</div>
                      </div>
                    </TableCell>
                    <TableCell>
                      <div className="space-y-2">
                        <Badge variant={statusVariant(item.status)}>{item.status}</Badge>
                        {item.cancel_requested ? <div className="text-[11px] text-amber-600">cancel requested</div> : null}
                      </div>
                    </TableCell>
                    <TableCell>
                      <div className="space-y-1 text-xs text-muted-foreground">
                        <div>{item.job_kind}</div>
                        <div>{item.requested_by ?? 'system'}</div>
                      </div>
                    </TableCell>
                    <TableCell className="text-xs text-muted-foreground">
                      {item.related_entity_type && item.related_entity_id
                        ? `${item.related_entity_type}:${item.related_entity_id}`
                        : '—'}
                    </TableCell>
                    <TableCell className="text-xs text-muted-foreground">
                      <div>{item.queued_at ?? item.created_at}</div>
                      <div>done: {item.finished_at ?? '—'}</div>
                    </TableCell>
                  </TableRow>
                ))}
                {!jobs.length ? (
                  <TableRow>
                    <TableCell colSpan={6} className="py-10 text-center text-sm text-muted-foreground">
                      当前筛选没有匹配任务。
                    </TableCell>
                  </TableRow>
                ) : null}
              </TableBody>
            </Table>
          </CardContent>
        </Card>

        <Card>
          <CardHeader>
            <CardTitle>任务详情</CardTitle>
            <CardDescription>查看 payload / result / error，并对单个任务执行取消或重跑。</CardDescription>
          </CardHeader>
          <CardContent>
            {selectedJob ? (
              <div className="space-y-4">
                <div className="flex flex-wrap items-center gap-2">
                  <Badge variant="outline">#{selectedJob.id}</Badge>
                  <Badge variant={statusVariant(selectedJob.status)}>{selectedJob.status}</Badge>
                  <Badge variant="secondary">{selectedJob.job_kind}</Badge>
                </div>

                <div>
                  <h3 className="text-xl font-semibold tracking-tight text-foreground">
                    {selectedJob.display_name ?? selectedJob.worker_name}
                  </h3>
                  <p className="mt-2 text-sm leading-6 text-muted-foreground">{selectedJob.worker_name}</p>
                </div>

                <div className="grid gap-3 sm:grid-cols-2">
                  {[
                    ['请求人', selectedJob.requested_by ?? 'system'],
                    ['来源', selectedJob.requested_source ?? 'system'],
                    ['关联实体', selectedJob.related_entity_type && selectedJob.related_entity_id ? `${selectedJob.related_entity_type}:${selectedJob.related_entity_id}` : '—'],
                    ['尝试次数', `${selectedJob.attempts_count} / ${selectedJob.max_attempts}`],
                    ['排队时间', selectedJob.queued_at ?? selectedJob.created_at],
                    ['开始时间', selectedJob.started_at ?? '—'],
                    ['完成时间', selectedJob.finished_at ?? '—'],
                    ['上游任务', selectedJob.parent_job_id ? `#${selectedJob.parent_job_id}` : '—'],
                  ].map(([label, value]) => (
                    <div key={String(label)} className="rounded-2xl border border-border/70 bg-background/50 px-4 py-3">
                      <div className="text-[11px] uppercase tracking-[0.2em] text-muted-foreground">{label}</div>
                      <div className="mt-2 text-sm text-foreground break-all">{value}</div>
                    </div>
                  ))}
                </div>

                <div className="flex flex-wrap gap-3">
                  <Button
                    variant="outline"
                    disabled={!selectedJob.can_cancel || actioning === `cancel-${selectedJob.id}`}
                    data-testid="workers-cancel-job"
                    onClick={async () => {
                      try {
                        setActioning(`cancel-${selectedJob.id}`)
                        const result = await adminApi.cancelWorkerJob(selectedJob.id)
                        toast.success(`任务 #${result.id} 已标记取消。`)
                        await loadData(false)
                      } catch (error) {
                        toast.error(error instanceof ApiError ? error.message : '取消任务失败。')
                      } finally {
                        setActioning(null)
                      }
                    }}
                  >
                    <StopCircle className="h-4 w-4" />
                    {actioning === `cancel-${selectedJob.id}` ? '取消中...' : '取消任务'}
                  </Button>
                  <Button
                    disabled={!selectedJob.can_retry || actioning === `retry-${selectedJob.id}`}
                    data-testid="workers-retry-job"
                    onClick={async () => {
                      try {
                        setActioning(`retry-${selectedJob.id}`)
                        const result = await adminApi.retryWorkerJob(selectedJob.id)
                        toast.success(`已重跑，新的任务 #${result.job.id}`)
                        await loadData(false)
                        setSelectedJobId(result.job.id)
                      } catch (error) {
                        toast.error(error instanceof ApiError ? error.message : '重跑任务失败。')
                      } finally {
                        setActioning(null)
                      }
                    }}
                  >
                    <RotateCcw className="h-4 w-4" />
                    {actioning === `retry-${selectedJob.id}` ? '重跑中...' : '重跑任务'}
                  </Button>
                </div>

                <div className="space-y-3">
                  <div>
                    <div className="mb-2 text-sm font-medium text-foreground">Payload</div>
                    <pre className="overflow-x-auto rounded-3xl border border-border/70 bg-background/60 p-4 text-xs leading-6 text-muted-foreground">{prettyJson(selectedJob.payload)}</pre>
                  </div>

                  <div>
                    <div className="mb-2 text-sm font-medium text-foreground">Result</div>
                    <pre className="overflow-x-auto rounded-3xl border border-border/70 bg-background/60 p-4 text-xs leading-6 text-muted-foreground">{prettyJson(selectedJob.result)}</pre>
                  </div>

                  <div>
                    <div className="mb-2 text-sm font-medium text-foreground">Error</div>
                    <pre className="overflow-x-auto rounded-3xl border border-border/70 bg-background/60 p-4 text-xs leading-6 text-muted-foreground">{selectedJob.error_text ?? '—'}</pre>
                  </div>
                </div>
              </div>
            ) : (
              <div className="rounded-3xl border border-dashed border-border/70 bg-background/50 px-5 py-10 text-center text-sm text-muted-foreground">
                暂无可查看的任务详情。
              </div>
            )}
          </CardContent>
        </Card>
      </div>
    </div>
  )
}
