import { useEffect, useMemo, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import {
  Alert, Button, Empty, message, Progress, Select, Space, Tabs, Tooltip, Typography,
} from 'antd'
import {
  FileTextOutlined, PlayCircleOutlined, ReloadOutlined, StopOutlined,
} from '@ant-design/icons'
import { reportsApi, runsApi, scenariosApi, targetsApi, type Run, type Scenario, type Target } from '../api'
import RunList from '../components/RunList'
import CaseBlock from '../components/CaseBlock'
import RuleOverview from '../components/RuleOverview'
import CaseDetail from '../components/CaseDetail'
import { useRunSession } from '../hooks/useRunSession'
import { useTicker } from '../hooks/useTicker'
import { useOnTabActive } from '../hooks/useOnTabActive'
import { colors, statusColors, statusLabels } from '../tokens'
import { formatDateTime, elapsedStr } from '../utils/date'
import { passRateColor } from '../utils/colors'

export default function RunsPage() {
  const navigate = useNavigate()

  const [runs, setRuns] = useState<Run[]>([])
  const [targets, setTargets] = useState<Target[]>([])
  const [scenarios, setScenarios] = useState<Scenario[]>([])
  const [loading, setLoading] = useState(true)
  const [targetId, setTargetId] = useState<string>()
  const [scenarioId, setScenarioId] = useState<string>()
  const [starting, setStarting] = useState(false)
  const [tabKey, setTabKey] = useState<string | null>(null)
  const [tabOverrideId, setTabOverrideId] = useState<string | null>(null)
  const [focusCaseId, setFocusCaseId] = useState<string | null>(null)

  const session = useRunSession()

  const loadLists = async () => {
    setLoading(true)
    try {
      const [r, t, s] = await Promise.all([
        runsApi.list(),
        targetsApi.list(),
        scenariosApi.list(),
      ])
      // API 已按 started_at DESC 排序，直接使用，最新的在前
      setRuns(r.data)
      setTargets(t.data)
      setScenarios(s.data)
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => { loadLists() }, [])

  // Keep-alive tabs never remount: refresh the list whenever the tab is
  // re-activated so runs triggered elsewhere (e.g. AI assistant) show up.
  useOnTabActive('/runs', loadLists)

  useEffect(() => {
    if (!session.isLive) return
    const id = window.setInterval(() => {
      runsApi.list().then((r) => setRuns(r.data)).catch(() => {})
    }, 3000)
    return () => window.clearInterval(id)
  }, [session.isLive])

  useEffect(() => {
    if (session.completed) {
      runsApi.list().then((r) => setRuns(r.data)).catch(() => {})
    }
  }, [session.completed])

  // 提取为共享函数，handleStart 和 onRerun 共用
  const startRun = async (tId: string, sId: string) => {
    setStarting(true)
    try {
      const res = await runsApi.start(tId, sId)
      await loadLists()
      session.select(res.data, { live: true })
      setTabOverrideId(null)
      setFocusCaseId(null)
    } finally {
      setStarting(false)
    }
  }

  const handleStart = async () => {
    if (!targetId || !scenarioId) {
      message.warning('请选择评测对象和场景')
      return
    }
    await startRun(targetId, scenarioId)
    message.success('评测已启动')
  }

  const handleSelect = (r: Run) => {
    session.select(r)
    setTabOverrideId(null)
    setFocusCaseId(null)
  }

  const handleOpenReport = (runId: string) => {
    navigate(`/reports?run=${runId}`)
  }

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
      {/* 页头 */}
      <div style={{ padding: '10px 16px 8px', flexShrink: 0, display: 'flex', alignItems: 'center', gap: 12 }}>
        <h2 style={{ margin: 0, fontSize: 20, fontWeight: 600, color: colors.text }}>评测执行</h2>
        <span style={{ width: 1, height: 18, background: '#d9d9d9', display: 'inline-block' }} />
        <span style={{ fontSize: 13, color: colors.textSecondary }}>启动评测任务并查看实时执行详情</span>
      </div>

      {/* 主体 grid — 贴边铺满 */}
      <div style={{ flex: 1, minHeight: 0 }}>
        <div style={{
          display: 'grid',
          gridTemplateColumns: 'minmax(360px, 28vw) 1fr',
          gridTemplateRows: '1fr',
          gap: 0,
          height: '100%',
          minHeight: 480,
        }}>
        {/* LEFT: launcher + list */}
        <div style={{
          display: 'flex',
          flexDirection: 'column',
          borderRight: `1px solid ${colors.border}`,
          background: '#fff',
          minHeight: 0,
          overflow: 'hidden',
        }}>
          {/* 启动区：两行布局 */}
          <div style={{
            padding: '12px 12px 10px',
            borderBottom: `1px solid ${colors.border}`,
            background: colors.bgSubtle,
            flexShrink: 0,
            display: 'flex',
            flexDirection: 'column',
            gap: 8,
          }}>
            <Select
              value={targetId}
              onChange={setTargetId}
              allowClear
              showSearch
              filterOption={(input, opt) =>
                (opt?.label as string ?? '').toLowerCase().includes(input.toLowerCase())}
              placeholder="选择评测对象"
              options={targets.map((t) => ({ label: t.name, value: t.id }))}
              style={{ width: '100%' }}
              size="middle"
            />
            <div style={{ display: 'flex', gap: 8 }}>
              <Select
                value={scenarioId}
                onChange={setScenarioId}
                allowClear
                showSearch
                filterOption={(input, opt) =>
                  (opt?.label as string ?? '').toLowerCase().includes(input.toLowerCase())}
                placeholder="选择评测场景"
                options={scenarios.map((s) => ({ label: `${s.name}（v${s.version ?? 1}）`, value: s.id }))}
                style={{ flex: 1 }}
                size="middle"
              />
              <Button
                type="primary"
                icon={<PlayCircleOutlined />}
                onClick={handleStart}
                loading={starting}
              >
                启动
              </Button>
            </div>
          </div>

          <div style={{ flex: 1, minHeight: 0 }}>
            <RunList
              runs={runs}
              loading={loading}
              targets={targets}
              scenarios={scenarios}
              selectedId={session.run?.id}
              onSelect={handleSelect}
              onOpenReport={handleOpenReport}
              liveRunId={session.isLive ? session.run?.id : undefined}
              liveProgress={session.isLive ? session.progress : null}
            />
          </div>
        </div>

        {/* RIGHT: detail workspace */}
        <div style={{
          display: 'flex',
          flexDirection: 'column',
          background: '#fff',
          minHeight: 0,
          overflow: 'hidden',
        }}>
          <DetailWorkspace
            run={session.run}
            cases={session.cases}
            progress={session.progress}
            snapshots={session.scenarioSnapshot}
            isLive={session.isLive}
            finalStatus={session.finalStatus}
            errorInfo={session.errorInfo}
            tabKey={tabKey}
            tabOverrideId={tabOverrideId}
            onTabChange={(k) => {
              setTabKey(k)
              setTabOverrideId(session.run?.id ?? null)
            }}
            focusCaseId={focusCaseId}
            onFocusCase={(id) => { setFocusCaseId(id); setTabKey('detail'); setTabOverrideId(session.run?.id ?? null) }}
            onCancel={async () => {
              try {
                await session.cancel()
                message.success('已发送停止请求')
              } catch {
                message.error('停止失败')
              }
            }}
            onOpenReport={handleOpenReport}
            onExportJson={(runId) => reportsApi.download(runId, 'json')}
            onRerun={async () => {
              if (!session.run) return
              await startRun(session.run.target_id, session.run.scenario_id)
              message.success('已重新启动')
            }}
          />
        </div>
      </div>
      </div>
    </div>
  )
}

// ─── Detail Workspace ─────────────────────────────────────────────────────────

interface DetailWorkspaceProps {
  run: Run | null
  cases: ReturnType<typeof useRunSession>['cases']
  progress: ReturnType<typeof useRunSession>['progress']
  snapshots: ReturnType<typeof useRunSession>['scenarioSnapshot']
  isLive: boolean
  finalStatus: ReturnType<typeof useRunSession>['finalStatus']
  errorInfo: ReturnType<typeof useRunSession>['errorInfo']
  tabKey: string | null
  tabOverrideId: string | null
  onTabChange: (k: string) => void
  focusCaseId: string | null
  onFocusCase: (id: string) => void
  onCancel: () => void
  onOpenReport: (runId: string) => void
  onExportJson: (runId: string) => void
  onRerun: () => void
}

function DetailWorkspace({
  run, cases, progress, snapshots, isLive, finalStatus, errorInfo,
  tabKey, tabOverrideId, onTabChange, focusCaseId, onFocusCase,
  onCancel, onOpenReport, onExportJson, onRerun,
}: DetailWorkspaceProps) {
  useTicker(isLive)

  const status = run?.status ?? 'pending'
  const autoTab = useMemo(() => {
    if (isLive) return 'log'
    if (status === 'completed') return 'overview'
    if (status === 'failed') return 'detail'
    return 'log'
  }, [isLive, status])

  if (!run) {
    return (
      <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <Empty
          image={Empty.PRESENTED_IMAGE_SIMPLE}
          description={<span style={{ color: colors.textMuted }}>选择左侧记录或启动新评测</span>}
        />
      </div>
    )
  }

  const summary = (run.summary || {}) as Record<string, unknown>
  const passRate = summary.pass_rate as number | undefined
  const totalCases = summary.total_cases as number | undefined
  const passedCases = summary.passed_cases as number | undefined
  const totalRules = summary.total_rules as number | undefined
  const passedRules = summary.passed_rules as number | undefined

  const activeKey = tabOverrideId === run.id && tabKey ? tabKey : autoTab

  const finalAlert = (() => {
    if (finalStatus === 'completed') return <Alert type="success" showIcon message="评测完成" style={{ padding: '4px 12px' }} />
    if (finalStatus === 'cancelled') return <Alert type="warning" showIcon message={errorInfo?.message || '评测已手动停止'} style={{ padding: '4px 12px' }} />
    if (finalStatus === 'failed') return <Alert type="error" showIcon message={`评测失败：${errorInfo?.message ?? '未知原因'}`} style={{ padding: '4px 12px' }} />
    return null
  })()

  return (
    <>
      {/* KPI bar */}
      <div style={{
        padding: '12px 16px',
        borderBottom: `1px solid ${colors.border}`,
        background: colors.bgSubtle,
        flexShrink: 0,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 20, flexWrap: 'wrap' }}>
          <StatusBadge status={status} finalStatus={finalStatus} />

          <KpiItem
            label="通过率"
            value={passRate != null ? `${Math.round(passRate * 100)}%` : '-'}
            valueColor={passRate != null ? passRateColor(passRate) : colors.textMuted}
            subtitle={
              passedCases != null && totalCases != null
                ? `${passedCases}/${totalCases} 用例通过 · ${passedRules ?? 0}/${totalRules ?? 0} 规则通过`
                : '等待评测结果'
            }
          />

          <KpiItem
            label={isLive ? '已运行' : '用时'}
            value={elapsedStr(run.started_at, run.completed_at)}
            subtitle={`${formatDateTime(run.started_at)}${run.completed_at ? ' → ' + formatDateTime(run.completed_at) : ''}`}
          />

          <div style={{ marginLeft: 'auto', display: 'flex', gap: 8, alignItems: 'center' }}>
            <Tooltip title={run.id}>
              <Typography.Text code copyable={{ text: run.id }} style={{ fontSize: 11 }}>
                {run.id.slice(0, 8)}…
              </Typography.Text>
            </Tooltip>
            {isLive ? (
              <Button danger size="small" icon={<StopOutlined />} onClick={onCancel}>停止</Button>
            ) : (
              <Space size={4}>
                <Button size="small" icon={<ReloadOutlined />} onClick={onRerun}>重跑</Button>
                {status === 'completed' && (
                  <>
                    <Button size="small" icon={<FileTextOutlined />} onClick={() => onOpenReport(run.id)}>报告</Button>
                    <Button size="small" onClick={() => onExportJson(run.id)}>导出</Button>
                  </>
                )}
              </Space>
            )}
          </div>
        </div>

        {progress && progress.total > 0 && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 8 }}>
            <span style={{ fontSize: 11, color: colors.textMuted, minWidth: 88 }}>
              进度 {progress.done}/{progress.total}{progress.currentIndex ? ` · 第 ${progress.currentIndex} 个` : ''}
            </span>
            <Progress
              percent={progress.total ? Math.round((progress.done / progress.total) * 100) : 0}
              size="small"
              strokeColor={colors.primary}
              showInfo={false}
              style={{ flex: 1, margin: 0 }}
            />
          </div>
        )}

        {finalAlert && <div style={{ marginTop: 8 }}>{finalAlert}</div>}
      </div>

      {/* Tab 导航栏（只渲染头部，内容区由下方 flex 面板独立控制） */}
      <div style={{ borderBottom: `1px solid ${colors.border}`, flexShrink: 0 }}>
        <Tabs
          className="nav-only-tabs"
          activeKey={activeKey}
          onChange={onTabChange}
          tabBarStyle={{ margin: '0 16px', marginBottom: 0 }}
          items={[
            { key: 'log',      label: `实时对话${cases.length > 0 ? ` (${cases.length})` : ''}` },
            { key: 'overview', label: '规则总览' },
            { key: 'detail',   label: '用例明细' },
          ]}
        />
      </div>

      {/* 实时对话 — 独立 flex 子元素，直接 overflowY: auto */}
      <div style={{
        display: activeKey === 'log' ? 'block' : 'none',
        flex: 1, minHeight: 0, overflowY: 'auto',
        padding: '10px 16px 16px',
      }}>
        {cases.length === 0 ? (
          <Empty
            image={Empty.PRESENTED_IMAGE_SIMPLE}
            description={isLive ? '等待用例开始…' : '暂无对话记录'}
            style={{ marginTop: 60 }}
          />
        ) : (
          cases.map((c) => (
            <CaseBlock key={c.caseId} cs={c} snapshot={snapshots[c.caseId]} />
          ))
        )}
      </div>

      {/* 规则总览 */}
      <div style={{
        display: activeKey === 'overview' ? 'block' : 'none',
        flex: 1, minHeight: 0, overflowY: 'auto',
        padding: '10px 16px 16px',
      }}>
        <RuleOverview cases={cases} onSelectCase={(id) => onFocusCase(id)} />
      </div>

      {/* 用例明细 — CaseDetail 内部两栏各自独立滚动 */}
      <div style={{
        display: activeKey === 'detail' ? 'flex' : 'none',
        flex: 1, minHeight: 0, overflow: 'hidden',
        padding: '10px 16px 16px',
      }}>
        <CaseDetail cases={cases} snapshots={snapshots} focusCaseId={focusCaseId} />
      </div>
    </>
  )
}

function StatusBadge({ status, finalStatus }: { status: string; finalStatus: ReturnType<typeof useRunSession>['finalStatus'] }) {
  const effective = finalStatus ?? status
  const color = statusColors[effective] ?? colors.textMuted
  const label = statusLabels[effective] ?? effective
  const isRunning = effective === 'running' || effective === 'pending'
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
      {isRunning
        ? <span className="pulse-dot" style={{ background: color }} />
        : <span style={{ width: 8, height: 8, borderRadius: '50%', background: color, display: 'inline-block' }} />}
      <span style={{ fontSize: 13, fontWeight: 600, color }}>{label}</span>
    </div>
  )
}

function KpiItem({ label, value, subtitle, valueColor }: {
  label: string
  value: string
  subtitle?: string
  valueColor?: string
}) {
  return (
    <div style={{ minWidth: 120 }}>
      <div style={{ fontSize: 11, color: colors.textMuted, marginBottom: 2 }}>{label}</div>
      <div style={{ fontSize: 20, fontWeight: 600, lineHeight: 1.2, color: valueColor ?? colors.text }}>{value}</div>
      {subtitle && <div style={{ fontSize: 11, color: colors.textMuted, marginTop: 2 }}>{subtitle}</div>}
    </div>
  )
}
